From b2b2e69b19a20a46f3db6d717a899248fa24628c Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 7 Mar 2013 14:34:02 +0100 Subject: [PATCH] add support for per-zone user chains --- defaults.c | 18 ++++++++++----- main.c | 4 ++-- options.h | 15 +++++++------ zones.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ zones.h | 2 +- 5 files changed, 93 insertions(+), 22 deletions(-) diff --git a/defaults.c b/defaults.c index 7f32728..973b3a7 100644 --- a/defaults.c +++ b/defaults.c @@ -223,9 +223,14 @@ fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family, if (defs->custom_chains) { - fw3_pr("-A delegate_input -j input_rule\n"); - fw3_pr("-A delegate_output -j output_rule\n"); - fw3_pr("-A delegate_forward -j forwarding_rule\n"); + fw3_pr("-A delegate_input -j input_rule " + "-m comment --comment \"user chain for input\"\n"); + + fw3_pr("-A delegate_output -j output_rule " + "-m comment --comment \"user chain for output\"\n"); + + fw3_pr("-A delegate_forward -j forwarding_rule " + "-m comment --comment \"user chain for forwarding\"\n"); } for (i = 0; i < ARRAY_SIZE(chains); i++) @@ -258,8 +263,11 @@ fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family, case FW3_TABLE_NAT: if (defs->custom_chains) { - fw3_pr("-A delegate_prerouting -j prerouting_rule\n"); - fw3_pr("-A delegate_postrouting -j postrouting_rule\n"); + fw3_pr("-A delegate_prerouting -j prerouting_rule " + "-m comment --comment \"user chain for prerouting\"\n"); + + fw3_pr("-A delegate_postrouting -j postrouting_rule " + "-m comment --comment \"user chain for postrouting\"\n"); } break; diff --git a/main.c b/main.c index 79d3b0b..cd821fc 100644 --- a/main.c +++ b/main.c @@ -206,11 +206,11 @@ stop(struct fw3_state *state, bool complete, bool reload) { /* pass 1 */ fw3_flush_rules(table, family, false, state, policy); - fw3_flush_zones(table, family, false, state); + fw3_flush_zones(table, family, false, reload, state); /* pass 2 */ fw3_flush_rules(table, family, true, state, policy); - fw3_flush_zones(table, family, true, state); + fw3_flush_zones(table, family, true, reload, state); } fw3_pr("COMMIT\n"); diff --git a/options.h b/options.h index 2af443b..7881375 100644 --- a/options.h +++ b/options.h @@ -63,13 +63,14 @@ enum fw3_family enum fw3_target { - FW3_TARGET_UNSPEC = 0, - FW3_TARGET_ACCEPT = 6, - FW3_TARGET_REJECT = 7, - FW3_TARGET_DROP = 8, - FW3_TARGET_NOTRACK = 9, - FW3_TARGET_DNAT = 10, - FW3_TARGET_SNAT = 11, + FW3_TARGET_UNSPEC = 0, + FW3_TARGET_ACCEPT = 6, + FW3_TARGET_REJECT = 7, + FW3_TARGET_DROP = 8, + FW3_TARGET_NOTRACK = 9, + FW3_TARGET_DNAT = 10, + FW3_TARGET_SNAT = 11, + FW3_TARGET_CUSTOM_CHAINS = 12, /* alias to FW3_DEFAULT_CUSTOM_CHAINS */ }; enum fw3_default diff --git a/zones.c b/zones.c index 82b76b4..c81125f 100644 --- a/zones.c +++ b/zones.c @@ -47,6 +47,13 @@ static const struct chain dst_chains[] = { C(V4, NAT, SNAT, "zone_%s_postrouting"), C(V4, NAT, DNAT, "zone_%s_prerouting"), + + C(ANY, FILTER, CUSTOM_CHAINS, "input_%s_rule"), + C(ANY, FILTER, CUSTOM_CHAINS, "output_%s_rule"), + C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_%s_rule"), + + C(V4, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"), + C(V4, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"), }; const struct fw3_option fw3_zone_opts[] = { @@ -165,6 +172,7 @@ fw3_alloc_zone(void) INIT_LIST_HEAD(&zone->masq_dest); zone->enabled = true; + zone->custom_chains = true; zone->log_limit.rate = 10; return zone; @@ -203,6 +211,9 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) if (!zone->extra_dest) zone->extra_dest = zone->extra_src; + if (!defs->custom_chains && zone->custom_chains) + zone->custom_chains = false; + if (!zone->name || !*zone->name) { warn_elem(e, "has no name - ignoring"); @@ -228,6 +239,12 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) zone->conntrack = true; } + if (zone->custom_chains) + { + setbit(zone->dst_flags, FW3_TARGET_SNAT); + setbit(zone->dst_flags, FW3_TARGET_DNAT); + } + setbit(zone->src_flags, zone->policy_input); setbit(zone->dst_flags, zone->policy_output); setbit(zone->dst_flags, zone->policy_forward); @@ -242,20 +259,58 @@ print_zone_chain(enum fw3_table table, enum fw3_family family, struct fw3_zone *zone, struct fw3_state *state) { bool s, d; + uint16_t mask = ~0; if (!fw3_is_family(zone, family)) return; setbit(zone->dst_flags, family); + /* user chains already loaded, don't create again */ + if (hasbit(zone->dst_flags, FW3_TARGET_CUSTOM_CHAINS)) + delbit(mask, FW3_TARGET_CUSTOM_CHAINS); + + if (zone->custom_chains) + setbit(zone->dst_flags, FW3_TARGET_CUSTOM_CHAINS); + 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, - zone->src_flags, src_chains, ARRAY_SIZE(src_chains)); + zone->src_flags & mask, + src_chains, ARRAY_SIZE(src_chains)); d = print_chains(table, family, ":%s - [0:0]\n", zone->name, - zone->dst_flags, dst_chains, ARRAY_SIZE(dst_chains)); + zone->dst_flags & mask, + dst_chains, ARRAY_SIZE(dst_chains)); + + if (zone->custom_chains) + { + if (table == FW3_TABLE_FILTER) + { + fw3_pr("-A zone_%s_input -j input_%s_rule " + "-m comment --comment \"user chain for %s input\"\n", + zone->name, zone->name, zone->name); + + fw3_pr("-A zone_%s_output -j output_%s_rule " + "-m comment --comment \"user chain for %s output\"\n", + zone->name, zone->name, zone->name); + + fw3_pr("-A zone_%s_forward -j forwarding_%s_rule " + "-m comment --comment \"user chain for %s forwarding\"\n", + zone->name, zone->name, zone->name); + } + else if (table == FW3_TABLE_NAT) + { + fw3_pr("-A zone_%s_prerouting -j prerouting_%s_rule " + "-m comment --comment \"user chain for %s prerouting\"\n", + zone->name, zone->name, zone->name); + + fw3_pr("-A zone_%s_postrouting -j postrouting_%s_rule " + "-m comment --comment \"user chain for %s postrouting\"\n", + zone->name, zone->name, zone->name); + } + } if (s || d) { @@ -482,10 +537,15 @@ 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 fw3_state *state) + bool pass2, bool reload, struct fw3_state *state) { struct fw3_zone *z, *tmp; - int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); + uint16_t mask = ~0; + uint16_t families = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); + + /* don't touch user chains on selective stop */ + if (reload) + delbit(mask, FW3_DEFAULT_CUSTOM_CHAINS); list_for_each_entry_safe(z, tmp, &state->running_zones, running_list) { @@ -493,16 +553,18 @@ fw3_flush_zones(enum fw3_table table, enum fw3_family family, continue; print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n", - z->name, z->src_flags, src_chains, ARRAY_SIZE(src_chains)); + z->name, z->src_flags & mask, + src_chains, ARRAY_SIZE(src_chains)); print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n", - z->name, z->dst_flags, dst_chains, ARRAY_SIZE(dst_chains)); + z->name, z->dst_flags & mask, + dst_chains, ARRAY_SIZE(dst_chains)); if (pass2) { delbit(z->dst_flags, family); - if (!(z->dst_flags & mask)) + if (!(z->dst_flags & families)) fw3_set_running(z, NULL); } } diff --git a/zones.h b/zones.h index 84619c2..be331df 100644 --- a/zones.h +++ b/zones.h @@ -34,7 +34,7 @@ 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 fw3_state *state); + bool pass2, bool reload, struct fw3_state *state); struct fw3_zone * fw3_lookup_zone(struct fw3_state *state, const char *name, bool running); -- 2.11.0