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)
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);
}
#define __FW3_DEFAULTS_H
#include "options.h"
+#include "iptables.h"
extern const struct fw3_option fw3_flag_opts[];
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
--- /dev/null
+/*
+ * firewall3 - 3rd OpenWrt UCI firewall implementation
+ *
+ * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * 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);
+}
--- /dev/null
+/*
+ * firewall3 - 3rd OpenWrt UCI firewall implementation
+ *
+ * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * 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 <libiptc/libiptc.h>
+#include <libiptc/libip6tc.h>
+
+#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
#include "ipsets.h"
#include "includes.h"
#include "ubus.h"
+#include "iptables.h"
static bool print_rules = false;
int rv = 1;
enum fw3_family family;
enum fw3_table table;
+ struct fw3_ipt_handle *handle;
if (!complete && !run_state)
{
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);
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;
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;
}
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);
}
}
#define __FW3_ZONES_H
#include "options.h"
+#include "iptables.h"
extern const struct fw3_option fw3_zone_opts[];
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);