From: Jo-Philipp Wich <jow@openwrt.org>
Date: Tue, 19 Feb 2013 23:58:02 +0000 (+0100)
Subject: rework ipset removal logic to only purge sets that are not in use by any family
X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=bb6873d86322a66bc01fc4195512ba5d2c78bddb;p=oweals%2Ffirewall3.git

rework ipset removal logic to only purge sets that are not in use by any family
---

diff --git a/ipsets.c b/ipsets.c
index ab86133..5e0d61f 100644
--- a/ipsets.c
+++ b/ipsets.c
@@ -266,7 +266,7 @@ create_ipset(struct fw3_ipset *ipset)
 	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]);
@@ -328,37 +328,69 @@ 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);
+
+	if (!statefile)
+		return;
 
-	if (statefile)
+	list_for_each_entry(e, statefile, list)
 	{
-		info("Destroying ipsets ...");
+		if (e->type != FW3_TYPE_IPSET)
+			continue;
 
-		list_for_each_entry(e, statefile, list)
-		{
-			if (e->type != FW3_TYPE_IPSET)
-				continue;
+		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);
 
-			info(" * %s", e->name);
+		if ((s = fw3_lookup_ipset(state, e->name)) != NULL)
+			s->flags = e->flags[0];
+
+		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);
diff --git a/ipsets.h b/ipsets.h
index 49c6e66..a169979 100644
--- a/ipsets.h
+++ b/ipsets.h
@@ -39,9 +39,8 @@ struct fw3_ipset_settype {
 };
 
 void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p);
-void fw3_create_ipsets(struct fw3_state *state);
-
-void fw3_destroy_ipsets(struct list_head *statefile);
+void fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile);
+void fw3_destroy_ipsets(struct fw3_state *state, struct list_head *statefile);
 
 void fw3_free_ipset(struct fw3_ipset *ipset);
 
diff --git a/main.c b/main.c
index 3ef7243..23c1497 100644
--- a/main.c
+++ b/main.c
@@ -220,12 +220,9 @@ stop(struct fw3_state *state, bool complete, bool restart)
 		rv = 0;
 	}
 
-	if (!restart &&
-	    !family_loaded(state, FW3_FAMILY_V4) &&
-	    !family_loaded(state, FW3_FAMILY_V6) &&
-	    fw3_command_pipe(false, "ipset", "-exist", "-"))
+	if (!restart && fw3_command_pipe(false, "ipset", "-exist", "-"))
 	{
-		fw3_destroy_ipsets(statefile);
+		fw3_destroy_ipsets(state, statefile);
 		fw3_command_close();
 	}
 
@@ -249,7 +246,7 @@ start(struct fw3_state *state, bool restart)
 	if (!print_rules && !restart &&
 	    fw3_command_pipe(false, "ipset", "-exist", "-"))
 	{
-		fw3_create_ipsets(state);
+		fw3_create_ipsets(state, statefile);
 		fw3_command_close();
 	}
 
diff --git a/utils.c b/utils.c
index 9b62789..1ba25fd 100644
--- a/utils.c
+++ b/utils.c
@@ -435,6 +435,9 @@ fw3_write_statefile(void *state)
 		if (i->external && *i->external)
 			continue;
 
+		if (!i->flags)
+			continue;
+
 		fprintf(sf, "%u %s %u\n", FW3_TYPE_IPSET, i->name, i->flags);
 	}