summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ipsets.c47
-rw-r--r--ipsets.h4
-rw-r--r--main.c1
-rw-r--r--utils.c7
4 files changed, 55 insertions, 4 deletions
diff --git a/ipsets.c b/ipsets.c
index 93bde0d..280845b 100644
--- a/ipsets.c
+++ b/ipsets.c
@@ -427,13 +427,16 @@ fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
/* spawn ipsets */
list_for_each_entry(ipset, &state->ipsets, list)
{
- if (ipset->family != family ||
- (reload_set && !ipset->reload_set))
+ if (ipset->family != family)
continue;
if (ipset->external)
continue;
+ if (fw3_check_ipset(ipset) &&
+ (reload_set && !ipset->reload_set))
+ continue;
+
if (!exec)
{
exec = fw3_command_pipe(false, "ipset", "-exist", "-");
@@ -568,3 +571,43 @@ out:
return rv;
}
+
+void
+fw3_ipsets_update_run_state(enum fw3_family family, struct fw3_state *run_state,
+ struct fw3_state *cfg_state)
+{
+ struct fw3_ipset *ipset_run, *ipset_cfg;
+ bool in_cfg;
+
+ list_for_each_entry(ipset_run, &run_state->ipsets, list) {
+ if (ipset_run->family != family)
+ continue;
+
+ in_cfg = false;
+
+ list_for_each_entry(ipset_cfg, &cfg_state->ipsets, list) {
+ if (ipset_cfg->family != family)
+ continue;
+
+ if (strlen(ipset_run->name) ==
+ strlen(ipset_cfg->name) &&
+ !strcmp(ipset_run->name, ipset_cfg->name)) {
+ in_cfg = true;
+ break;
+ }
+ }
+
+ /* If a set is found in run_state, but not in cfg_state then the
+ * set has been deleted/renamed. Set reload_set to true to force
+ * the old set to be destroyed in the "stop" fase of the reload.
+ * If the set is found, then copy the reload_set value from the
+ * configuration state. This ensures that the elements are
+ * always updated according to the configuration, and not the
+ * runtime state (which the user might have forgotten).
+ */
+ if (!in_cfg)
+ ipset_run->reload_set = true;
+ else
+ ipset_run->reload_set = ipset_cfg->reload_set;
+ }
+}
diff --git a/ipsets.h b/ipsets.h
index fec79f8..76078d4 100644
--- a/ipsets.h
+++ b/ipsets.h
@@ -37,6 +37,10 @@ struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name);
bool fw3_check_ipset(struct fw3_ipset *set);
+void
+fw3_ipsets_update_run_state(enum fw3_family family, struct fw3_state *run_state,
+ struct fw3_state *cfg_state);
+
static inline void fw3_free_ipset(struct fw3_ipset *ipset)
{
list_del(&ipset->list);
diff --git a/main.c b/main.c
index 8d9a2e8..7ad00b4 100644
--- a/main.c
+++ b/main.c
@@ -354,6 +354,7 @@ reload(void)
fw3_ipt_close(handle);
}
+ fw3_ipsets_update_run_state(family, run_state, cfg_state);
fw3_destroy_ipsets(run_state, family, true);
family_set(run_state, family, false);
diff --git a/utils.c b/utils.c
index 147acf8..b465878 100644
--- a/utils.c
+++ b/utils.c
@@ -586,8 +586,11 @@ write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
uci_set(ctx, &ptr);
ptr.o = NULL;
- ptr.option = "reload_set";
- ptr.value = s->reload_set ? "true" : "false";
+ ptr.option = "family";
+ if (s->family == FW3_FAMILY_V4)
+ ptr.value = "ipv4";
+ else
+ ptr.value = "ipv6";
uci_set(ctx, &ptr);
ptr.o = NULL;