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),
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)
INIT_LIST_HEAD(&ipset->datatypes);
INIT_LIST_HEAD(&ipset->entries);
- ipset->enabled = true;
- ipset->family = FW3_FAMILY_V4;
+ ipset->comment = false;
+ ipset->counters = false;
+ ipset->enabled = true;
+ ipset->family = FW3_FAMILY_V4;
+ ipset->reload_set = false;
list_add_tail(&ipset->list, &state->ipsets);
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)
}
void
-fw3_create_ipsets(struct fw3_state *state)
+fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
+ bool reload_set)
{
- int tries;
+ unsigned int delay, tries;
bool exec = false;
struct fw3_ipset *ipset;
/* spawn ipsets */
list_for_each_entry(ipset, &state->ipsets, list)
{
+ 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", "-");
fw3_command_close();
}
- /* wait for ipsets to appear */
+ /* wait a little expontially for ipsets to appear */
list_for_each_entry(ipset, &state->ipsets, list)
{
if (ipset->external)
continue;
+ delay = 5;
for (tries = 0; !fw3_check_ipset(ipset) && tries < 10; tries++)
- usleep(50000);
+ usleep(delay<<1);
}
}
void
-fw3_destroy_ipsets(struct fw3_state *state)
+fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
+ bool reload_set)
{
- int tries;
+ unsigned int delay, 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", "-");
if (ipset->external)
continue;
+ delay = 5;
for (tries = 0; fw3_check_ipset(ipset) && tries < 10; tries++)
- usleep(50000);
+ usleep(delay<<1);
}
}
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;
+ }
+}