rework ipset removal logic to only purge sets that are not in use by any family
[project/firewall3.git] / ipsets.c
index 215be73..5e0d61f 100644 (file)
--- a/ipsets.c
+++ b/ipsets.c
@@ -263,16 +263,10 @@ create_ipset(struct fw3_ipset *ipset)
                "set",
        };
 
-       const char *families[] = {
-               "(bug)",
-               "inet",
-               "inet6",
-       };
-
        if (ipset->external && *ipset->external)
                return;
 
-       info(" * %s", ipset->name);
+       info("Creating ipset %s", ipset->name);
 
        first = true;
        fw3_pr("create %s %s", ipset->name, methods[ipset->method]);
@@ -317,7 +311,7 @@ create_ipset(struct fw3_ipset *ipset)
        }
 
        if (ipset->family != FW3_FAMILY_ANY)
-               fw3_pr(" family %s", families[ipset->family]);
+               fw3_pr(" family inet%s", (ipset->family == FW3_FAMILY_V4) ? "" : "6");
 
        if (ipset->timeout > 0)
                fw3_pr(" timeout %u", ipset->timeout);
@@ -334,38 +328,73 @@ create_ipset(struct fw3_ipset *ipset)
        fw3_pr("\n");
 }
 
+static bool
+ipset_loaded(struct list_head *statefile, const char *name)
+{
+       struct fw3_statefile_entry *e;
+       int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6);
+
+       if (!statefile)
+               return false;
+
+       list_for_each_entry(e, statefile, list)
+       {
+               if (e->type != FW3_TYPE_IPSET)
+                       continue;
+
+               if (!strcmp(e->name, name) && (e->flags[0] & mask))
+                       return true;
+       }
+
+       return false;
+}
+
 void
-fw3_create_ipsets(struct fw3_state *state)
+fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile)
 {
        struct fw3_ipset *ipset;
 
        if (state->disable_ipsets)
                return;
 
-       info("Initializing ipsets ...");
-
        list_for_each_entry(ipset, &state->ipsets, list)
-               create_ipset(ipset);
+               if (!ipset_loaded(statefile, ipset->name))
+                       create_ipset(ipset);
 
        fw3_pr("quit\n");
 }
 
 void
-fw3_destroy_ipsets(struct list_head *statefile)
+fw3_destroy_ipsets(struct fw3_state *state, struct list_head *statefile)
 {
+       struct fw3_ipset *s;
        struct fw3_statefile_entry *e;
+       int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6);
 
-       info("Destroying ipsets ...");
+       if (!statefile)
+               return;
 
        list_for_each_entry(e, statefile, list)
        {
                if (e->type != FW3_TYPE_IPSET)
                        continue;
 
-               info(" * %s", e->name);
+               if (!hasbit(state->defaults.flags, FW3_FAMILY_V4))
+                       delbit(e->flags[0], FW3_FAMILY_V4);
+
+               if (!hasbit(state->defaults.flags, FW3_FAMILY_V6))
+                       delbit(e->flags[0], FW3_FAMILY_V6);
+
+               if ((s = fw3_lookup_ipset(state, e->name)) != NULL)
+                       s->flags = e->flags[0];
 
-               fw3_pr("flush %s\n", e->name);
-               fw3_pr("destroy %s\n", e->name);
+               if (!(e->flags[0] & mask))
+               {
+                       info("Deleting ipset %s", e->name);
+
+                       fw3_pr("flush %s\n", e->name);
+                       fw3_pr("destroy %s\n", e->name);
+               }
        }
 }