X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=main.c;h=d94d0e9e71555aa615993fb0e6ce856be17258b6;hb=23741a3279981c5e0ce3ca9e00e368d4f0b142b6;hp=ddbd24d60656c5600a0bce0fddddb6ab053daeee;hpb=8fee8f9c520c58d07772cc6bd8f65d9eb1776a56;p=project%2Ffirewall3.git diff --git a/main.c b/main.c index ddbd24d..d94d0e9 100644 --- a/main.c +++ b/main.c @@ -30,7 +30,7 @@ static bool print_rules = false; -static bool skip_family[FW3_FAMILY_V6 + 1] = { false }; +static enum fw3_family use_family = FW3_FAMILY_ANY; static struct fw3_state * @@ -69,12 +69,6 @@ build_state(void) fw3_load_redirects(state, p); fw3_load_forwards(state, p); - if (state->defaults.disable_ipv6 && !skip_family[FW3_FAMILY_V6]) - { - warn("IPv6 rules globally disabled in configuration"); - skip_family[FW3_FAMILY_V6] = true; - } - return state; } @@ -106,83 +100,154 @@ free_state(struct fw3_state *state) static bool restore_pipe(enum fw3_family family, bool silent) { - const char *cmd[] = { - "(bug)", - "iptables-restore", - "ip6tables-restore", - }; + const char *cmd; + + cmd = (family == FW3_FAMILY_V4) ? "iptables-restore" : "ip6tables-restore"; if (print_rules) return fw3_stdout_pipe(); - if (!fw3_command_pipe(silent, cmd[family], "--lenient", "--noflush")) + if (!fw3_command_pipe(silent, cmd, "--lenient", "--noflush")) { - warn("Unable to execute %s", cmd[family]); + warn("Unable to execute %s", cmd); return false; } return true; } +static bool +family_running(struct list_head *statefile, 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; +} + +static bool +family_used(enum fw3_family family) +{ + return (use_family == FW3_FAMILY_ANY) || (use_family == family); +} + +static bool +family_loaded(struct fw3_state *state, enum fw3_family family) +{ + return hasbit(state->defaults.flags, family); +} + +static void +family_set(struct fw3_state *state, enum fw3_family family, bool set) +{ + if (set) + setbit(state->defaults.flags, family); + else + delbit(state->defaults.flags, family); +} + static int -stop(struct fw3_state *state, bool complete) +stop(struct fw3_state *state, bool complete, bool restart) { + int rv = 1; enum fw3_family family; enum fw3_table table; - const char *tables[] = { - "filter", - "nat", - "mangle", - "raw", - }; + struct list_head *statefile = fw3_read_statefile(); + + if (!complete && !statefile) + { + if (!restart) + warn("The firewall appears to be stopped. " + "Use the 'flush' command to forcefully purge all rules."); + + return rv; + } for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) { - if (skip_family[family] || !restore_pipe(family, true)) + if (!complete && !family_running(statefile, family)) continue; - info("Removing IPv%d rules ...", family == FW3_FAMILY_V4 ? 4 : 6); + if (!family_used(family) || !restore_pipe(family, true)) + continue; + + info("Removing %s rules ...", fw3_flag_names[family]); for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++) { - if (!fw3_has_table(family == FW3_FAMILY_V6, tables[table])) + if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table])) continue; info(" * %sing %s table", - complete ? "Flush" : "Clear", tables[table]); + complete ? "Flush" : "Clear", fw3_flag_names[table]); + + fw3_pr("*%s\n", fw3_flag_names[table]); + + if (complete) + { + fw3_flush_all(table); + } + else + { + /* pass 1 */ + fw3_flush_rules(table, family, false, statefile); + fw3_flush_zones(table, family, false, statefile); + + /* pass 2 */ + fw3_flush_rules(table, family, true, statefile); + fw3_flush_zones(table, family, true, statefile); + } - fw3_pr("*%s\n", tables[table]); - fw3_print_flush_rules(table, family, state, complete); fw3_pr("COMMIT\n"); } fw3_command_close(); + + if (!restart) + family_set(state, family, false); + + rv = 0; } - if (complete && fw3_command_pipe(false, "ipset", "-exist", "-")) + if (!restart && + !family_loaded(state, FW3_FAMILY_V4) && + !family_loaded(state, FW3_FAMILY_V6) && + fw3_command_pipe(false, "ipset", "-exist", "-")) { - fw3_destroy_ipsets(state); + fw3_destroy_ipsets(statefile); fw3_command_close(); } - return 0; + fw3_free_statefile(statefile); + + if (!rv) + fw3_write_statefile(state); + + return rv; } static int -start(struct fw3_state *state) +start(struct fw3_state *state, bool restart) { + int rv = 1; enum fw3_family family; enum fw3_table table; - const char *tables[] = { - "filter", - "nat", - "mangle", - "raw", - }; + struct list_head *statefile = fw3_read_statefile(); - if (!print_rules && fw3_command_pipe(false, "ipset", "-exist", "-")) + if (!print_rules && !restart && + fw3_command_pipe(false, "ipset", "-exist", "-")) { fw3_create_ipsets(state); fw3_command_close(); @@ -190,33 +255,54 @@ start(struct fw3_state *state) for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) { - if (skip_family[family] || !restore_pipe(family, false)) + if (!family_used(family)) continue; - info("Constructing IPv%d rules ...", family == FW3_FAMILY_V4 ? 4 : 6); + if (!family_loaded(state, family) || !restore_pipe(family, false)) + continue; + + if (!restart && family_running(statefile, family)) + { + warn("The %s firewall appears to be started already. " + "If it is indeed empty, remove the %s file and retry.", + fw3_flag_names[family], FW3_STATEFILE); + + continue; + } + + info("Constructing %s rules ...", fw3_flag_names[family]); for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++) { - if (!fw3_has_table(family == FW3_FAMILY_V6, tables[table])) + if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table])) continue; - info(" * Populating %s table", tables[table]); + info(" * Populating %s table", fw3_flag_names[table]); - fw3_pr("*%s\n", tables[table]); + fw3_pr("*%s\n", fw3_flag_names[table]); fw3_print_default_chains(table, family, state); fw3_print_zone_chains(table, family, state); - fw3_print_default_rules(table, family, state); + fw3_print_default_head_rules(table, family, state); fw3_print_rules(table, family, state); fw3_print_redirects(table, family, state); fw3_print_forwards(table, family, state); fw3_print_zone_rules(table, family, state); + fw3_print_default_tail_rules(table, family, state); fw3_pr("COMMIT\n"); } fw3_command_close(); + family_set(state, family, true); + + rv = 0; } - return 0; + fw3_free_statefile(statefile); + + if (!rv) + fw3_write_statefile(state); + + return rv; } static int @@ -276,19 +362,18 @@ int main(int argc, char **argv) { int ch, rv = 1; struct fw3_state *state = NULL; + struct fw3_defaults *defs = NULL; while ((ch = getopt(argc, argv, "46qh")) != -1) { switch (ch) { case '4': - skip_family[FW3_FAMILY_V4] = false; - skip_family[FW3_FAMILY_V6] = true; + use_family = FW3_FAMILY_V4; break; case '6': - skip_family[FW3_FAMILY_V4] = true; - skip_family[FW3_FAMILY_V6] = false; + use_family = FW3_FAMILY_V6; break; case 'q': @@ -305,6 +390,10 @@ int main(int argc, char **argv) error("Failed to connect to ubus"); state = build_state(); + defs = &state->defaults; + + if (!fw3_lock()) + goto out; if (optind >= argc) { @@ -312,50 +401,34 @@ int main(int argc, char **argv) goto out; } + if (use_family == FW3_FAMILY_V6 && defs->disable_ipv6) + warn("IPv6 rules globally disabled in configuration"); + if (!strcmp(argv[optind], "print")) { + freopen("/dev/null", "w", stderr); + state->disable_ipsets = true; print_rules = true; - if (!skip_family[FW3_FAMILY_V4] && !skip_family[FW3_FAMILY_V6]) - skip_family[FW3_FAMILY_V6] = true; - - rv = start(state); + rv = start(state, false); } else if (!strcmp(argv[optind], "start")) { - if (!fw3_check_statefile(false)) - goto out; - - rv = start(state); - fw3_close_statefile(); + rv = start(state, false); } else if (!strcmp(argv[optind], "stop")) { - if (!fw3_check_statefile(true)) - goto out; - - rv = stop(state, false); - fw3_remove_statefile(); + rv = stop(state, false, false); } else if (!strcmp(argv[optind], "flush")) { - rv = stop(state, true); - fw3_remove_statefile(); + rv = stop(state, true, false); } else if (!strcmp(argv[optind], "restart")) { - if (fw3_check_statefile(true)) - { - stop(state, false); - fw3_remove_statefile(); - } - - if (!fw3_check_statefile(false)) - goto out; - - rv = start(state); - fw3_close_statefile(); + rv = stop(state, false, true); + rv = start(state, !rv); } else if (!strcmp(argv[optind], "network") && (optind + 1) < argc) { @@ -374,5 +447,7 @@ out: if (state) free_state(state); + fw3_unlock(); + return rv; }