@@ -29,8 +29,8 @@ static const struct fw3_chain_spec default_chains[] = {
C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"),
C(ANY, FILTER, SYN_FLOOD, "syn_flood"),
- C(V4, NAT, CUSTOM_CHAINS, "prerouting_rule"),
- C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"),
+ C(ANY, NAT, CUSTOM_CHAINS, "prerouting_rule"),
+ C(ANY, NAT, CUSTOM_CHAINS, "postrouting_rule"),
{ }
};
@@ -420,14 +420,14 @@ struct fw3_redirect
struct list_head proto;
- struct fw3_address ip_src;
+ struct list_head ip_src;
struct list_head mac_src;
struct fw3_port port_src;
- struct fw3_address ip_dest;
+ struct list_head ip_dest;
struct fw3_port port_dest;
- struct fw3_address ip_redir;
+ struct list_head ip_redir;
struct fw3_port port_redir;
struct fw3_limit limit;
@@ -462,13 +462,13 @@ struct fw3_snat
struct list_head proto;
- struct fw3_address ip_src;
+ struct list_head ip_src;
struct fw3_port port_src;
- struct fw3_address ip_dest;
+ struct list_head ip_dest;
struct fw3_port port_dest;
- struct fw3_address ip_snat;
+ struct list_head ip_snat;
struct fw3_port port_snat;
struct fw3_limit limit;
@@ -33,14 +33,14 @@ const struct fw3_option fw3_redirect_opts[] = {
FW3_LIST("proto", protocol, redirect, proto),
- FW3_OPT("src_ip", network, redirect, ip_src),
+ FW3_LIST("src_ip", network, redirect, ip_src),
FW3_LIST("src_mac", mac, redirect, mac_src),
FW3_OPT("src_port", port, redirect, port_src),
- FW3_OPT("src_dip", network, redirect, ip_dest),
+ FW3_LIST("src_dip", network, redirect, ip_dest),
FW3_OPT("src_dport", port, redirect, port_dest),
- FW3_OPT("dest_ip", network, redirect, ip_redir),
+ FW3_LIST("dest_ip", network, redirect, ip_redir),
FW3_OPT("dest_port", port, redirect, port_redir),
FW3_OPT("extra", string, redirect, extra),
@@ -68,7 +68,6 @@ const struct fw3_option fw3_redirect_opts[] = {
{ }
};
-
static bool
check_families(struct uci_element *e, struct fw3_redirect *r)
{
@@ -101,19 +100,19 @@ check_families(struct uci_element *e, struct fw3_redirect *r)
return false;
}
- if (r->ip_src.family && r->ip_src.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_src, r->family))
{
warn_elem(e, "uses source ip with different family");
return false;
}
- if (r->ip_dest.family && r->ip_dest.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_dest, r->family))
{
warn_elem(e, "uses destination ip with different family");
return false;
}
- if (r->ip_redir.family && r->ip_redir.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_redir, r->family))
{
warn_elem(e, "uses redirect ip with different family");
return false;
@@ -125,11 +124,21 @@ check_families(struct uci_element *e, struct fw3_redirect *r)
static bool
compare_addr(struct fw3_address *a, struct fw3_address *b)
{
- if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4)
+ if (a->family != b->family)
return false;
- return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
- (b->address.v4.s_addr & a->mask.v4.s_addr));
+ return (a->family == FW3_FAMILY_V4 &&
+ (a->address.v4.s_addr & a->mask.v4.s_addr) ==
+ (b->address.v4.s_addr & b->mask.v4.s_addr)) ||
+ (a->family == FW3_FAMILY_V6 &&
+ (a->address.v6.s6_addr32[0] & a->mask.v6.s6_addr32[0]) ==
+ (b->address.v6.s6_addr32[0] & b->mask.v6.s6_addr32[0]) &&
+ (a->address.v6.s6_addr32[1] & a->mask.v6.s6_addr32[1]) ==
+ (b->address.v6.s6_addr32[1] & b->mask.v6.s6_addr32[1]) &&
+ (a->address.v6.s6_addr32[2] & a->mask.v6.s6_addr32[2]) ==
+ (b->address.v6.s6_addr32[2] & b->mask.v6.s6_addr32[2]) &&
+ (a->address.v6.s6_addr32[3] & a->mask.v6.s6_addr32[3]) ==
+ (b->address.v6.s6_addr32[3] & b->mask.v6.s6_addr32[3]));
}
static bool
@@ -139,8 +148,9 @@ resolve_dest(struct uci_element *e, struct fw3_redirect *redir,
struct fw3_zone *zone;
struct fw3_address *addr;
struct list_head *addrs;
+ struct fw3_address *ip_redir = list_first_entry(&redir->ip_redir, struct fw3_address, list);
- if (!redir->ip_redir.set)
+ if (!ip_redir->set)
return false;
list_for_each_entry(zone, &state->zones, list)
@@ -152,7 +162,7 @@ resolve_dest(struct uci_element *e, struct fw3_redirect *redir,
list_for_each_entry(addr, addrs, list)
{
- if (!compare_addr(addr, &redir->ip_redir))
+ if (!compare_addr(addr, ip_redir))
continue;
strncpy(redir->dest.name, zone->name, sizeof(redir->dest.name) - 1);
@@ -175,10 +185,12 @@ static bool
check_local(struct uci_element *e, struct fw3_redirect *redir,
struct fw3_state *state)
{
+ struct fw3_address *ip_redir = list_first_entry(&redir->ip_redir, struct fw3_address, list);
+
if (redir->target != FW3_FLAG_DNAT)
return false;
- if (!redir->ip_redir.set)
+ if (!ip_redir->set)
redir->local = true;
return redir->local;
@@ -300,6 +312,7 @@ check_redirect(struct fw3_state *state, struct fw3_redirect *redir, struct uci_e
else
{
set(redir->_src->flags, FW3_FAMILY_V4, redir->target);
+ set(redir->_src->flags, FW3_FAMILY_V6, redir->target);
valid = true;
if (!check_local(e, redir, state) && !redir->dest.set &&
@@ -318,7 +331,10 @@ check_redirect(struct fw3_state *state, struct fw3_redirect *redir, struct uci_e
}
if (redir->helper.ptr)
+ {
set(redir->_src->flags, FW3_FAMILY_V4, FW3_FLAG_HELPER);
+ set(redir->_src->flags, FW3_FAMILY_V6, FW3_FLAG_HELPER);
+ }
}
}
else
@@ -328,7 +344,7 @@ check_redirect(struct fw3_state *state, struct fw3_redirect *redir, struct uci_e
"must not have destination '*' for SNAT target");
else if (!redir->_dest)
warn_section("redirect", redir, e, "has no destination specified");
- else if (!redir->ip_dest.set)
+ else if (list_empty(&redir->ip_dest))
warn_section("redirect", redir, e, "has no src_dip option specified");
else if (!list_empty(&redir->mac_src))
warn_section("redirect", redir, e, "must not use 'src_mac' option for SNAT target");
@@ -337,6 +353,7 @@ check_redirect(struct fw3_state *state, struct fw3_redirect *redir, struct uci_e
else
{
set(redir->_dest->flags, FW3_FAMILY_V4, redir->target);
+ set(redir->_dest->flags, FW3_FAMILY_V6, redir->target);
valid = true;
}
}
@@ -366,7 +383,10 @@ fw3_alloc_redirect(struct fw3_state *state)
return NULL;
INIT_LIST_HEAD(&redir->proto);
+ INIT_LIST_HEAD(&redir->ip_src);
INIT_LIST_HEAD(&redir->mac_src);
+ INIT_LIST_HEAD(&redir->ip_dest);
+ INIT_LIST_HEAD(&redir->ip_redir);
INIT_LIST_HEAD(&redir->reflection_zones);
redir->enabled = true;
@@ -477,13 +497,26 @@ static void
set_snat_dnat(struct fw3_ipt_rule *r, enum fw3_flag target,
struct fw3_address *addr, struct fw3_port *port)
{
- char buf[sizeof("255.255.255.255:65535-65535\0")];
+ char buf[sizeof("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535-65535\0")];
buf[0] = '\0';
if (addr && addr->set)
{
- inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf));
+ if (addr->family == FW3_FAMILY_V4)
+ inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf));
+ else
+ {
+ int len;
+
+ buf[0] = '[';
+ if (inet_ntop(AF_INET6, &addr->address.v6, buf + 1, sizeof(buf) - 2))
+ len = strlen(buf);
+ else
+ len = 1;
+ buf[len++]= ']';
+ buf[len] = '\0';
+ }
}
if (port && port->set)
@@ -508,17 +541,6 @@ set_snat_dnat(struct fw3_ipt_rule *r, enum fw3_flag target,
}
static void
-set_target_nat(struct fw3_ipt_rule *r, struct fw3_redirect *redir)
-{
- if (redir->local)
- set_redirect(r, &redir->port_redir);
- else if (redir->target == FW3_FLAG_DNAT)
- set_snat_dnat(r, redir->target, &redir->ip_redir, &redir->port_redir);
- else
- set_snat_dnat(r, redir->target, &redir->ip_dest, &redir->port_dest);
-}
-
-static void
set_comment(struct fw3_ipt_rule *r, const char *name, int num, const char *suffix)
{
if (name)
@@ -543,32 +565,41 @@ print_redirect(struct fw3_ipt_handle *h, struct fw3_state *state,
struct fw3_protocol *proto, struct fw3_mac *mac)
{
struct fw3_ipt_rule *r;
- struct fw3_address *src, *dst;
- struct fw3_port *spt, *dpt;
+ struct fw3_address *src, *dst, *rdr;
+ struct fw3_port *spt, *dpt, *rpt;
switch (h->table)
{
case FW3_TABLE_NAT:
- src = &redir->ip_src;
- dst = &redir->ip_dest;
- spt = &redir->port_src;
- dpt = &redir->port_dest;
-
- if (redir->target == FW3_FLAG_SNAT)
+ src = fw3_first_family_addr(&redir->ip_src, h->family);
+ dst = fw3_first_family_addr(&redir->ip_dest, h->family);
+ rdr = fw3_first_family_addr(&redir->ip_redir, h->family);
+ if ((src == NULL && !list_empty(&redir->ip_src)) ||
+ (dst == NULL && !list_empty(&redir->ip_dest)) ||
+ (rdr == NULL && !list_empty(&redir->ip_redir)))
{
- dst = &redir->ip_redir;
- dpt = &redir->port_redir;
+ info(" ! Skipping due to different family of ip address");
+ return;
}
- r = fw3_ipt_rule_create(h, proto, NULL, NULL, src, dst);
- fw3_ipt_rule_sport_dport(r, spt, dpt);
+ spt = &redir->port_src;
+ dpt = &redir->port_dest;
+ rpt = &redir->port_redir;
+
+ r = fw3_ipt_rule_create(h, proto, NULL, NULL, src, redir->target == FW3_FLAG_SNAT ? rdr : dst);
+ fw3_ipt_rule_sport_dport(r, spt, redir->target == FW3_FLAG_SNAT ? rpt : dpt);
fw3_ipt_rule_mac(r, mac);
fw3_ipt_rule_ipset(r, &redir->ipset);
fw3_ipt_rule_helper(r, &redir->helper);
fw3_ipt_rule_limit(r, &redir->limit);
fw3_ipt_rule_time(r, &redir->time);
fw3_ipt_rule_mark(r, &redir->mark);
- set_target_nat(r, redir);
+ if (redir->local)
+ set_redirect(r, rpt);
+ else if (redir->target == FW3_FLAG_DNAT)
+ set_snat_dnat(r, redir->target, rdr, rpt);
+ else
+ set_snat_dnat(r, redir->target, dst, dpt);
fw3_ipt_rule_extra(r, redir->extra);
set_comment(r, redir->name, num, NULL);
append_chain_nat(r, redir);
@@ -577,6 +608,15 @@ print_redirect(struct fw3_ipt_handle *h, struct fw3_state *state,
case FW3_TABLE_RAW:
if (redir->target == FW3_FLAG_DNAT && redir->helper.ptr)
{
+ src = fw3_first_family_addr(&redir->ip_src, h->family);
+ rdr = fw3_first_family_addr(&redir->ip_redir, h->family);
+ if ((src == NULL && !list_empty(&redir->ip_src)) ||
+ (rdr == NULL && !list_empty(&redir->ip_redir)))
+ {
+ info(" ! Skipping due to different family of ip address");
+ return;
+ }
+
if (!fw3_cthelper_check_proto(redir->helper.ptr, proto))
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
@@ -588,7 +628,7 @@ print_redirect(struct fw3_ipt_handle *h, struct fw3_state *state,
info(" - Auto-selected conntrack helper '%s' based on proto/port",
redir->helper.ptr->name);
- r = fw3_ipt_rule_create(h, proto, NULL, NULL, &redir->ip_src, &redir->ip_redir);
+ r = fw3_ipt_rule_create(h, proto, NULL, NULL, src, rdr);
fw3_ipt_rule_sport_dport(r, &redir->port_src, &redir->port_redir);
fw3_ipt_rule_mac(r, mac);
fw3_ipt_rule_ipset(r, &redir->ipset);
@@ -616,19 +656,26 @@ print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
struct fw3_address *ia, struct fw3_address *ea, struct fw3_device *rz)
{
struct fw3_ipt_rule *r;
+ struct fw3_address *rdr;
switch (h->table)
{
case FW3_TABLE_NAT:
+ rdr = fw3_first_family_addr(&redir->ip_redir, h->family);
+ if (rdr == NULL && !list_empty(&redir->ip_redir))
+ {
+ info(" ! Skipping reflection due to different family of dest_ip");
+ return;
+ }
r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, ea);
fw3_ipt_rule_sport_dport(r, NULL, &redir->port_dest);
fw3_ipt_rule_limit(r, &redir->limit);
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, "reflection");
- set_snat_dnat(r, FW3_FLAG_DNAT, &redir->ip_redir, &redir->port_redir);
+ set_snat_dnat(r, FW3_FLAG_DNAT, rdr, &redir->port_redir);
fw3_ipt_rule_replace(r, "zone_%s_prerouting", rz->name);
- r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, &redir->ip_redir);
+ r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, rdr);
fw3_ipt_rule_sport_dport(r, NULL, &redir->port_redir);
fw3_ipt_rule_limit(r, &redir->limit);
fw3_ipt_rule_time(r, &redir->time);
@@ -653,6 +700,9 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_device *reflection_zone;
struct fw3_zone *zone;
+ if (!fw3_is_family(redir, handle->family))
+ return;
+
if (redir->name)
info(" * Redirect '%s'", redir->name);
else
@@ -665,15 +715,11 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
return;
}
- if (!fw3_is_family(&redir->ip_src, handle->family) ||
- !fw3_is_family(&redir->ip_dest, handle->family) ||
- !fw3_is_family(&redir->ip_redir, handle->family))
+ if (!fw3_check_family_addr(&redir->ip_src, handle->family) ||
+ !fw3_check_family_addr(&redir->ip_dest, handle->family) ||
+ !fw3_check_family_addr(&redir->ip_redir, handle->family))
{
- if (!redir->ip_src.resolved ||
- !redir->ip_dest.resolved ||
- !redir->ip_redir.resolved)
- info(" ! Skipping due to different family of ip address");
-
+ info(" ! Skipping due to different family of ip address");
return;
}
@@ -701,13 +747,13 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
print_redirect(handle, state, redir, num, proto, mac);
/* reflection rules */
- if (redir->target != FW3_FLAG_DNAT || !redir->reflection || redir->local)
+ if (redir->target != FW3_FLAG_DNAT || !redir->reflection || redir->local || handle->family != FW3_FAMILY_V4)
return;
if (!redir->_dest || !redir->_src->masq)
return;
- ext_addrs = fw3_resolve_zone_addresses(redir->_src, &redir->ip_dest);
+ ext_addrs = fw3_resolve_zone_addresses(redir->_src, fw3_first_family_addr(&redir->ip_dest, handle->family));
if (!ext_addrs)
goto out;
@@ -769,9 +815,6 @@ fw3_print_redirects(struct fw3_ipt_handle *handle, struct fw3_state *state)
int num = 0;
struct fw3_redirect *redir;
- if (handle->family == FW3_FAMILY_V6)
- return;
-
if (handle->table != FW3_TABLE_FILTER &&
handle->table != FW3_TABLE_NAT &&
handle->table != FW3_TABLE_RAW)
@@ -23,7 +23,7 @@
#include "zones.h"
#include "ipsets.h"
#include "helpers.h"
-#include "ubus.h"
+#include "utils.h"
#include "iptables.h"
extern const struct fw3_option fw3_redirect_opts[];
@@ -32,13 +32,13 @@ const struct fw3_option fw3_snat_opts[] = {
FW3_LIST("proto", protocol, snat, proto),
- FW3_OPT("src_ip", network, snat, ip_src),
+ FW3_LIST("src_ip", network, snat, ip_src),
FW3_OPT("src_port", port, snat, port_src),
- FW3_OPT("snat_ip", network, snat, ip_snat),
+ FW3_LIST("snat_ip", network, snat, ip_snat),
FW3_OPT("snat_port", port, snat, port_snat),
- FW3_OPT("dest_ip", network, snat, ip_dest),
+ FW3_LIST("dest_ip", network, snat, ip_dest),
FW3_OPT("dest_port", port, snat, port_dest),
FW3_OPT("extra", string, snat, extra),
@@ -83,19 +83,19 @@ check_families(struct uci_element *e, struct fw3_snat *r)
return false;
}
- if (r->ip_src.family && r->ip_src.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_src, r->family))
{
warn_section("nat", r, e, "uses source ip with different family");
return false;
}
- if (r->ip_dest.family && r->ip_dest.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_dest, r->family))
{
warn_section("nat", r, e, "uses destination ip with different family");
return false;
}
- if (r->ip_snat.family && r->ip_snat.family != r->family)
+ if (!fw3_check_family_addr(&r->ip_snat, r->family))
{
warn_section("nat", r, e, "uses snat ip with different family");
return false;
@@ -112,6 +112,9 @@ alloc_snat(struct fw3_state *state)
if (snat) {
INIT_LIST_HEAD(&snat->proto);
+ INIT_LIST_HEAD(&snat->ip_src);
+ INIT_LIST_HEAD(&snat->ip_dest);
+ INIT_LIST_HEAD(&snat->ip_snat);
list_add_tail(&snat->list, &state->snats);
snat->enabled = true;
}
@@ -164,12 +167,12 @@ check_snat(struct fw3_state *state, struct fw3_snat *snat, struct uci_element *e
}
if (snat->target == FW3_FLAG_SNAT &&
- !snat->ip_snat.set && !snat->port_snat.set)
+ list_empty(&snat->ip_snat) && !snat->port_snat.set)
{
warn_section("nat", snat, e, "needs either 'snat_ip' or 'snat_port' for SNAT");
return false;
}
- else if (snat->target != FW3_FLAG_SNAT && snat->ip_snat.set)
+ else if (snat->target != FW3_FLAG_SNAT && !list_empty(&snat->ip_snat))
{
warn_section("nat", snat, e, "must not use 'snat_ip' for non-SNAT");
return false;
@@ -187,7 +190,10 @@ check_snat(struct fw3_state *state, struct fw3_snat *snat, struct uci_element *e
}
if (snat->_src)
+ {
set(snat->_src->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT);
+ set(snat->_src->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT);
+ }
return true;
}
@@ -262,18 +268,31 @@ append_chain(struct fw3_ipt_rule *r, struct fw3_snat *snat)
}
static void
-set_target(struct fw3_ipt_rule *r, struct fw3_snat *snat,
+set_target(struct fw3_ipt_rule *r, struct fw3_snat *snat, struct fw3_address *snat_addr,
struct fw3_protocol *proto)
{
- char buf[sizeof("255.255.255.255:65535-65535\0")];
+ char buf[sizeof("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535-65535\0")];
if (snat->target == FW3_FLAG_SNAT)
{
buf[0] = '\0';
- if (snat->ip_snat.set)
+ if (snat_addr && snat_addr->set)
{
- inet_ntop(AF_INET, &snat->ip_snat.address.v4, buf, sizeof(buf));
+ if (snat_addr->family == FW3_FAMILY_V4)
+ inet_ntop(AF_INET, &snat_addr->address.v4, buf, sizeof(buf));
+ else
+ {
+ int len;
+
+ buf[0] = '[';
+ if (inet_ntop(AF_INET6, &snat_addr->address.v6, buf + 1, sizeof(buf) - 2))
+ len = strlen(buf);
+ else
+ len = 1;
+ buf[len++]= ']';
+ buf[len] = '\0';
+ }
}
if (snat->port_snat.set && proto && !proto->any &&
@@ -323,14 +342,23 @@ print_snat(struct fw3_ipt_handle *h, struct fw3_state *state,
struct fw3_snat *snat, int num, struct fw3_protocol *proto)
{
struct fw3_ipt_rule *r;
- struct fw3_address *src, *dst;
+ struct fw3_address *src, *dst, *snt;
struct fw3_port *spt, *dpt;
switch (h->table)
{
case FW3_TABLE_NAT:
- src = &snat->ip_src;
- dst = &snat->ip_dest;
+ src = fw3_first_family_addr(&snat->ip_src, h->family);
+ dst = fw3_first_family_addr(&snat->ip_dest, h->family);
+ snt = fw3_first_family_addr(&snat->ip_snat, h->family);
+ if ((src == NULL && !list_empty(&snat->ip_src)) ||
+ (dst == NULL && !list_empty(&snat->ip_dest)) ||
+ (snt == NULL && !list_empty(&snat->ip_snat)))
+ {
+ info(" ! Skipping due to different family of ip address");
+ return;
+ }
+
spt = &snat->port_src;
dpt = &snat->port_dest;
@@ -341,7 +369,7 @@ print_snat(struct fw3_ipt_handle *h, struct fw3_state *state,
fw3_ipt_rule_limit(r, &snat->limit);
fw3_ipt_rule_time(r, &snat->time);
fw3_ipt_rule_mark(r, &snat->mark);
- set_target(r, snat, proto);
+ set_target(r, snat, snt, proto);
fw3_ipt_rule_extra(r, snat->extra);
set_comment(r, snat->name, num);
append_chain(r, snat);
@@ -358,6 +386,9 @@ expand_snat(struct fw3_ipt_handle *handle, struct fw3_state *state,
{
struct fw3_protocol *proto;
+ if (!fw3_is_family(snat, handle->family))
+ return;
+
if (snat->name)
info(" * NAT '%s'", snat->name);
else
@@ -369,15 +400,11 @@ expand_snat(struct fw3_ipt_handle *handle, struct fw3_state *state,
return;
}
- if (!fw3_is_family(&snat->ip_src, handle->family) ||
- !fw3_is_family(&snat->ip_dest, handle->family) ||
- !fw3_is_family(&snat->ip_snat, handle->family))
+ if (!fw3_check_family_addr(&snat->ip_src, handle->family) ||
+ !fw3_check_family_addr(&snat->ip_dest, handle->family) ||
+ !fw3_check_family_addr(&snat->ip_snat, handle->family))
{
- if (!snat->ip_src.resolved ||
- !snat->ip_dest.resolved ||
- !snat->ip_snat.resolved)
- info(" ! Skipping due to different family of ip address");
-
+ info(" ! Skipping due to different family of ip address");
return;
}
@@ -410,9 +437,6 @@ fw3_print_snats(struct fw3_ipt_handle *handle, struct fw3_state *state)
int num = 0;
struct fw3_snat *snat;
- if (handle->family == FW3_FAMILY_V6)
- return;
-
if (handle->table != FW3_TABLE_NAT)
return;
@@ -133,6 +133,41 @@ parse_subnets(struct list_head *head, enum fw3_family family,
return n;
}
+static int
+parse_prefix_assignments(struct list_head *head, enum fw3_family family,
+ struct blob_attr *list)
+{
+ struct blob_attr *pfx, *cur;
+ struct fw3_address *addr;
+ int rem, pfxlen, n = 0;
+
+ if (!list)
+ return 0;
+
+ rem = blobmsg_data_len(list);
+
+ __blob_for_each_attr(pfx, blobmsg_data(list), rem)
+ {
+ pfxlen = blobmsg_data_len(pfx);
+
+ __blob_for_each_attr(cur, blobmsg_data(pfx), pfxlen)
+ {
+ if (!strcmp(blobmsg_name(cur), "local-address"))
+ {
+ addr = parse_subnet(family, blobmsg_data(cur), blobmsg_data_len(cur));
+
+ if (addr)
+ {
+ list_add_tail(&addr->list, head);
+ n++;
+ }
+ }
+ }
+ }
+
+ return n;
+}
+
struct fw3_device *
fw3_ubus_device(const char *net)
{
@@ -218,7 +253,7 @@ fw3_ubus_address(struct list_head *list, const char *net)
n += parse_subnets(list, FW3_FAMILY_V4, tb[ADDR_IPV4]);
n += parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6]);
- n += parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6_PREFIX]);
+ n += parse_prefix_assignments(list, FW3_FAMILY_V6, tb[ADDR_IPV6_PREFIX]);
}
return n;
@@ -1047,3 +1047,37 @@ fw3_check_loopback_addr(struct fw3_address *addr)
return false;
}
+
+struct fw3_address *
+fw3_first_family_addr(struct list_head *addrs, enum fw3_family family)
+{
+ struct fw3_address *addr;
+
+ if (family == FW3_FAMILY_ANY)
+ return NULL;
+
+ list_for_each_entry(addr, addrs, list)
+ {
+ if (addr->family == family)
+ return addr;
+ }
+
+ return NULL;
+}
+
+bool
+fw3_check_family_addr(struct list_head *addrs, enum fw3_family family)
+{
+ struct fw3_address *addr;
+
+ if (family == FW3_FAMILY_ANY || list_empty(addrs))
+ return true;
+
+ list_for_each_entry(addr, addrs, list)
+ {
+ if (addr->family == family)
+ return true;
+ }
+
+ return false;
+}
@@ -44,6 +44,7 @@
extern bool fw3_pr_debug;
+enum fw3_family;
struct fw3_address;
void warn_elem(struct uci_element *e, const char *format, ...)
@@ -134,4 +135,9 @@ const char * fw3_protoname(void *proto);
bool fw3_check_loopback_dev(const char *name);
bool fw3_check_loopback_addr(struct fw3_address *addr);
+
+struct fw3_address * fw3_first_family_addr(struct list_head *addrs, enum fw3_family family);
+
+bool fw3_check_family_addr(struct list_head *addrs, enum fw3_family family);
+
#endif
@@ -37,8 +37,8 @@ static const struct fw3_chain_spec zone_chains[] = {
C(ANY, FILTER, REJECT, "zone_%s_dest_REJECT"),
C(ANY, FILTER, DROP, "zone_%s_dest_DROP"),
- C(V4, NAT, SNAT, "zone_%s_postrouting"),
- C(V4, NAT, DNAT, "zone_%s_prerouting"),
+ C(ANY, NAT, SNAT, "zone_%s_postrouting"),
+ C(ANY, NAT, DNAT, "zone_%s_prerouting"),
C(ANY, RAW, HELPER, "zone_%s_helper"),
C(ANY, RAW, NOTRACK, "zone_%s_notrack"),
@@ -47,8 +47,8 @@ static const struct fw3_chain_spec zone_chains[] = {
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"),
+ C(ANY, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"),
+ C(ANY, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"),
{ }
};
@@ -310,6 +310,9 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p)
{
fw3_setbit(zone->flags[0], FW3_FLAG_SNAT);
fw3_setbit(zone->flags[0], FW3_FLAG_DNAT);
+
+ fw3_setbit(zone->flags[1], FW3_FLAG_SNAT);
+ fw3_setbit(zone->flags[1], FW3_FLAG_DNAT);
}
resolve_cthelpers(state, e, zone);