Skip to content

Commit 509e673

Browse files
kristrevldir-EDB0
authored andcommitted
firewall3: Improve ipset support
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 <[email protected]> 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 <[email protected]>
1 parent de94097 commit 509e673

File tree

5 files changed

+64
-16
lines changed

5 files changed

+64
-16
lines changed

ipsets.c

+40-9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
const struct fw3_option fw3_ipset_opts[] = {
2323
FW3_OPT("enabled", bool, ipset, enabled),
24+
FW3_OPT("reload_set", bool, ipset, reload_set),
25+
FW3_OPT("counters", bool, ipset, counters),
26+
FW3_OPT("comment", bool, ipset, comment),
2427

2528
FW3_OPT("name", string, ipset, name),
2629
FW3_OPT("family", family, ipset, family),
@@ -204,6 +207,10 @@ check_types(struct uci_element *e, struct fw3_ipset *ipset)
204207
static bool
205208
check_ipset(struct fw3_state *state, struct fw3_ipset *ipset, struct uci_element *e)
206209
{
210+
if (!ipset->enabled) {
211+
return false;
212+
}
213+
207214
if (ipset->external)
208215
{
209216
if (!*ipset->external)
@@ -252,8 +259,11 @@ fw3_alloc_ipset(struct fw3_state *state)
252259
INIT_LIST_HEAD(&ipset->datatypes);
253260
INIT_LIST_HEAD(&ipset->entries);
254261

255-
ipset->enabled = true;
256-
ipset->family = FW3_FAMILY_V4;
262+
ipset->comment = false;
263+
ipset->counters = false;
264+
ipset->enabled = true;
265+
ipset->family = FW3_FAMILY_V4;
266+
ipset->reload_set = false;
257267

258268
list_add_tail(&ipset->list, &state->ipsets);
259269

@@ -389,6 +399,12 @@ create_ipset(struct fw3_ipset *ipset, struct fw3_state *state)
389399
if (ipset->hashsize > 0)
390400
fw3_pr(" hashsize %u", ipset->hashsize);
391401

402+
if (ipset->counters)
403+
fw3_pr(" counters");
404+
405+
if (ipset->comment)
406+
fw3_pr(" comment");
407+
392408
fw3_pr("\n");
393409

394410
list_for_each_entry(entry, &ipset->entries, list)
@@ -398,9 +414,10 @@ create_ipset(struct fw3_ipset *ipset, struct fw3_state *state)
398414
}
399415

400416
void
401-
fw3_create_ipsets(struct fw3_state *state)
417+
fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
418+
bool reload_set)
402419
{
403-
int tries;
420+
unsigned int delay, tries;
404421
bool exec = false;
405422
struct fw3_ipset *ipset;
406423

@@ -410,6 +427,10 @@ fw3_create_ipsets(struct fw3_state *state)
410427
/* spawn ipsets */
411428
list_for_each_entry(ipset, &state->ipsets, list)
412429
{
430+
if (ipset->family != family ||
431+
(reload_set && !ipset->reload_set))
432+
continue;
433+
413434
if (ipset->external)
414435
continue;
415436

@@ -430,27 +451,36 @@ fw3_create_ipsets(struct fw3_state *state)
430451
fw3_command_close();
431452
}
432453

433-
/* wait for ipsets to appear */
454+
/* wait a little expontially for ipsets to appear */
434455
list_for_each_entry(ipset, &state->ipsets, list)
435456
{
436457
if (ipset->external)
437458
continue;
438459

460+
delay = 5;
439461
for (tries = 0; !fw3_check_ipset(ipset) && tries < 10; tries++)
440-
usleep(50000);
462+
usleep(delay<<1);
441463
}
442464
}
443465

444466
void
445-
fw3_destroy_ipsets(struct fw3_state *state)
467+
fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
468+
bool reload_set)
446469
{
447-
int tries;
470+
unsigned int delay, tries;
448471
bool exec = false;
449472
struct fw3_ipset *ipset;
450473

474+
if (state->disable_ipsets)
475+
return;
476+
451477
/* destroy ipsets */
452478
list_for_each_entry(ipset, &state->ipsets, list)
453479
{
480+
if (ipset->family != family ||
481+
(reload_set && !ipset->reload_set))
482+
continue;
483+
454484
if (!exec)
455485
{
456486
exec = fw3_command_pipe(false, "ipset", "-exist", "-");
@@ -477,8 +507,9 @@ fw3_destroy_ipsets(struct fw3_state *state)
477507
if (ipset->external)
478508
continue;
479509

510+
delay = 5;
480511
for (tries = 0; fw3_check_ipset(ipset) && tries < 10; tries++)
481-
usleep(50000);
512+
usleep(delay<<1);
482513
}
483514
}
484515

ipsets.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828
extern const struct fw3_option fw3_ipset_opts[];
2929

3030
void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p, struct blob_attr *a);
31-
void fw3_create_ipsets(struct fw3_state *state);
32-
void fw3_destroy_ipsets(struct fw3_state *state);
31+
void fw3_create_ipsets(struct fw3_state *state, enum fw3_family family,
32+
bool reload_set);
33+
void fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family,
34+
bool reload_set);
3335

3436
struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name);
3537

main.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,10 @@ stop(bool complete)
224224
rv = 0;
225225
}
226226

227-
if (run_state)
228-
fw3_destroy_ipsets(run_state);
227+
if (run_state) {
228+
for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++)
229+
fw3_destroy_ipsets(run_state, family, false);
230+
}
229231

230232
if (complete)
231233
fw3_flush_conntrack(NULL);
@@ -244,11 +246,11 @@ start(void)
244246
enum fw3_table table;
245247
struct fw3_ipt_handle *handle;
246248

247-
if (!print_family)
248-
fw3_create_ipsets(cfg_state);
249-
250249
for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++)
251250
{
251+
if (!print_family)
252+
fw3_create_ipsets(cfg_state, family, false);
253+
252254
if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
253255
continue;
254256

@@ -352,13 +354,17 @@ reload(void)
352354
fw3_ipt_close(handle);
353355
}
354356

357+
fw3_destroy_ipsets(run_state, family, true);
358+
355359
family_set(run_state, family, false);
356360
family_set(cfg_state, family, false);
357361

358362
start:
359363
if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6)
360364
continue;
361365

366+
fw3_create_ipsets(cfg_state, family, true);
367+
362368
for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++)
363369
{
364370
if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table]))

options.h

+4
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,10 @@ struct fw3_ipset
501501
struct list_head list;
502502

503503
bool enabled;
504+
bool reload_set;
505+
bool counters;
506+
bool comment;
507+
504508
const char *name;
505509
enum fw3_family family;
506510

utils.c

+5
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,11 @@ write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
585585
ptr.value = s->name;
586586
uci_set(ctx, &ptr);
587587

588+
ptr.o = NULL;
589+
ptr.option = "reload_set";
590+
ptr.value = s->reload_set ? "true" : "false";
591+
uci_set(ctx, &ptr);
592+
588593
ptr.o = NULL;
589594
ptr.option = "storage";
590595
ptr.value = fw3_ipset_method_names[s->method];

0 commit comments

Comments
 (0)