C(V4, NAT, SNAT, "zone_%s_postrouting"),
C(V4, NAT, DNAT, "zone_%s_prerouting"),
- C(ANY, RAW, NOTRACK, "zone_%s_notrack"),
+ 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"),
};
-static struct fw3_option zone_opts[] = {
+const struct fw3_option fw3_zone_opts[] = {
+ FW3_OPT("enabled", bool, zone, enabled),
+
FW3_OPT("name", string, zone, name),
FW3_OPT("family", family, zone, family),
FW3_OPT("log", bool, zone, log),
FW3_OPT("log_limit", limit, zone, log_limit),
+
+ { }
};
INIT_LIST_HEAD(&zone->masq_src);
INIT_LIST_HEAD(&zone->masq_dest);
+ zone->enabled = true;
+ zone->custom_chains = true;
zone->log_limit.rate = 10;
return zone;
if (!zone)
continue;
- fw3_parse_options(zone, zone_opts, ARRAY_SIZE(zone_opts), s);
+ fw3_parse_options(zone, fw3_zone_opts, s);
+
+ if (!zone->enabled)
+ {
+ fw3_free_zone(zone);
+ continue;
+ }
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");
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);
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)
{
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)
{
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);
}
}
return NULL;
}
-
-void
-fw3_free_zone(struct fw3_zone *zone)
-{
- fw3_free_list(&zone->networks);
- fw3_free_list(&zone->devices);
- fw3_free_list(&zone->subnets);
-
- fw3_free_list(&zone->masq_src);
- fw3_free_list(&zone->masq_dest);
-
- free(zone);
-}