]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables: purge out user-define chains from the kernel
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 20 Jan 2013 21:32:43 +0000 (22:32 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 30 Dec 2013 22:50:23 +0000 (23:50 +0100)
xtables-restore has to purge out user-defined chains that are
not defined in the configuration file.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
iptables/nft.c
iptables/nft.h
iptables/xtables-restore.c

index 43b13debea596e07173e990d1147122cadd80e9c..fd19ff5502b040d253ce9b81fca55c4a5a5ce147 100644 (file)
@@ -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,
index 00216681e09577f54e852edd1db7f0644b4d8b27..f7ed0a388da2276685dd7660f8de1bb7782d1190 100644 (file)
@@ -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);
index f6009776cd1eecf12d59ef750ee4bdcffac22023..9778a9f7b656ee0aa66094352eb0278428c73f2f 100644 (file)
@@ -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' "