From 275a37dbf280bd471ebb2c673267c49a81071bbb Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 20 Feb 2013 21:05:45 +0100 Subject: [PATCH] rework runtime state tracking --- defaults.c | 35 ++++++++--------- defaults.h | 2 +- forwards.c | 4 +- ipsets.c | 101 +++++++++++++++++++++++------------------------- ipsets.h | 8 ++-- main.c | 57 +++++++++++---------------- options.h | 7 ++++ redirects.c | 6 +-- rules.c | 6 +-- utils.c | 126 +++++++++++++++++++++++++++++++++++------------------------- utils.h | 13 ++----- zones.c | 79 +++++++++++++++++++++++++------------ zones.h | 7 +++- 13 files changed, 243 insertions(+), 208 deletions(-) diff --git a/defaults.c b/defaults.c index 2d64695..0992f58 100644 --- a/defaults.c +++ b/defaults.c @@ -295,30 +295,29 @@ reset_policy(enum fw3_table table) void fw3_flush_rules(enum fw3_table table, enum fw3_family family, - bool pass2, struct list_head *statefile) + bool pass2, struct fw3_state *state) { - struct fw3_statefile_entry *e; + struct fw3_defaults *d = &state->running_defaults; - list_for_each_entry(e, statefile, list) + if (!hasbit(d->flags, family)) + return; + + if (!pass2) { - if (e->type != FW3_TYPE_DEFAULTS) - continue; + reset_policy(table); - if (!pass2) - { - reset_policy(table); + print_chains(table, family, "-D %s\n", state->running_defaults.flags, + toplevel_rules, ARRAY_SIZE(toplevel_rules)); - print_chains(table, family, "-D %s\n", e->flags[0], - toplevel_rules, ARRAY_SIZE(toplevel_rules)); + print_chains(table, family, "-F %s\n", state->running_defaults.flags, + default_chains, ARRAY_SIZE(default_chains)); + } + else + { + print_chains(table, family, "-X %s\n", state->running_defaults.flags, + default_chains, ARRAY_SIZE(default_chains)); - print_chains(table, family, "-F %s\n", e->flags[0], - default_chains, ARRAY_SIZE(default_chains)); - } - else - { - print_chains(table, family, "-X %s\n", e->flags[0], - default_chains, ARRAY_SIZE(default_chains)); - } + delbit(d->flags, family); } } diff --git a/defaults.h b/defaults.h index 17f9ba9..72f3eef 100644 --- a/defaults.h +++ b/defaults.h @@ -33,7 +33,7 @@ void fw3_print_default_tail_rules(enum fw3_table table, enum fw3_family family, struct fw3_state *state); void fw3_flush_rules(enum fw3_table table, enum fw3_family family, - bool pass2, struct list_head *statefile); + bool pass2, struct fw3_state *state); void fw3_flush_all(enum fw3_table table); diff --git a/forwards.c b/forwards.c index 1715abc..9abe4bf 100644 --- a/forwards.c +++ b/forwards.c @@ -60,14 +60,14 @@ fw3_load_forwards(struct fw3_state *state, struct uci_package *p) continue; } else if (forward->src.set && !forward->src.any && - !(forward->_src = fw3_lookup_zone(state, forward->src.name))) + !(forward->_src = fw3_lookup_zone(state, forward->src.name, false))) { warn_elem(e, "refers to not existing zone '%s'", forward->src.name); fw3_free_forward(forward); continue; } else if (forward->dest.set && !forward->dest.any && - !(forward->_dest = fw3_lookup_zone(state, forward->dest.name))) + !(forward->_dest = fw3_lookup_zone(state, forward->dest.name, false))) { warn_elem(e, "refers to not existing zone '%s'", forward->dest.name); fw3_free_forward(forward); diff --git a/ipsets.c b/ipsets.c index 5e0d61f..62ed131 100644 --- a/ipsets.c +++ b/ipsets.c @@ -184,6 +184,24 @@ check_types(struct uci_element *e, struct fw3_ipset *ipset) return false; } +struct fw3_ipset * +fw3_alloc_ipset(void) +{ + struct fw3_ipset *ipset; + + ipset = malloc(sizeof(*ipset)); + + if (!ipset) + return NULL; + + memset(ipset, 0, sizeof(*ipset)); + + INIT_LIST_HEAD(&ipset->datatypes); + INIT_LIST_HEAD(&ipset->iprange); + + return ipset; +} + void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) { @@ -203,16 +221,11 @@ fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) if (strcmp(s->type, "ipset")) continue; - ipset = malloc(sizeof(*ipset)); + ipset = fw3_alloc_ipset(); if (!ipset) continue; - memset(ipset, 0, sizeof(*ipset)); - - INIT_LIST_HEAD(&ipset->datatypes); - INIT_LIST_HEAD(&ipset->iprange); - fw3_parse_options(ipset, ipset_opts, ARRAY_SIZE(ipset_opts), s); if (!ipset->name || !*ipset->name) @@ -239,7 +252,7 @@ fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) static void -create_ipset(struct fw3_ipset *ipset) +create_ipset(struct fw3_ipset *ipset, struct fw3_state *state) { bool first = true; char s[INET6_ADDRSTRLEN]; @@ -326,31 +339,12 @@ create_ipset(struct fw3_ipset *ipset) fw3_pr(" hashsize %u", ipset->hashsize); fw3_pr("\n"); -} - -static bool -ipset_loaded(struct list_head *statefile, const char *name) -{ - struct fw3_statefile_entry *e; - int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); - - if (!statefile) - return false; - list_for_each_entry(e, statefile, list) - { - if (e->type != FW3_TYPE_IPSET) - continue; - - if (!strcmp(e->name, name) && (e->flags[0] & mask)) - return true; - } - - return false; + fw3_set_running(ipset, &state->running_ipsets); } void -fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile) +fw3_create_ipsets(struct fw3_state *state) { struct fw3_ipset *ipset; @@ -358,42 +352,34 @@ fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile) return; list_for_each_entry(ipset, &state->ipsets, list) - if (!ipset_loaded(statefile, ipset->name)) - create_ipset(ipset); + if (!fw3_lookup_ipset(state, ipset->name, true)) + create_ipset(ipset, state); fw3_pr("quit\n"); } void -fw3_destroy_ipsets(struct fw3_state *state, struct list_head *statefile) +fw3_destroy_ipsets(struct fw3_state *state) { - struct fw3_ipset *s; - struct fw3_statefile_entry *e; + struct fw3_ipset *s, *tmp; int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); - if (!statefile) - return; - - list_for_each_entry(e, statefile, list) + list_for_each_entry_safe(s, tmp, &state->running_ipsets, running_list) { - if (e->type != FW3_TYPE_IPSET) - continue; - if (!hasbit(state->defaults.flags, FW3_FAMILY_V4)) - delbit(e->flags[0], FW3_FAMILY_V4); + delbit(s->flags, FW3_FAMILY_V4); if (!hasbit(state->defaults.flags, FW3_FAMILY_V6)) - delbit(e->flags[0], FW3_FAMILY_V6); + delbit(s->flags, FW3_FAMILY_V6); - if ((s = fw3_lookup_ipset(state, e->name)) != NULL) - s->flags = e->flags[0]; - - if (!(e->flags[0] & mask)) + if (!(s->flags & mask)) { - info("Deleting ipset %s", e->name); + info("Deleting ipset %s", s->name); + + fw3_pr("flush %s\n", s->name); + fw3_pr("destroy %s\n", s->name); - fw3_pr("flush %s\n", e->name); - fw3_pr("destroy %s\n", e->name); + fw3_set_running(s, NULL); } } } @@ -408,16 +394,23 @@ fw3_free_ipset(struct fw3_ipset *ipset) } struct fw3_ipset * -fw3_lookup_ipset(struct fw3_state *state, const char *name) +fw3_lookup_ipset(struct fw3_state *state, const char *name, bool running) { - struct fw3_ipset *ipset; + struct fw3_ipset *s; if (list_empty(&state->ipsets)) return NULL; - list_for_each_entry(ipset, &state->ipsets, list) - if (!strcmp(ipset->name, name)) - return ipset; + list_for_each_entry(s, &state->ipsets, list) + { + if (strcmp(s->name, name)) + continue; + + if (!running || s->running_list.next) + return s; + + break; + } return NULL; } diff --git a/ipsets.h b/ipsets.h index a169979..410c712 100644 --- a/ipsets.h +++ b/ipsets.h @@ -38,12 +38,14 @@ struct fw3_ipset_settype { uint8_t optional; }; +struct fw3_ipset * fw3_alloc_ipset(void); void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p); -void fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile); -void fw3_destroy_ipsets(struct fw3_state *state, struct list_head *statefile); +void fw3_create_ipsets(struct fw3_state *state); +void fw3_destroy_ipsets(struct fw3_state *state); void fw3_free_ipset(struct fw3_ipset *ipset); -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, + bool running); #endif diff --git a/main.c b/main.c index 23c1497..62f51e1 100644 --- a/main.c +++ b/main.c @@ -62,6 +62,9 @@ build_state(void) state->disable_ipsets = true; } + INIT_LIST_HEAD(&state->running_zones); + INIT_LIST_HEAD(&state->running_ipsets); + fw3_load_defaults(state, p); fw3_load_ipsets(state, p); fw3_load_zones(state, p); @@ -69,6 +72,8 @@ build_state(void) fw3_load_redirects(state, p); fw3_load_forwards(state, p); + state->statefile = fw3_read_statefile(state); + return state; } @@ -89,6 +94,9 @@ free_state(struct fw3_state *state) list_for_each_safe(cur, tmp, &state->forwards) fw3_free_forward((struct fw3_forward *)cur); + list_for_each_safe(cur, tmp, &state->ipsets) + fw3_free_ipset((struct fw3_ipset *)cur); + uci_free_context(state->uci); free(state); @@ -117,22 +125,9 @@ restore_pipe(enum fw3_family family, bool silent) } static bool -family_running(struct list_head *statefile, enum fw3_family family) +family_running(struct fw3_state *state, enum fw3_family family) { - struct fw3_statefile_entry *e; - - if (statefile) - { - list_for_each_entry(e, statefile, list) - { - if (e->type != FW3_TYPE_DEFAULTS) - continue; - - return hasbit(e->flags[0], family); - } - } - - return false; + return hasbit(state->running_defaults.flags, family); } static bool @@ -163,9 +158,7 @@ stop(struct fw3_state *state, bool complete, bool restart) enum fw3_family family; enum fw3_table table; - struct list_head *statefile = fw3_read_statefile(); - - if (!complete && !statefile) + if (!complete && !state->statefile) { if (!restart) warn("The firewall appears to be stopped. " @@ -176,7 +169,7 @@ stop(struct fw3_state *state, bool complete, bool restart) for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) { - if (!complete && !family_running(statefile, family)) + if (!complete && !family_running(state, family)) continue; if (!family_used(family) || !restore_pipe(family, true)) @@ -201,12 +194,12 @@ stop(struct fw3_state *state, bool complete, bool restart) else { /* pass 1 */ - fw3_flush_rules(table, family, false, statefile); - fw3_flush_zones(table, family, false, statefile); + fw3_flush_rules(table, family, false, state); + fw3_flush_zones(table, family, false, state); /* pass 2 */ - fw3_flush_rules(table, family, true, statefile); - fw3_flush_zones(table, family, true, statefile); + fw3_flush_rules(table, family, true, state); + fw3_flush_zones(table, family, true, state); } fw3_pr("COMMIT\n"); @@ -222,12 +215,10 @@ stop(struct fw3_state *state, bool complete, bool restart) if (!restart && fw3_command_pipe(false, "ipset", "-exist", "-")) { - fw3_destroy_ipsets(state, statefile); + fw3_destroy_ipsets(state); fw3_command_close(); } - fw3_free_statefile(statefile); - if (!rv) fw3_write_statefile(state); @@ -241,12 +232,10 @@ start(struct fw3_state *state, bool restart) enum fw3_family family; enum fw3_table table; - struct list_head *statefile = fw3_read_statefile(); - if (!print_rules && !restart && fw3_command_pipe(false, "ipset", "-exist", "-")) { - fw3_create_ipsets(state, statefile); + fw3_create_ipsets(state); fw3_command_close(); } @@ -255,10 +244,7 @@ start(struct fw3_state *state, bool restart) if (!family_used(family)) continue; - if (!family_loaded(state, family) || !restore_pipe(family, false)) - continue; - - if (!print_rules && !restart && family_running(statefile, family)) + if (!print_rules && !restart && family_running(state, family)) { warn("The %s firewall appears to be started already. " "If it is indeed empty, remove the %s file and retry.", @@ -267,6 +253,9 @@ start(struct fw3_state *state, bool restart) continue; } + if (!family_loaded(state, family) || !restore_pipe(family, false)) + continue; + info("Constructing %s rules ...", fw3_flag_names[family]); for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++) @@ -294,8 +283,6 @@ start(struct fw3_state *state, bool restart) rv = 0; } - fw3_free_statefile(statefile); - if (!rv && !print_rules) fw3_write_statefile(state); diff --git a/options.h b/options.h index e02f890..c45a9d4 100644 --- a/options.h +++ b/options.h @@ -219,6 +219,7 @@ struct fw3_defaults struct fw3_zone { struct list_head list; + struct list_head running_list; const char *name; @@ -340,6 +341,7 @@ struct fw3_forward struct fw3_ipset { struct list_head list; + struct list_head running_list; const char *name; enum fw3_family family; @@ -371,7 +373,12 @@ struct fw3_state struct list_head forwards; struct list_head ipsets; + struct fw3_defaults running_defaults; + struct list_head running_zones; + struct list_head running_ipsets; + bool disable_ipsets; + bool statefile; }; diff --git a/redirects.c b/redirects.c index fc6b6b6..627438b 100644 --- a/redirects.c +++ b/redirects.c @@ -132,14 +132,14 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) continue; } else if (redir->src.set && !redir->src.any && - !(redir->_src = fw3_lookup_zone(state, redir->src.name))) + !(redir->_src = fw3_lookup_zone(state, redir->src.name, false))) { warn_elem(e, "refers to not existing zone '%s'", redir->src.name); fw3_free_redirect(redir); continue; } else if (redir->dest.set && !redir->dest.any && - !(redir->_dest = fw3_lookup_zone(state, redir->dest.name))) + !(redir->_dest = fw3_lookup_zone(state, redir->dest.name, false))) { warn_elem(e, "refers to not existing zone '%s'", redir->dest.name); fw3_free_redirect(redir); @@ -152,7 +152,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) continue; } else if (redir->ipset.set && !redir->ipset.any && - !(redir->_ipset = fw3_lookup_ipset(state, redir->ipset.name))) + !(redir->_ipset = fw3_lookup_ipset(state, redir->ipset.name, false))) { warn_elem(e, "refers to unknown ipset '%s'", redir->ipset.name); fw3_free_redirect(redir); diff --git a/rules.c b/rules.c index bc983a6..1979340 100644 --- a/rules.c +++ b/rules.c @@ -90,14 +90,14 @@ fw3_load_rules(struct fw3_state *state, struct uci_package *p) continue; } else if (rule->src.set && !rule->src.any && - !(rule->_src = fw3_lookup_zone(state, rule->src.name))) + !(rule->_src = fw3_lookup_zone(state, rule->src.name, false))) { warn_elem(e, "refers to not existing zone '%s'", rule->src.name); fw3_free_rule(rule); continue; } else if (rule->dest.set && !rule->dest.any && - !(rule->_dest = fw3_lookup_zone(state, rule->dest.name))) + !(rule->_dest = fw3_lookup_zone(state, rule->dest.name, false))) { warn_elem(e, "refers to not existing zone '%s'", rule->dest.name); fw3_free_rule(rule); @@ -110,7 +110,7 @@ fw3_load_rules(struct fw3_state *state, struct uci_package *p) continue; } else if (rule->ipset.set && !rule->ipset.any && - !(rule->_ipset = fw3_lookup_ipset(state, rule->ipset.name))) + !(rule->_ipset = fw3_lookup_ipset(state, rule->ipset.name, false))) { warn_elem(e, "refers to unknown ipset '%s'", rule->ipset.name); fw3_free_rule(rule); diff --git a/utils.c b/utils.c index 1ba25fd..c9ca206 100644 --- a/utils.c +++ b/utils.c @@ -19,6 +19,10 @@ #include "utils.h" #include "options.h" +#include "zones.h" +#include "ipsets.h" + + static int lock_fd = -1; static pid_t pipe_pid = -1; static FILE *pipe_fd = NULL; @@ -332,66 +336,90 @@ fw3_unlock(void) } -struct list_head * -fw3_read_statefile(void) +bool +fw3_read_statefile(void *state) { FILE *sf; - int n; + int n, type; char line[128]; - const char *p; + const char *p, *name; - struct list_head *state; - struct fw3_statefile_entry *entry; + uint16_t flags[2]; + + struct fw3_state *s = state; + struct fw3_zone *zone; + struct fw3_ipset *ipset; sf = fopen(FW3_STATEFILE, "r"); if (!sf) - return NULL; - - state = malloc(sizeof(*state)); - - if (!state) - return NULL; - - INIT_LIST_HEAD(state); + return false; while (fgets(line, sizeof(line), sf)) { - entry = malloc(sizeof(*entry)); - - if (!entry) - continue; - - memset(entry, 0, sizeof(*entry)); - p = strtok(line, " \t\n"); if (!p) continue; - entry->type = strtoul(p, NULL, 10); - - p = strtok(NULL, " \t\n"); + type = strtoul(p, NULL, 10); + name = strtok(NULL, " \t\n"); - if (!p) + if (!name) continue; - entry->name = strdup(p); - for (n = 0, p = strtok(NULL, " \t\n"); - n < ARRAY_SIZE(entry->flags) && p != NULL; + n < ARRAY_SIZE(flags) && p != NULL; n++, p = strtok(NULL, " \t\n")) { - entry->flags[n] = strtoul(p, NULL, 10); + flags[n] = strtoul(p, NULL, 10); } - list_add_tail(&entry->list, state); + switch (type) + { + case FW3_TYPE_DEFAULTS: + s->running_defaults.flags = flags[0]; + break; + + case FW3_TYPE_ZONE: + if (!(zone = fw3_lookup_zone(state, name, false))) + { + zone = fw3_alloc_zone(); + + if (!zone) + continue; + + zone->name = strdup(name); + list_add_tail(&zone->list, &s->zones); + } + + zone->src_flags = flags[0]; + zone->dst_flags = flags[1]; + list_add_tail(&zone->running_list, &s->running_zones); + break; + + case FW3_TYPE_IPSET: + if (!(ipset = fw3_lookup_ipset(state, name, false))) + { + ipset = fw3_alloc_ipset(); + + if (!ipset) + continue; + + ipset->name = strdup(name); + list_add_tail(&ipset->list, &s->ipsets); + } + + ipset->flags = flags[0]; + list_add_tail(&ipset->running_list, &s->running_ipsets); + break; + } } fclose(sf); - return state; + return true; } void @@ -424,40 +452,34 @@ fw3_write_statefile(void *state) fprintf(sf, "%u - %u\n", FW3_TYPE_DEFAULTS, d->flags); - list_for_each_entry(z, &s->zones, list) + list_for_each_entry(z, &s->running_zones, running_list) { fprintf(sf, "%u %s %u %u\n", FW3_TYPE_ZONE, z->name, z->src_flags, z->dst_flags); } - list_for_each_entry(i, &s->ipsets, list) + list_for_each_entry(i, &s->running_ipsets, running_list) { - if (i->external && *i->external) - continue; - - if (!i->flags) - continue; - fprintf(sf, "%u %s %u\n", FW3_TYPE_IPSET, i->name, i->flags); } fclose(sf); } -void -fw3_free_statefile(struct list_head *statefile) -{ - struct fw3_statefile_entry *e, *tmp; - if (!statefile) - return; +struct object_list_heads +{ + struct list_head list; + struct list_head running_list; +}; - list_for_each_entry_safe(e, tmp, statefile, list) - { - list_del(&e->list); - free(e->name); - free(e); - } +void +fw3_set_running(void *object, struct list_head *dest) +{ + struct object_list_heads *o = object; - free(statefile); + if (dest && !o->running_list.next) + list_add_tail(&o->running_list, dest); + else if (!dest && o->running_list.next) + list_del(&o->running_list); } diff --git a/utils.h b/utils.h index 5cadd58..f157daf 100644 --- a/utils.h +++ b/utils.h @@ -87,16 +87,9 @@ enum fw3_statefile_type FW3_TYPE_IPSET = 2, }; -struct fw3_statefile_entry -{ - struct list_head list; - enum fw3_statefile_type type; - char *name; - uint32_t flags[2]; -}; - -struct list_head * fw3_read_statefile(void); +bool fw3_read_statefile(void *state); void fw3_write_statefile(void *state); -void fw3_free_statefile(struct list_head *statefile); + +void fw3_set_running(void *object, struct list_head *dest); #endif diff --git a/zones.c b/zones.c index 9595c37..317acc8 100644 --- a/zones.c +++ b/zones.c @@ -144,6 +144,29 @@ resolve_networks(struct uci_element *e, struct fw3_zone *zone) } } +struct fw3_zone * +fw3_alloc_zone(void) +{ + struct fw3_zone *zone; + + zone = malloc(sizeof(*zone)); + + if (!zone) + return NULL; + + memset(zone, 0, sizeof(*zone)); + + INIT_LIST_HEAD(&zone->networks); + INIT_LIST_HEAD(&zone->devices); + INIT_LIST_HEAD(&zone->subnets); + INIT_LIST_HEAD(&zone->masq_src); + INIT_LIST_HEAD(&zone->masq_dest); + + zone->log_limit.rate = 10; + + return zone; +} + void fw3_load_zones(struct fw3_state *state, struct uci_package *p) { @@ -161,21 +184,11 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) if (strcmp(s->type, "zone")) continue; - zone = malloc(sizeof(*zone)); + zone = fw3_alloc_zone(); if (!zone) continue; - memset(zone, 0, sizeof(*zone)); - - INIT_LIST_HEAD(&zone->networks); - INIT_LIST_HEAD(&zone->devices); - INIT_LIST_HEAD(&zone->subnets); - INIT_LIST_HEAD(&zone->masq_src); - INIT_LIST_HEAD(&zone->masq_dest); - - zone->log_limit.rate = 10; - fw3_parse_options(zone, zone_opts, ARRAY_SIZE(zone_opts), s); if (!zone->extra_dest) @@ -217,7 +230,7 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) static void print_zone_chain(enum fw3_table table, enum fw3_family family, - struct fw3_zone *zone, bool disable_notrack) + struct fw3_zone *zone, struct fw3_state *state) { bool s, d; @@ -226,7 +239,7 @@ print_zone_chain(enum fw3_table table, enum fw3_family family, setbit(zone->dst_flags, family); - if (!zone->conntrack && !disable_notrack) + if (!zone->conntrack && !state->defaults.drop_invalid) setbit(zone->dst_flags, FW3_TARGET_NOTRACK); s = print_chains(table, family, ":%s - [0:0]\n", zone->name, @@ -236,7 +249,10 @@ print_zone_chain(enum fw3_table table, enum fw3_family family, zone->dst_flags, dst_chains, ARRAY_SIZE(dst_chains)); if (s || d) + { info(" * Zone '%s'", zone->name); + fw3_set_running(zone, &state->running_zones); + } } static void @@ -442,7 +458,7 @@ fw3_print_zone_chains(enum fw3_table table, enum fw3_family family, struct fw3_zone *zone; list_for_each_entry(zone, &state->zones, list) - print_zone_chain(table, family, zone, state->defaults.drop_invalid); + print_zone_chain(table, family, zone, state); } void @@ -457,28 +473,34 @@ fw3_print_zone_rules(enum fw3_table table, enum fw3_family family, void fw3_flush_zones(enum fw3_table table, enum fw3_family family, - bool pass2, struct list_head *statefile) + bool pass2, struct fw3_state *state) { - struct fw3_statefile_entry *e; + struct fw3_zone *z, *tmp; + int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); - list_for_each_entry(e, statefile, list) + list_for_each_entry_safe(z, tmp, &state->running_zones, running_list) { - if (e->type != FW3_TYPE_ZONE) - continue; - - if (!hasbit(e->flags[1], family)) + if (!hasbit(z->dst_flags, family)) continue; print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n", - e->name, e->flags[0], src_chains, ARRAY_SIZE(src_chains)); + z->name, z->src_flags, src_chains, ARRAY_SIZE(src_chains)); print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n", - e->name, e->flags[1], dst_chains, ARRAY_SIZE(dst_chains)); + z->name, z->dst_flags, dst_chains, ARRAY_SIZE(dst_chains)); + + if (pass2) + { + delbit(z->dst_flags, family); + + if (!(z->dst_flags & mask)) + fw3_set_running(z, NULL); + } } } struct fw3_zone * -fw3_lookup_zone(struct fw3_state *state, const char *name) +fw3_lookup_zone(struct fw3_state *state, const char *name, bool running) { struct fw3_zone *z; @@ -486,9 +508,16 @@ fw3_lookup_zone(struct fw3_state *state, const char *name) return NULL; list_for_each_entry(z, &state->zones, list) - if (!strcmp(z->name, name)) + { + if (strcmp(z->name, name)) + continue; + + if (!running || z->running_list.next) return z; + break; + } + return NULL; } diff --git a/zones.h b/zones.h index 57e42df..c462ea8 100644 --- a/zones.h +++ b/zones.h @@ -21,6 +21,8 @@ #include "options.h" +struct fw3_zone * fw3_alloc_zone(void); + void fw3_load_zones(struct fw3_state *state, struct uci_package *p); void fw3_print_zone_chains(enum fw3_table table, enum fw3_family family, @@ -30,9 +32,10 @@ void fw3_print_zone_rules(enum fw3_table table, enum fw3_family family, struct fw3_state *state); void fw3_flush_zones(enum fw3_table table, enum fw3_family family, - bool pass2, struct list_head *statefile); + bool pass2, struct fw3_state *state); -struct fw3_zone * fw3_lookup_zone(struct fw3_state *state, const char *name); +struct fw3_zone * fw3_lookup_zone(struct fw3_state *state, const char *name, + bool running); void fw3_free_zone(struct fw3_zone *zone); -- 2.11.0