summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--iptables/nft.c82
-rw-r--r--iptables/nft.h3
-rw-r--r--iptables/xtables-restore.c5
-rw-r--r--iptables/xtables-save.c2
4 files changed, 55 insertions, 37 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 1a920dce..45f203af 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -671,7 +671,7 @@ static void nft_chain_builtin_init(struct nft_handle *h,
struct builtin_table *table)
{
int i;
- struct nftnl_chain_list *list = nft_chain_dump(h, NULL);
+ struct nftnl_chain_list *list = nft_chain_dump(h);
struct nftnl_chain *c;
/* Initialize built-in chains if they don't exist yet */
@@ -684,8 +684,6 @@ static void nft_chain_builtin_init(struct nft_handle *h,
nft_chain_builtin_add(h, table, &table->chains[i]);
}
-
- nftnl_chain_list_free(list);
}
static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
@@ -762,8 +760,35 @@ static void flush_rule_cache(struct nft_handle *h)
h->rule_cache = NULL;
}
+static int __flush_chain_cache(struct nftnl_chain *c, void *data)
+{
+ const char *tablename = data;
+
+ if (!strcmp(nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), tablename)) {
+ nftnl_chain_list_del(c);
+ nftnl_chain_free(c);
+ }
+
+ return 0;
+}
+
+static void flush_chain_cache(struct nft_handle *h, const char *tablename)
+{
+ if (!h->chain_cache)
+ return;
+
+ if (tablename) {
+ nftnl_chain_list_foreach(h->chain_cache, __flush_chain_cache,
+ (void *)tablename);
+ } else {
+ nftnl_chain_list_free(h->chain_cache);
+ h->chain_cache = NULL;
+ }
+}
+
void nft_fini(struct nft_handle *h)
{
+ flush_chain_cache(h, NULL);
flush_rule_cache(h);
mnl_socket_close(h->nl);
}
@@ -1161,14 +1186,15 @@ err:
return MNL_CB_OK;
}
-static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h,
- const char *tablename)
+static struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
struct nftnl_chain_list *list;
int ret;
+ if (h->chain_cache)
+ return h->chain_cache;
retry:
list = nftnl_chain_list_alloc();
if (list == NULL) {
@@ -1178,15 +1204,6 @@ retry:
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
- if (tablename) {
- struct nftnl_chain *t = nftnl_chain_alloc();
-
- if (t) {
- nftnl_chain_set(t, NFTNL_CHAIN_TABLE, tablename);
- nftnl_chain_nlmsg_build_payload(nlh, t);
- nftnl_chain_free(t);
- }
- }
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list);
if (ret < 0 && errno == EINTR) {
@@ -1195,12 +1212,14 @@ retry:
goto retry;
}
+ h->chain_cache = list;
+
return list;
}
-struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h, const char *tablename)
+struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h)
{
- return nftnl_chain_list_get(h, tablename);
+ return nftnl_chain_list_get(h);
}
static const char *policy_name[NF_ACCEPT+1] = {
@@ -1254,7 +1273,6 @@ next:
}
nftnl_chain_list_iter_destroy(iter);
- nftnl_chain_list_free(list);
return 1;
}
@@ -1427,7 +1445,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
nft_fn = nft_rule_flush;
- list = nftnl_chain_list_get(h, table);
+ list = nftnl_chain_list_get(h);
if (list == NULL) {
ret = 0;
goto err;
@@ -1461,8 +1479,6 @@ next:
nftnl_chain_list_iter_destroy(iter);
flush_rule_cache(h);
err:
- nftnl_chain_list_free(list);
-
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
@@ -1487,6 +1503,10 @@ 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);
+ nft_chain_dump(h);
+
+ nftnl_chain_list_add(c, h->chain_cache);
+
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
@@ -1506,7 +1526,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
nft_fn = nft_chain_user_del;
- list = nftnl_chain_list_get(h, table);
+ list = nftnl_chain_list_get(h);
if (list == NULL)
goto err;
@@ -1537,6 +1557,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl
break;
deleted_ctr++;
+ nftnl_chain_list_del(c);
if (chain != NULL)
break;
@@ -1595,7 +1616,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{
struct nftnl_chain_list *list;
- list = nftnl_chain_list_get(h, table);
+ list = nftnl_chain_list_get(h);
if (list == NULL)
return NULL;
@@ -1761,6 +1782,8 @@ static int __nft_table_flush(struct nft_handle *h, const char *table)
batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t);
+ flush_chain_cache(h, table);
+
return 0;
}
@@ -2132,7 +2155,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
return 1;
}
- list = nft_chain_dump(h, table);
+ list = nft_chain_dump(h);
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
@@ -2186,8 +2209,6 @@ next:
nftnl_chain_list_iter_destroy(iter);
err:
- nftnl_chain_list_free(list);
-
return 1;
}
@@ -2256,7 +2277,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 1;
- list = nft_chain_dump(h, table);
+ list = nft_chain_dump(h);
/* Dump policies and custom chains first */
if (!rulenum)
@@ -2291,8 +2312,6 @@ next:
nftnl_chain_list_iter_destroy(iter);
err:
- nftnl_chain_list_free(list);
-
return ret;
}
@@ -2376,6 +2395,7 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_USER_DEL:
+ break;
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
@@ -2786,7 +2806,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 0;
- list = nftnl_chain_list_get(h, table);
+ list = nftnl_chain_list_get(h);
if (list == NULL)
goto err;
@@ -2931,7 +2951,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename
struct nftnl_chain *chain;
int ret = 0;
- list = nftnl_chain_list_get(h, tablename);
+ list = nftnl_chain_list_get(h);
if (list == NULL)
return -1;
@@ -2952,7 +2972,7 @@ next:
}
nftnl_chain_list_iter_destroy(iter);
- nftnl_chain_list_free(list);
+
return ret;
}
diff --git a/iptables/nft.h b/iptables/nft.h
index 9311662b..72c2fdc5 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -36,6 +36,7 @@ struct nft_handle {
struct list_head err_list;
struct nft_family_ops *ops;
struct builtin_table *tables;
+ struct nftnl_chain_list *chain_cache;
struct nftnl_rule_list *rule_cache;
bool restore;
int8_t config_done;
@@ -73,7 +74,7 @@ int nft_table_flush(struct nft_handle *h, const char *table);
struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
-struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h, const char *table);
+struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h);
struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 6cd4de23..3270ec02 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -169,7 +169,7 @@ static struct nftnl_chain_list *get_chain_list(struct nft_handle *h)
{
struct nftnl_chain_list *chain_list;
- chain_list = nft_chain_dump(h, NULL);
+ chain_list = nft_chain_dump(h);
if (chain_list == NULL)
xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
@@ -449,9 +449,6 @@ void xtables_restore_parse(struct nft_handle *h,
xt_params->program_name, line + 1);
exit(1);
}
-
- if (chain_list)
- nftnl_chain_list_free(chain_list);
}
static int
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index be98b835..8bcc31fd 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -57,7 +57,7 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
return 0;
}
- chain_list = nft_chain_dump(h, tablename);
+ chain_list = nft_chain_dump(h);
time_t now = time(NULL);