[OpenWrt-Devel] firewall3: Improve ipset support
diff mbox series

Message ID 20190206202151.4624-1-kristian.evensen@gmail.com
State New
Headers show
Series
  • [OpenWrt-Devel] firewall3: Improve ipset support
Related show

Commit Message

Kristian Evensen Feb. 6, 2019, 8:21 p.m. UTC
This patch is an attempt at improving the ipset support in firewall3.
The following changes have been made:

* The enabled option did not work properly for ipsets, as it was not
checked on create/destroy of a set. After this commit, sets are only
created/destroyed if enabled is set to true.

* Add support for reloading, or recreating, ipsets on firewall reload.
By setting "reload_set" to true, the set will be destroyed and then
re-created when the firewall is reloaded. My use-case for "reload_set"
was to reset sets populated by dnsmasq, without having to restart the
firewall or resort to scripts.

* Add support for the counters and comment extensions. By setting
"counters" or "comment" to true, then counters or comments are added to
the set.

Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
---
 ipsets.c  | 35 +++++++++++++++++++++++++++++++++--
 ipsets.h  |  6 ++++--
 main.c    | 16 +++++++++++-----
 options.h |  4 ++++
 utils.c   |  5 +++++
 5 files changed, 57 insertions(+), 9 deletions(-)

Patch
diff mbox series

diff --git a/ipsets.c b/ipsets.c
index b73c3d2..49ba672 100644
--- a/ipsets.c
+++ b/ipsets.c
@@ -21,6 +21,9 @@ 
 
 const struct fw3_option fw3_ipset_opts[] = {
 	FW3_OPT("enabled",       bool,           ipset,     enabled),
+	FW3_OPT("reload_set",	 bool,           ipset,     reload_set),
+	FW3_OPT("counters",	 bool,           ipset,     counters),
+	FW3_OPT("comment",	 bool,           ipset,     comment),
 
 	FW3_OPT("name",          string,         ipset,     name),
 	FW3_OPT("family",        family,         ipset,     family),
@@ -56,6 +59,8 @@  enum ipset_optflag {
 	OPT_HASHSIZE  = (1 << 3),
 	OPT_MAXELEM   = (1 << 4),
 	OPT_FAMILY    = (1 << 5),
+	OPT_COUNTERS  = (1 << 6),
+	OPT_COMMENT   = (1 << 7),
 };
 
 struct ipset_type {
@@ -204,6 +209,10 @@  check_types(struct uci_element *e, struct fw3_ipset *ipset)
 static bool
 check_ipset(struct fw3_state *state, struct fw3_ipset *ipset, struct uci_element *e)
 {
+	if (!ipset->enabled) {
+		return false;
+	}
+
 	if (ipset->external)
 	{
 		if (!*ipset->external)
@@ -253,6 +262,9 @@  fw3_alloc_ipset(struct fw3_state *state)
 	INIT_LIST_HEAD(&ipset->entries);
 
 	ipset->enabled = true;
+	ipset->reload_set = false;
+	ipset->counters = false;
+	ipset->comment = false;
 	ipset->family  = FW3_FAMILY_V4;
 
 	list_add_tail(&ipset->list, &state->ipsets);
@@ -389,6 +401,12 @@  create_ipset(struct fw3_ipset *ipset, struct fw3_state *state)
 	if (ipset->hashsize > 0)
 		fw3_pr(" hashsize %u", ipset->hashsize);
 
+	if (ipset->counters)
+		fw3_pr(" counters");
+
+	if (ipset->comment)
+		fw3_pr(" comment");
+
 	fw3_pr("\n");
 
 	list_for_each_entry(entry, &ipset->entries, list)
@@ -398,7 +416,8 @@  create_ipset(struct fw3_ipset *ipset, struct fw3_state *state)
 }
 
 void
-fw3_create_ipsets(struct fw3_state *state)
+fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
+		  bool reload_set)
 {
 	int tries;
 	bool exec = false;
@@ -410,6 +429,10 @@  fw3_create_ipsets(struct fw3_state *state)
 	/* spawn ipsets */
 	list_for_each_entry(ipset, &state->ipsets, list)
 	{
+		if (ipset->family != family ||
+		    (reload_set && !ipset->reload_set))
+			continue;
+
 		if (ipset->external)
 			continue;
 
@@ -442,15 +465,23 @@  fw3_create_ipsets(struct fw3_state *state)
 }
 
 void
-fw3_destroy_ipsets(struct fw3_state *state)
+fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
+		   bool reload_set)
 {
 	int tries;
 	bool exec = false;
 	struct fw3_ipset *ipset;
 
+	if (state->disable_ipsets)
+		return;
+
 	/* destroy ipsets */
 	list_for_each_entry(ipset, &state->ipsets, list)
 	{
+		if (ipset->family != family ||
+		    (reload_set && !ipset->reload_set))
+			continue;
+
 		if (!exec)
 		{
 			exec = fw3_command_pipe(false, "ipset", "-exist", "-");
diff --git a/ipsets.h b/ipsets.h
index 2ba862d..fec79f8 100644
--- a/ipsets.h
+++ b/ipsets.h
@@ -28,8 +28,10 @@ 
 extern const struct fw3_option fw3_ipset_opts[];
 
 void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p, struct blob_attr *a);
-void fw3_create_ipsets(struct fw3_state *state);
-void fw3_destroy_ipsets(struct fw3_state *state);
+void fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
+		       bool reload_set);
+void fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
+			bool reload_set);
 
 struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name);
 
diff --git a/main.c b/main.c
index 1410fef..8d9a2e8 100644
--- a/main.c
+++ b/main.c
@@ -224,8 +224,10 @@  stop(bool complete)
 		rv = 0;
 	}
 
-	if (run_state)
-		fw3_destroy_ipsets(run_state);
+	if (run_state) {
+		for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++)
+			fw3_destroy_ipsets(run_state, family, false);
+	}
 
 	if (complete)
 		fw3_flush_conntrack(NULL);
@@ -244,11 +246,11 @@  start(void)
 	enum fw3_table table;
 	struct fw3_ipt_handle *handle;
 
-	if (!print_family)
-		fw3_create_ipsets(cfg_state);
-
 	for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++)
 	{
+		if (!print_family)
+			fw3_create_ipsets(cfg_state, family, false);
+
 		if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
 			continue;
 
@@ -352,6 +354,8 @@  reload(void)
 			fw3_ipt_close(handle);
 		}
 
+		fw3_destroy_ipsets(run_state, family, true);
+
 		family_set(run_state, family, false);
 		family_set(cfg_state, family, false);
 
@@ -359,6 +363,8 @@  start:
 		if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
 			continue;
 
+		fw3_create_ipsets(cfg_state, family, true);
+
 		for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++)
 		{
 			if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table]))
diff --git a/options.h b/options.h
index a75cfa3..cffc01c 100644
--- a/options.h
+++ b/options.h
@@ -501,6 +501,10 @@  struct fw3_ipset
 	struct list_head list;
 
 	bool enabled;
+	bool reload_set;
+	bool counters;
+	bool comment;
+
 	const char *name;
 	enum fw3_family family;
 
diff --git a/utils.c b/utils.c
index 7f09787..cd5e7de 100644
--- a/utils.c
+++ b/utils.c
@@ -585,6 +585,11 @@  write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
 	ptr.value  = s->name;
 	uci_set(ctx, &ptr);
 
+	ptr.o      = NULL;
+	ptr.option = "reload_set";
+	ptr.value  = s->reload_set ? "true" : "false";
+	uci_set(ctx, &ptr);
+
 	ptr.o      = NULL;
 	ptr.option = "storage";
 	ptr.value  = fw3_ipset_method_names[s->method];