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>
re-ordered additional variables
dropped enum OPT_COMMENT & OPT_COUNTERS as unused
implemented exponential delay whilst waiting for ipset deletion/creation
fixed delays made firewall unresponsive for too long on reloads
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
const struct fw3_option fw3_ipset_opts[] = {
FW3_OPT("enabled", bool, ipset, enabled),
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),
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)
{
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)
if (ipset->external)
{
if (!*ipset->external)
INIT_LIST_HEAD(&ipset->datatypes);
INIT_LIST_HEAD(&ipset->entries);
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);
list_add_tail(&ipset->list, &state->ipsets);
if (ipset->hashsize > 0)
fw3_pr(" hashsize %u", ipset->hashsize);
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)
fw3_pr("\n");
list_for_each_entry(entry, &ipset->entries, list)
-fw3_create_ipsets(struct fw3_state *state)
+fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
+ bool reload_set)
+ unsigned int delay, tries;
bool exec = false;
struct fw3_ipset *ipset;
bool exec = false;
struct fw3_ipset *ipset;
/* spawn ipsets */
list_for_each_entry(ipset, &state->ipsets, list)
{
/* spawn ipsets */
list_for_each_entry(ipset, &state->ipsets, list)
{
+ if (ipset->family != family ||
+ (reload_set && !ipset->reload_set))
+ continue;
+
if (ipset->external)
continue;
if (ipset->external)
continue;
- /* 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;
list_for_each_entry(ipset, &state->ipsets, list)
{
if (ipset->external)
continue;
for (tries = 0; !fw3_check_ipset(ipset) && tries < 10; tries++)
for (tries = 0; !fw3_check_ipset(ipset) && tries < 10; tries++)
-fw3_destroy_ipsets(struct fw3_state *state)
+fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
+ bool reload_set)
+ unsigned int delay, tries;
bool exec = false;
struct fw3_ipset *ipset;
bool exec = false;
struct fw3_ipset *ipset;
+ if (state->disable_ipsets)
+ return;
+
/* destroy ipsets */
list_for_each_entry(ipset, &state->ipsets, list)
{
/* 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 (!exec)
{
exec = fw3_command_pipe(false, "ipset", "-exist", "-");
if (ipset->external)
continue;
if (ipset->external)
continue;
for (tries = 0; fw3_check_ipset(ipset) && tries < 10; tries++)
for (tries = 0; fw3_check_ipset(ipset) && tries < 10; tries++)
extern const struct fw3_option fw3_ipset_opts[];
void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p, struct blob_attr *a);
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);
struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name);
- 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);
if (complete)
fw3_flush_conntrack(NULL);
enum fw3_table table;
struct fw3_ipt_handle *handle;
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++)
{
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;
if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
continue;
+ fw3_destroy_ipsets(run_state, family, true);
+
family_set(run_state, family, false);
family_set(cfg_state, family, false);
family_set(run_state, family, false);
family_set(cfg_state, family, false);
if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
continue;
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]))
for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++)
{
if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table]))
struct list_head list;
bool enabled;
struct list_head list;
bool enabled;
+ bool reload_set;
+ bool counters;
+ bool comment;
+
const char *name;
enum fw3_family family;
const char *name;
enum fw3_family family;
ptr.value = s->name;
uci_set(ctx, &ptr);
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];
ptr.o = NULL;
ptr.option = "storage";
ptr.value = fw3_ipset_method_names[s->method];