X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=main.c;h=d4d7b7b6aa577539faaa8859158170ac38ac0884;hp=2dd1f86f02c13d52c001734ddbcd70926e6e1389;hb=eb2a20924afd979feb485298111ced679de42aa0;hpb=6e6afb0c7d4d69e4a48122664645c8de67f34c96 diff --git a/main.c b/main.c index 2dd1f86..d4d7b7b 100644 --- a/main.c +++ b/main.c @@ -26,25 +26,13 @@ #include "redirects.h" #include "forwards.h" #include "ipsets.h" +#include "includes.h" #include "ubus.h" static bool print_rules = false; static enum fw3_family use_family = FW3_FAMILY_ANY; -static const char *families[] = { - "(bug)", - "IPv4", - "IPv6", -}; - -static const char *tables[] = { - "filter", - "nat", - "mangle", - "raw", -}; - static struct fw3_state * build_state(void) @@ -52,6 +40,9 @@ build_state(void) struct fw3_state *state = NULL; struct uci_package *p = NULL; + if (!fw3_ubus_connect()) + error("Failed to connect to ubus"); + state = malloc(sizeof(*state)); if (!state) @@ -75,12 +66,18 @@ 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); fw3_load_rules(state, p); fw3_load_redirects(state, p); fw3_load_forwards(state, p); + fw3_load_includes(state, p); + + state->statefile = fw3_read_statefile(state); return state; } @@ -102,6 +99,12 @@ 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); + + list_for_each_safe(cur, tmp, &state->includes) + fw3_free_include((struct fw3_include *)cur); + uci_free_context(state->uci); free(state); @@ -113,18 +116,16 @@ 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; } @@ -132,22 +133,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 has(state->defaults.flags, family, family); } static bool @@ -156,58 +144,53 @@ 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); + set(state->defaults.flags, family, family); else - delbit(state->defaults.flags, family); + del(state->defaults.flags, family, family); } static int -stop(struct fw3_state *state, bool complete, bool restart) +stop(struct fw3_state *state, bool complete, bool reload) { + FILE *ct; + int rv = 1; enum fw3_family family; enum fw3_table table; - struct list_head *statefile = fw3_read_statefile(); - - if (!complete && !statefile) + if (!complete && !state->statefile) { - if (!restart) + if (!reload) warn("The firewall appears to be stopped. " "Use the 'flush' command to forcefully purge all rules."); return rv; } + if (!print_rules) + fw3_hotplug_zones(state, false); + 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)) continue; - info("Removing %s rules ...", families[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]); + info(" * %sing %s %s table", complete ? "Flush" : "Clear", + fw3_flag_names[family], fw3_flag_names[table]); - fw3_pr("*%s\n", tables[table]); + fw3_pr("*%s\n", fw3_flag_names[table]); if (complete) { @@ -216,12 +199,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(state, family, table, reload, false); + fw3_flush_zones(state, family, table, reload, false); /* pass 2 */ - fw3_flush_rules(table, family, true, statefile); - fw3_flush_zones(table, family, true, statefile); + fw3_flush_rules(state, family, table, reload, true); + fw3_flush_zones(state, family, table, reload, true); } fw3_pr("COMMIT\n"); @@ -229,22 +212,27 @@ stop(struct fw3_state *state, bool complete, bool restart) fw3_command_close(); - if (!restart) + if (!reload) + { + if (fw3_command_pipe(false, "ipset", "-exist", "-")) + { + fw3_destroy_ipsets(state, family); + fw3_command_close(); + } + family_set(state, family, false); + } rv = 0; } - if (!restart && - !family_loaded(state, FW3_FAMILY_V4) && - !family_loaded(state, FW3_FAMILY_V6) && - fw3_command_pipe(false, "ipset", "-exist", "-")) + if (complete && (ct = fopen("/proc/net/nf_conntrack", "w")) != NULL) { - fw3_destroy_ipsets(statefile); - fw3_command_close(); - } + info(" * Flushing conntrack table ..."); - fw3_free_statefile(statefile); + fwrite("f\n", 2, 1, ct); + fclose(ct); + } if (!rv) fw3_write_statefile(state); @@ -253,19 +241,19 @@ stop(struct fw3_state *state, bool complete, bool restart) } static int -start(struct fw3_state *state, bool restart) +start(struct fw3_state *state, bool reload) { int rv = 1; 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", "-")) + if (!print_rules && !reload) { - fw3_create_ipsets(state); - fw3_command_close(); + if (fw3_command_pipe(false, "ipset", "-exist", "-")) + { + fw3_create_ipsets(state); + fw3_command_close(); + } } for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) @@ -273,49 +261,57 @@ start(struct fw3_state *state, bool restart) if (!family_used(family)) continue; - if (!family_loaded(state, family) || !restore_pipe(family, false)) - continue; - - if (!restart && family_running(statefile, family)) + if (!print_rules && !reload && family_running(state, family)) { warn("The %s firewall appears to be started already. " "If it is indeed empty, remove the %s file and retry.", - families[family], FW3_STATEFILE); + fw3_flag_names[family], FW3_STATEFILE); continue; } - info("Constructing %s rules ...", families[family]); + if (!restore_pipe(family, false)) + continue; 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]); - - fw3_pr("*%s\n", tables[table]); - fw3_print_default_chains(table, family, state); - fw3_print_zone_chains(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); + info(" * Populating %s %s table", + fw3_flag_names[family], fw3_flag_names[table]); + + fw3_pr("*%s\n", fw3_flag_names[table]); + fw3_print_default_chains(state, family, table, reload); + fw3_print_zone_chains(state, family, table, reload); + fw3_print_default_head_rules(state, family, table, reload); + fw3_print_rules(state, family, table); + fw3_print_redirects(state, family, table); + fw3_print_forwards(state, family, table); + fw3_print_zone_rules(state, family, table, reload); + fw3_print_default_tail_rules(state, family, table, reload); fw3_pr("COMMIT\n"); } + fw3_print_includes(state, family, reload); + fw3_command_close(); family_set(state, family, true); rv = 0; } - fw3_free_statefile(statefile); - if (!rv) - fw3_write_statefile(state); + { + fw3_set_defaults(state); + + if (!print_rules) + { + fw3_run_includes(state, reload); + fw3_hotplug_zones(state, true); + fw3_write_statefile(state); + } + } return rv; } @@ -365,7 +361,7 @@ lookup_device(struct fw3_state *state, const char *dev) static int usage(void) { - fprintf(stderr, "fw3 [-4] [-6] [-q] {start|stop|flush|restart|print}\n"); + fprintf(stderr, "fw3 [-4] [-6] [-q] {start|stop|flush|reload|restart|print}\n"); fprintf(stderr, "fw3 [-q] network {net}\n"); fprintf(stderr, "fw3 [-q] device {dev}\n"); @@ -379,7 +375,7 @@ int main(int argc, char **argv) struct fw3_state *state = NULL; struct fw3_defaults *defs = NULL; - while ((ch = getopt(argc, argv, "46qh")) != -1) + while ((ch = getopt(argc, argv, "46dqh")) != -1) { switch (ch) { @@ -391,6 +387,10 @@ int main(int argc, char **argv) use_family = FW3_FAMILY_V6; break; + case 'd': + fw3_pr_debug = true; + break; + case 'q': freopen("/dev/null", "w", stderr); break; @@ -401,15 +401,9 @@ int main(int argc, char **argv) } } - if (!fw3_ubus_connect()) - error("Failed to connect to ubus"); - state = build_state(); defs = &state->defaults; - if (!fw3_lock()) - goto out; - if (optind >= argc) { rv = usage(); @@ -421,6 +415,9 @@ int main(int argc, char **argv) if (!strcmp(argv[optind], "print")) { + if (use_family == FW3_FAMILY_ANY) + use_family = FW3_FAMILY_V4; + freopen("/dev/null", "w", stderr); state->disable_ipsets = true; @@ -430,20 +427,50 @@ int main(int argc, char **argv) } else if (!strcmp(argv[optind], "start")) { - rv = start(state, false); + if (fw3_lock()) + { + rv = start(state, false); + fw3_unlock(); + } } else if (!strcmp(argv[optind], "stop")) { - rv = stop(state, false, false); + if (fw3_lock()) + { + rv = stop(state, false, false); + fw3_unlock(); + } } else if (!strcmp(argv[optind], "flush")) { - rv = stop(state, true, false); + if (fw3_lock()) + { + rv = stop(state, true, false); + fw3_unlock(); + } } else if (!strcmp(argv[optind], "restart")) { - rv = stop(state, false, true); - rv = start(state, !rv); + if (fw3_lock()) + { + stop(state, true, false); + free_state(state); + + state = build_state(); + rv = start(state, false); + + fw3_unlock(); + } + } + else if (!strcmp(argv[optind], "reload")) + { + if (fw3_lock()) + { + rv = stop(state, false, true); + rv = start(state, !rv); + + fw3_unlock(); + } } else if (!strcmp(argv[optind], "network") && (optind + 1) < argc) { @@ -462,7 +489,5 @@ out: if (state) free_state(state); - fw3_unlock(); - return rv; }