From b6109157659a7d3f389797cfc6f91c90641ba33e Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 13 May 2013 19:47:12 +0200 Subject: [PATCH] Use libiptc to clear current ruleset --- CMakeLists.txt | 4 +- defaults.c | 56 +++++--------- defaults.h | 7 +- iptables.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++ iptables.h | 43 +++++++++++ main.c | 47 +++++------- zones.c | 34 ++++++--- zones.h | 5 +- 8 files changed, 307 insertions(+), 83 deletions(-) create mode 100644 iptables.c create mode 100644 iptables.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 01d2c7c..50b1c3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ IF(APPLE) LINK_DIRECTORIES(/opt/local/lib) ENDIF() -ADD_EXECUTABLE(firewall3 main.c options.c defaults.c zones.c forwards.c rules.c redirects.c utils.c ubus.c ipsets.c includes.c) -TARGET_LINK_LIBRARIES(firewall3 uci ubox ubus) +ADD_EXECUTABLE(firewall3 main.c options.c defaults.c zones.c forwards.c rules.c redirects.c utils.c ubus.c ipsets.c includes.c iptables.c) +TARGET_LINK_LIBRARIES(firewall3 uci ubox ubus ip4tc ip6tc) SET(CMAKE_INSTALL_PREFIX /usr) diff --git a/defaults.c b/defaults.c index f87ac92..20c57d6 100644 --- a/defaults.c +++ b/defaults.c @@ -301,55 +301,39 @@ fw3_set_defaults(struct fw3_state *state) set_default("window_scaling", state->defaults.tcp_window_scaling); } -static void -reset_policy(enum fw3_table table, enum fw3_flag policy) -{ - if (table != FW3_TABLE_FILTER) - return; - - fw3_pr(":INPUT %s [0:0]\n", fw3_flag_names[policy]); - fw3_pr(":OUTPUT %s [0:0]\n", fw3_flag_names[policy]); - fw3_pr(":FORWARD %s [0:0]\n", fw3_flag_names[policy]); -} - void -fw3_flush_rules(struct fw3_state *state, enum fw3_family family, - enum fw3_table table, bool reload, bool pass2) +fw3_flush_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, + bool reload) { struct fw3_defaults *defs = &state->defaults; - uint32_t custom_mask = ~0; + const struct fw3_rule_spec *c; - if (!has(defs->flags, family, table)) + if (!has(defs->flags, handle->family, handle->table)) return; - /* don't touch user chains on selective stop */ - if (reload) - delbit(custom_mask, FW3_FLAG_CUSTOM_CHAINS); - - if (!pass2) + for (c = default_chains; c->format; c++) { - reset_policy(table, reload ? FW3_FLAG_DROP : FW3_FLAG_ACCEPT); + /* don't touch user chains on selective stop */ + if (reload && hasbit(c->flag, FW3_FLAG_CUSTOM_CHAINS)) + continue; - fw3_pr_rulespec(table, family, defs->flags, custom_mask, - toplevel_rules, "-D %s\n"); + if (!fw3_is_family(c, handle->family)) + continue; - fw3_pr_rulespec(table, family, defs->flags, custom_mask, - default_chains, "-F %s\n"); - } - else - { - fw3_pr_rulespec(table, family, defs->flags, custom_mask, - default_chains, "-X %s\n"); + if (c->table != handle->table) + continue; - del(defs->flags, family, table); + fw3_ipt_set_policy(handle, reload ? FW3_FLAG_DROP : FW3_FLAG_ACCEPT); + fw3_ipt_delete_rules(handle, c->format); + fw3_ipt_delete_chain(handle, c->format); } + + del(defs->flags, handle->family, handle->table); } void -fw3_flush_all(enum fw3_table table) +fw3_flush_all(struct fw3_ipt_handle *handle) { - reset_policy(table, FW3_FLAG_ACCEPT); - - fw3_pr("-F\n"); - fw3_pr("-X\n"); + fw3_ipt_set_policy(handle, FW3_FLAG_ACCEPT); + fw3_ipt_flush(handle); } diff --git a/defaults.h b/defaults.h index 1c1a6a0..a89a36e 100644 --- a/defaults.h +++ b/defaults.h @@ -20,6 +20,7 @@ #define __FW3_DEFAULTS_H #include "options.h" +#include "iptables.h" extern const struct fw3_option fw3_flag_opts[]; @@ -38,9 +39,9 @@ void fw3_print_default_tail_rules(struct fw3_state *state, void fw3_set_defaults(struct fw3_state *state); -void fw3_flush_rules(struct fw3_state *state, enum fw3_family family, - enum fw3_table table, bool reload, bool pass2); +void fw3_flush_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, + bool reload); -void fw3_flush_all(enum fw3_table table); +void fw3_flush_all(struct fw3_ipt_handle *handle); #endif diff --git a/iptables.c b/iptables.c new file mode 100644 index 0000000..f5f4952 --- /dev/null +++ b/iptables.c @@ -0,0 +1,194 @@ +/* + * firewall3 - 3rd OpenWrt UCI firewall implementation + * + * Copyright (C) 2013 Jo-Philipp Wich + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "iptables.h" + + +struct fw3_ipt_handle * +fw3_ipt_open(enum fw3_family family, enum fw3_table table) +{ + struct fw3_ipt_handle *h; + + h = malloc(sizeof(*h)); + + if (!h) + return NULL; + + if (family == FW3_FAMILY_V6) + { + h->family = FW3_FAMILY_V6; + h->table = table; + h->handle = ip6tc_init(fw3_flag_names[table]); + } + else + { + h->family = FW3_FAMILY_V4; + h->table = table; + h->handle = iptc_init(fw3_flag_names[table]); + } + + if (!h->handle) + { + free(h); + return NULL; + } + + return h; +} + +void fw3_ipt_set_policy(struct fw3_ipt_handle *h, enum fw3_flag policy) +{ + if (h->table != FW3_TABLE_FILTER) + return; + + if (h->family == FW3_FAMILY_V6) + { + ip6tc_set_policy("INPUT", fw3_flag_names[policy], NULL, h->handle); + ip6tc_set_policy("OUTPUT", fw3_flag_names[policy], NULL, h->handle); + ip6tc_set_policy("FORWARD", fw3_flag_names[policy], NULL, h->handle); + } + else + { + iptc_set_policy("INPUT", fw3_flag_names[policy], NULL, h->handle); + iptc_set_policy("OUTPUT", fw3_flag_names[policy], NULL, h->handle); + iptc_set_policy("FORWARD", fw3_flag_names[policy], NULL, h->handle); + } +} + +void fw3_ipt_delete_chain(struct fw3_ipt_handle *h, const char *chain) +{ + if (h->family == FW3_FAMILY_V6) + { + if (ip6tc_flush_entries(chain, h->handle)) + ip6tc_delete_chain(chain, h->handle); + } + else + { + if (iptc_flush_entries(chain, h->handle)) + iptc_delete_chain(chain, h->handle); + } +} + +void fw3_ipt_delete_rules(struct fw3_ipt_handle *h, const char *target) +{ + unsigned int num; + const struct ipt_entry *e; + const struct ip6t_entry *e6; + const char *chain; + const char *t; + bool found; + + if (h->family == FW3_FAMILY_V6) + { + for (chain = ip6tc_first_chain(h->handle); + chain != NULL; + chain = ip6tc_next_chain(h->handle)) + { + do { + found = false; + + for (num = 0, e6 = ip6tc_first_rule(chain, h->handle); + e6 != NULL; + num++, e6 = ip6tc_next_rule(e6, h->handle)) + { + t = ip6tc_get_target(e6, h->handle); + + if (*t && !strcmp(t, target)) + { + ip6tc_delete_num_entry(chain, num, h->handle); + found = true; + break; + } + } + } while (found); + } + } + else + { + for (chain = iptc_first_chain(h->handle); + chain != NULL; + chain = iptc_next_chain(h->handle)) + { + do { + found = false; + + for (num = 0, e = iptc_first_rule(chain, h->handle); + e != NULL; + num++, e = iptc_next_rule(e, h->handle)) + { + t = iptc_get_target(e, h->handle); + + if (*t && !strcmp(t, target)) + { + iptc_delete_num_entry(chain, num, h->handle); + found = true; + break; + } + } + } while (found); + } + } +} + +void fw3_ipt_flush(struct fw3_ipt_handle *h) +{ + const char *chain; + + if (h->family == FW3_FAMILY_V6) + { + for (chain = ip6tc_first_chain(h->handle); + chain != NULL; + chain = ip6tc_next_chain(h->handle)) + { + ip6tc_flush_entries(chain, h->handle); + } + + for (chain = ip6tc_first_chain(h->handle); + chain != NULL; + chain = ip6tc_next_chain(h->handle)) + { + ip6tc_delete_chain(chain, h->handle); + } + } + else + { + for (chain = iptc_first_chain(h->handle); + chain != NULL; + chain = iptc_next_chain(h->handle)) + { + iptc_flush_entries(chain, h->handle); + } + + for (chain = iptc_first_chain(h->handle); + chain != NULL; + chain = iptc_next_chain(h->handle)) + { + iptc_delete_chain(chain, h->handle); + } + } +} + +void fw3_ipt_commit(struct fw3_ipt_handle *h) +{ + if (h->family == FW3_FAMILY_V6) + ip6tc_commit(h->handle); + else + iptc_commit(h->handle); + + free(h); +} diff --git a/iptables.h b/iptables.h new file mode 100644 index 0000000..d809c1d --- /dev/null +++ b/iptables.h @@ -0,0 +1,43 @@ +/* + * firewall3 - 3rd OpenWrt UCI firewall implementation + * + * Copyright (C) 2013 Jo-Philipp Wich + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __FW3_IPTABLES_H +#define __FW3_IPTABLES_H + +#include +#include + +#include "options.h" + + +struct fw3_ipt_handle { + enum fw3_family family; + enum fw3_table table; + struct xtc_handle *handle; +}; + +struct fw3_ipt_handle *fw3_ipt_open(enum fw3_family family, enum fw3_table table); + +void fw3_ipt_set_policy(struct fw3_ipt_handle *h, enum fw3_flag policy); +void fw3_ipt_delete_chain(struct fw3_ipt_handle *h, const char *chain); +void fw3_ipt_delete_rules(struct fw3_ipt_handle *h, const char *target); +void fw3_ipt_flush(struct fw3_ipt_handle *h); + +void fw3_ipt_commit(struct fw3_ipt_handle *h); + +#endif diff --git a/main.c b/main.c index a0c8a87..09de782 100644 --- a/main.c +++ b/main.c @@ -28,6 +28,7 @@ #include "ipsets.h" #include "includes.h" #include "ubus.h" +#include "iptables.h" static bool print_rules = false; @@ -183,6 +184,7 @@ stop(bool complete) int rv = 1; enum fw3_family family; enum fw3_table table; + struct fw3_ipt_handle *handle; if (!complete && !run_state) { @@ -200,38 +202,30 @@ stop(bool complete) if (!complete && !family_running(family)) continue; - if (!restore_pipe(family, true)) - continue; - for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++) { if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table])) continue; + if (!(handle = fw3_ipt_open(family, table))) + continue; + info(" * %sing %s %s table", complete ? "Flush" : "Clear", fw3_flag_names[family], fw3_flag_names[table]); - fw3_pr("*%s\n", fw3_flag_names[table]); - if (complete) { - fw3_flush_all(table); + fw3_flush_all(handle); } else if (run_state) { - /* pass 1 */ - fw3_flush_rules(run_state, family, table, false, false); - fw3_flush_zones(run_state, family, table, false, false); - - /* pass 2 */ - fw3_flush_rules(run_state, family, table, false, true); - fw3_flush_zones(run_state, family, table, false, true); + fw3_flush_rules(handle, run_state, false); + fw3_flush_zones(handle, run_state, false); } - fw3_pr("COMMIT\n"); + fw3_ipt_commit(handle); } - fw3_command_close(); family_set(run_state, family, false); family_set(cfg_state, family, false); @@ -345,15 +339,13 @@ reload(void) int rv = 1; enum fw3_family family; enum fw3_table table; + struct fw3_ipt_handle *handle; if (!print_rules && run_state) fw3_hotplug_zones(run_state, false); for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) { - if (!restore_pipe(family, true)) - continue; - if (!family_running(family)) goto start; @@ -362,29 +354,28 @@ reload(void) if (!fw3_has_table(family == FW3_FAMILY_V6, fw3_flag_names[table])) continue; + if (!(handle = fw3_ipt_open(family, table))) + continue; + info(" * Clearing %s %s table", fw3_flag_names[family], fw3_flag_names[table]); - fw3_pr("*%s\n", fw3_flag_names[table]); - if (run_state) { - /* pass 1 */ - fw3_flush_rules(run_state, family, table, true, false); - fw3_flush_zones(run_state, family, table, true, false); - - /* pass 2 */ - fw3_flush_rules(run_state, family, table, true, true); - fw3_flush_zones(run_state, family, table, true, true); + fw3_flush_rules(handle, run_state, true); + fw3_flush_zones(handle, run_state, true); } - fw3_pr("COMMIT\n"); + fw3_ipt_commit(handle); } family_set(run_state, family, false); family_set(cfg_state, family, false); start: + if (!restore_pipe(family, true)) + continue; + if (family == FW3_FAMILY_V6 && cfg_state->defaults.disable_ipv6) goto skip; diff --git a/zones.c b/zones.c index b0fcaee..1fd785b 100644 --- a/zones.c +++ b/zones.c @@ -501,26 +501,36 @@ fw3_print_zone_rules(struct fw3_state *state, enum fw3_family family, } void -fw3_flush_zones(struct fw3_state *state, enum fw3_family family, - enum fw3_table table, bool reload, bool pass2) +fw3_flush_zones(struct fw3_ipt_handle *handle, struct fw3_state *state, + bool reload) { struct fw3_zone *z, *tmp; - uint32_t custom_mask = ~0; - - /* don't touch user chains on selective stop */ - if (reload) - delbit(custom_mask, FW3_FLAG_CUSTOM_CHAINS); + const struct fw3_rule_spec *c; + char chain[32]; list_for_each_entry_safe(z, tmp, &state->zones, list) { - if (!has(z->flags, family, table)) + if (!has(z->flags, handle->family, handle->table)) continue; - fw3_pr_rulespec(table, family, z->flags, custom_mask, zone_chains, - pass2 ? "-X %s\n" : "-F %s\n", z->name); + for (c = zone_chains; c->format; c++) + { + /* don't touch user chains on selective stop */ + if (reload && hasbit(c->flag, FW3_FLAG_CUSTOM_CHAINS)) + continue; + + if (!fw3_is_family(c, handle->family)) + continue; + + if (c->table != handle->table) + continue; + + snprintf(chain, sizeof(chain), c->format, z->name); + fw3_ipt_delete_rules(handle, chain); + fw3_ipt_delete_chain(handle, chain); + } - if (pass2) - del(z->flags, family, table); + del(z->flags, handle->family, handle->table); } } diff --git a/zones.h b/zones.h index dd449a6..353f089 100644 --- a/zones.h +++ b/zones.h @@ -20,6 +20,7 @@ #define __FW3_ZONES_H #include "options.h" +#include "iptables.h" extern const struct fw3_option fw3_zone_opts[]; @@ -33,8 +34,8 @@ void fw3_print_zone_chains(struct fw3_state *state, enum fw3_family family, void fw3_print_zone_rules(struct fw3_state *state, enum fw3_family family, enum fw3_table table, bool reload); -void fw3_flush_zones(struct fw3_state *state, enum fw3_family family, - enum fw3_table table, bool reload, bool pass2); +void fw3_flush_zones(struct fw3_ipt_handle *handle, struct fw3_state *state, + bool reload); void fw3_hotplug_zones(struct fw3_state *state, bool add); -- 2.25.1