#include "zones.h"
#include "ubus.h"
+#include "helpers.h"
#define C(f, tbl, tgt, fmt) \
C(V4, NAT, SNAT, "zone_%s_postrouting"),
C(V4, NAT, DNAT, "zone_%s_prerouting"),
+ C(ANY, RAW, HELPER, "zone_%s_helper"),
C(ANY, RAW, NOTRACK, "zone_%s_notrack"),
C(ANY, FILTER, CUSTOM_CHAINS, "input_%s_rule"),
FW3_OPT("log", bool, zone, log),
FW3_OPT("log_limit", limit, zone, log_limit),
+ FW3_OPT("auto_helper", bool, zone, auto_helper),
+ FW3_LIST("helper", cthelper, zone, cthelpers),
+
FW3_OPT("__flags_v4", int, zone, flags[0]),
FW3_OPT("__flags_v6", int, zone, flags[1]),
}
}
+static void
+resolve_cthelpers(struct fw3_state *s, struct uci_element *e, struct fw3_zone *zone)
+{
+ struct fw3_cthelpermatch *match;
+
+ if (list_empty(&zone->cthelpers))
+ {
+ if (!zone->masq && zone->auto_helper)
+ {
+ fw3_setbit(zone->flags[0], FW3_FLAG_HELPER);
+ fw3_setbit(zone->flags[1], FW3_FLAG_HELPER);
+ }
+
+ return;
+ }
+
+ list_for_each_entry(match, &zone->cthelpers, list)
+ {
+ if (match->invert)
+ {
+ warn_elem(e, "must not use a negated helper match");
+ continue;
+ }
+
+ match->ptr = fw3_lookup_cthelper(s, match->name);
+
+ if (!match->ptr)
+ {
+ warn_elem(e, "refers to not existing helper '%s'", match->name);
+ continue;
+ }
+
+ if (fw3_is_family(match->ptr, FW3_FAMILY_V4))
+ fw3_setbit(zone->flags[0], FW3_FLAG_HELPER);
+
+ if (fw3_is_family(match->ptr, FW3_FAMILY_V6))
+ fw3_setbit(zone->flags[1], FW3_FLAG_HELPER);
+ }
+}
+
struct fw3_zone *
fw3_alloc_zone(void)
{
INIT_LIST_HEAD(&zone->subnets);
INIT_LIST_HEAD(&zone->masq_src);
INIT_LIST_HEAD(&zone->masq_dest);
+ INIT_LIST_HEAD(&zone->cthelpers);
INIT_LIST_HEAD(&zone->old_addrs);
zone->enabled = true;
+ zone->auto_helper = true;
zone->custom_chains = true;
zone->log_limit.rate = 10;
if (!defs->custom_chains && zone->custom_chains)
zone->custom_chains = false;
+ if (!defs->auto_helper && zone->auto_helper)
+ zone->auto_helper = false;
+
if (!zone->name || !*zone->name)
{
warn_elem(e, "has no name - ignoring");
fw3_setbit(zone->flags[0], FW3_FLAG_DNAT);
}
+ resolve_cthelpers(state, e, zone);
+
fw3_setbit(zone->flags[0], fw3_to_src_target(zone->policy_input));
fw3_setbit(zone->flags[0], zone->policy_forward);
fw3_setbit(zone->flags[0], zone->policy_output);
if (!fw3_is_family(zone, handle->family))
return;
- info(" * Zone '%s'", zone->name);
-
set(zone->flags, handle->family, handle->table);
if (zone->custom_chains)
}
else if (handle->table == FW3_TABLE_RAW)
{
+ if (has(zone->flags, handle->family, FW3_FLAG_HELPER))
+ {
+ r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
+ fw3_ipt_rule_comment(r, "%s CT helper assignment", zone->name);
+ fw3_ipt_rule_target(r, "zone_%s_helper", zone->name);
+ fw3_ipt_rule_extra(r, zone->extra_src);
+ fw3_ipt_rule_replace(r, "PREROUTING");
+ }
+
if (has(zone->flags, handle->family, FW3_FLAG_NOTRACK))
{
r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
+ fw3_ipt_rule_comment(r, "%s CT bypass", zone->name);
fw3_ipt_rule_target(r, "zone_%s_notrack", zone->name);
fw3_ipt_rule_extra(r, zone->extra_src);
fw3_ipt_rule_replace(r, "PREROUTING");
if (!fw3_is_family(zone, handle->family))
return;
+ info(" * Zone '%s'", zone->name);
+
switch (handle->table)
{
case FW3_TABLE_FILTER:
break;
case FW3_TABLE_RAW:
+ fw3_print_cthelpers(handle, state, zone);
+ break;
+
case FW3_TABLE_MANGLE:
break;
}