diff options
Diffstat (limited to 'iptables')
-rw-r--r-- | iptables/nft-cache.c | 76 | ||||
-rw-r--r-- | iptables/nft-cache.h | 6 | ||||
-rw-r--r-- | iptables/nft.c | 35 | ||||
-rw-r--r-- | iptables/xtables-restore.c | 4 | ||||
-rw-r--r-- | iptables/xtables-save.c | 2 |
5 files changed, 79 insertions, 44 deletions
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c index 822d6f20..64dcda57 100644 --- a/iptables/nft-cache.c +++ b/iptables/nft-cache.c @@ -153,7 +153,8 @@ err: } static int fetch_chain_cache(struct nft_handle *h, - const struct builtin_table *t) + const struct builtin_table *t, + const char *chain) { struct nftnl_chain_list_cb_data d = { .h = h, @@ -183,8 +184,24 @@ static int fetch_chain_cache(struct nft_handle *h, return -1; } - nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, - NLM_F_DUMP, h->seq); + if (t && chain) { + struct nftnl_chain *c = nftnl_chain_alloc(); + + if (!c) + return -1; + + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, + h->family, NLM_F_ACK, + h->seq); + nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, t->name); + nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain); + nftnl_chain_nlmsg_build_payload(nlh, c); + nftnl_chain_free(c); + } else { + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, + h->family, NLM_F_DUMP, + h->seq); + } ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d); if (ret < 0 && errno == EINTR) @@ -247,13 +264,23 @@ static int nft_rule_list_update(struct nftnl_chain *c, void *data) return 0; } -static int fetch_rule_cache(struct nft_handle *h, const struct builtin_table *t) +static int fetch_rule_cache(struct nft_handle *h, + const struct builtin_table *t, const char *chain) { int i; - if (t) - return nftnl_chain_list_foreach(h->cache->table[t->type].chains, - nft_rule_list_update, h); + if (t) { + struct nftnl_chain_list *list; + struct nftnl_chain *c; + + list = h->cache->table[t->type].chains; + + if (chain) { + c = nftnl_chain_list_lookup_byname(list, chain); + return nft_rule_list_update(c, h); + } + return nftnl_chain_list_foreach(list, nft_rule_list_update, h); + } for (i = 0; i < NFT_TABLE_MAX; i++) { enum nft_table_type type = h->tables[i].type; @@ -268,8 +295,9 @@ static int fetch_rule_cache(struct nft_handle *h, const struct builtin_table *t) return 0; } -static void __nft_build_cache(struct nft_handle *h, enum nft_cache_level level, - const struct builtin_table *t) +static void +__nft_build_cache(struct nft_handle *h, enum nft_cache_level level, + const struct builtin_table *t, const char *chain) { uint32_t genid_start, genid_stop; @@ -288,12 +316,12 @@ retry: break; /* fall through */ case NFT_CL_TABLES: - fetch_chain_cache(h, t); + fetch_chain_cache(h, t, chain); if (level == NFT_CL_CHAINS) break; /* fall through */ case NFT_CL_CHAINS: - fetch_rule_cache(h, t); + fetch_rule_cache(h, t, chain); if (level == NFT_CL_RULES) break; /* fall through */ @@ -307,7 +335,7 @@ retry: goto retry; } - if (!t) + if (!t && !chain) h->cache_level = level; else if (h->cache_level < NFT_CL_TABLES) h->cache_level = NFT_CL_TABLES; @@ -315,10 +343,18 @@ retry: h->nft_genid = genid_start; } -void nft_build_cache(struct nft_handle *h) +void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c) { - if (h->cache_level < NFT_CL_RULES) - __nft_build_cache(h, NFT_CL_RULES, NULL); + const struct builtin_table *t; + const char *table, *chain; + + if (!c) + return __nft_build_cache(h, NFT_CL_RULES, NULL, NULL); + + table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + t = nft_table_builtin_find(h, table); + __nft_build_cache(h, NFT_CL_RULES, t, chain); } void nft_fake_cache(struct nft_handle *h) @@ -417,7 +453,7 @@ void nft_rebuild_cache(struct nft_handle *h) __nft_flush_cache(h); h->cache_level = NFT_CL_NONE; - __nft_build_cache(h, level, NULL); + __nft_build_cache(h, level, NULL, NULL); } void nft_release_cache(struct nft_handle *h) @@ -428,13 +464,13 @@ void nft_release_cache(struct nft_handle *h) struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) { - __nft_build_cache(h, NFT_CL_TABLES, NULL); + __nft_build_cache(h, NFT_CL_TABLES, NULL, NULL); return h->cache->tables; } -struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, - const char *table) +struct nftnl_chain_list * +nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain) { const struct builtin_table *t; @@ -442,7 +478,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, if (!t) return NULL; - __nft_build_cache(h, NFT_CL_CHAINS, t); + __nft_build_cache(h, NFT_CL_CHAINS, t, chain); return h->cache->table[t->type].chains; } diff --git a/iptables/nft-cache.h b/iptables/nft-cache.h index 423c6516..793a85f4 100644 --- a/iptables/nft-cache.h +++ b/iptables/nft-cache.h @@ -4,14 +4,14 @@ struct nft_handle; void nft_fake_cache(struct nft_handle *h); -void nft_build_cache(struct nft_handle *h); +void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c); 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); void flush_rule_cache(struct nftnl_chain *c); -struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, - const char *table); +struct nftnl_chain_list * +nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain); struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h); #endif /* _NFT_CACHE_H_ */ diff --git a/iptables/nft.c b/iptables/nft.c index 94fabd78..775582aa 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -709,7 +709,7 @@ nft_chain_builtin_find(const struct builtin_table *t, const char *chain) static void nft_chain_builtin_init(struct nft_handle *h, const struct builtin_table *table) { - struct nftnl_chain_list *list = nft_chain_list_get(h, table->name); + struct nftnl_chain_list *list = nft_chain_list_get(h, table->name, NULL); struct nftnl_chain *c; int i; @@ -1178,7 +1178,7 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, if (h->family == NFPROTO_BRIDGE) { c = nft_chain_find(h, table, chain); if (c && !nft_chain_builtin(c)) - nft_build_cache(h); + nft_build_cache(h, c); } nft_fn = nft_rule_append; @@ -1405,9 +1405,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) struct nftnl_chain *c; int ret = 0; - nft_build_cache(h); - - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, NULL); if (!list) return 0; @@ -1417,6 +1415,7 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) c = nftnl_chain_list_iter_next(iter); while (c) { + nft_build_cache(h, c); ret = nft_chain_save_rules(h, c, format); if (ret != 0) break; @@ -1468,7 +1467,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, nft_fn = nft_rule_flush; - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list == NULL) { ret = 1; goto err; @@ -1533,7 +1532,7 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list) nftnl_chain_list_add(c, list); @@ -1573,7 +1572,7 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list) nftnl_chain_list_add(c, list); @@ -1607,7 +1606,7 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data) /* This triggers required policy rule deletion. */ if (h->family == NFPROTO_BRIDGE) - nft_build_cache(h); + nft_build_cache(h, c); /* XXX This triggers a fast lookup from the kernel. */ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); @@ -1632,7 +1631,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, nft_fn = nft_chain_user_del; - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list == NULL) return 0; @@ -1660,7 +1659,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain) { struct nftnl_chain_list *list; - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list == NULL) return NULL; @@ -1890,7 +1889,7 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen struct nftnl_rule_iter *iter; bool found = false; - nft_build_cache(h); + nft_build_cache(h, c); if (rulenum >= 0) /* Delete by rule number case */ @@ -2198,7 +2197,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, if (!nft_is_table_compatible(h, table)) xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table); - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (!list) return 0; @@ -2299,7 +2298,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, if (!nft_is_table_compatible(h, table)) xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table); - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (!list) return 0; @@ -2717,7 +2716,7 @@ int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, else return 0; - nft_build_cache(h); + nft_build_cache(h, c); nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval); return 1; @@ -2983,7 +2982,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, struct nftnl_chain *c; int ret = 0; - list = nft_chain_list_get(h, table); + list = nft_chain_list_get(h, table, chain); if (list == NULL) goto err; @@ -3056,7 +3055,7 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) enum nf_inet_hooks hook; int prio; - nft_build_cache(h); + nft_build_cache(h, c); if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL)) return -1; @@ -3089,7 +3088,7 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) { struct nftnl_chain_list *clist; - clist = nft_chain_list_get(h, tablename); + clist = nft_chain_list_get(h, tablename, NULL); if (clist == NULL) return false; diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index 7641955d..4f6d324b 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -63,7 +63,7 @@ static struct nftnl_chain_list *get_chain_list(struct nft_handle *h, { struct nftnl_chain_list *chain_list; - chain_list = nft_chain_list_get(h, table); + chain_list = nft_chain_list_get(h, table, NULL); if (chain_list == NULL) xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n"); @@ -100,7 +100,7 @@ void xtables_restore_parse(struct nft_handle *h, if (!h->noflush) nft_fake_cache(h); else - nft_build_cache(h); + nft_build_cache(h, NULL); /* Grab standard input. */ while (fgets(buffer, sizeof(buffer), p->in)) { diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c index 3741888f..e234425d 100644 --- a/iptables/xtables-save.c +++ b/iptables/xtables-save.c @@ -83,7 +83,7 @@ __do_output(struct nft_handle *h, const char *tablename, void *data) return 0; } - chain_list = nft_chain_list_get(h, tablename); + chain_list = nft_chain_list_get(h, tablename, NULL); if (!chain_list) return 0; |