summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--iptables/nft.c63
-rw-r--r--iptables/nft.h3
-rw-r--r--iptables/xtables-restore.c23
3 files changed, 76 insertions, 13 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 43b13deb..fd19ff55 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1801,19 +1801,13 @@ err:
return ret == 0 ? 1 : 0;
}
-static struct nft_chain *
-nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
+struct nft_chain *
+nft_chain_list_find(struct nft_handle *h, struct nft_chain_list *list,
+ const char *table, const char *chain)
{
- struct nft_chain_list *list;
struct nft_chain_list_iter *iter;
struct nft_chain *c;
- list = nft_chain_list_get(h);
- if (list == NULL) {
- DEBUGP("cannot allocate chain list\n");
- return NULL;
- }
-
iter = nft_chain_list_iter_create(list);
if (iter == NULL) {
DEBUGP("cannot allocate rule list iterator\n");
@@ -1833,13 +1827,29 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
if (strcmp(chain, chain_name) != 0)
goto next;
+ nft_chain_list_iter_destroy(iter);
return c;
next:
c = nft_chain_list_iter_next(iter);
}
+ nft_chain_list_iter_destroy(iter);
return NULL;
}
+static struct nft_chain *
+nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
+{
+ struct nft_chain_list *list;
+
+ list = nft_chain_list_get(h);
+ if (list == NULL) {
+ DEBUGP("cannot allocate chain list\n");
+ return NULL;
+ }
+
+ return nft_chain_list_find(h, list, table, chain);
+}
+
int nft_chain_user_rename(struct nft_handle *h,const char *chain,
const char *table, const char *newname)
{
@@ -2006,6 +2016,41 @@ err:
return ret == 0 ? 1 : 0;
}
+int nft_table_purge_chains(struct nft_handle *h, const char *this_table,
+ struct nft_chain_list *chain_list)
+{
+ struct nft_chain_list_iter *iter;
+ struct nft_chain *chain_obj;
+
+ iter = nft_chain_list_iter_create(chain_list);
+ if (iter == NULL) {
+ DEBUGP("cannot allocate rule list iterator\n");
+ return 0;
+ }
+
+ chain_obj = nft_chain_list_iter_next(iter);
+ while (chain_obj != NULL) {
+ const char *table =
+ nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE);
+
+ if (strcmp(this_table, table) != 0)
+ goto next;
+
+ if (nft_chain_builtin(chain_obj))
+ goto next;
+
+ if ( __nft_chain_del(h, chain_obj) < 0) {
+ if (errno != EBUSY)
+ return -1;
+ }
+next:
+ chain_obj = nft_chain_list_iter_next(iter);
+ }
+ nft_chain_list_iter_destroy(iter);
+
+ return 0;
+}
+
static inline int
match_different(const struct xt_entry_match *a,
const unsigned char *a_elems,
diff --git a/iptables/nft.h b/iptables/nft.h
index 00216681..f7ed0a38 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -17,12 +17,14 @@ void nft_fini(struct nft_handle *h);
* Operations with tables.
*/
struct nft_table;
+struct nft_chain_list;
int nft_table_add(struct nft_handle *h, const struct nft_table *t);
int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, const char *tablename, bool counters), bool counters);
bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_set_dormant(struct nft_handle *h, const char *table);
int nft_table_wake_dormant(struct nft_handle *h, const char *table);
+int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nft_chain_list *list);
/*
* Operations with chains.
@@ -32,6 +34,7 @@ struct nft_chain;
int nft_chain_add(struct nft_handle *h, const struct nft_chain *c);
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
struct nft_chain_list *nft_chain_dump(struct nft_handle *h);
+struct nft_chain *nft_chain_list_find(struct nft_handle *h, struct nft_chain_list *list, const char *table, const char *chain);
int nft_chain_save(struct nft_handle *h, struct nft_chain_list *list, const char *table);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index f6009776..9778a9f7 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -16,6 +16,7 @@
#include "libiptc/libiptc.h"
#include "xtables-multi.h"
#include "nft.h"
+#include <libnftables/chain.h>
#ifdef DEBUG
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
@@ -171,6 +172,8 @@ xtables_restore_main(int argc, char *argv[])
int in_table = 0, testing = 0;
const char *tablename = NULL;
const struct xtc_ops *ops = &iptc_ops;
+ struct nft_chain_list *chain_list;
+ struct nft_chain *chain_obj;
line = 0;
@@ -233,6 +236,10 @@ xtables_restore_main(int argc, char *argv[])
}
else in = stdin;
+ chain_list = nft_chain_dump(&h);
+ if (chain_list == NULL)
+ xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
+
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret = 0;
@@ -259,6 +266,10 @@ xtables_restore_main(int argc, char *argv[])
ret = 1;
}
in_table = 0;
+
+ /* Purge out unused chains in this table */
+ nft_table_purge_chains(&h, curtable, chain_list);
+
} else if ((buffer[0] == '*') && (!in_table)) {
/* New table */
char *table;
@@ -282,10 +293,6 @@ xtables_restore_main(int argc, char *argv[])
DEBUGP("Cleaning all chains of table '%s'\n",
table);
nft_rule_flush(&h, NULL, table);
-
- DEBUGP("Deleting all user-defined chains "
- "of table '%s'\n", table);
- nft_chain_user_del(&h, NULL, table);
}
ret = 1;
@@ -305,6 +312,14 @@ xtables_restore_main(int argc, char *argv[])
exit(1);
}
+ chain_obj = nft_chain_list_find(&h, chain_list,
+ curtable, chain);
+ /* This chain has been found, delete from list. Later
+ * on, unvisited chains will be purged out.
+ */
+ if (chain_obj != NULL)
+ nft_chain_list_del(chain_obj);
+
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid chain name `%s' "