FW3_OPT("reflection", bool, redirect, reflection),
FW3_OPT("reflection_src", reflection_source,
redirect, reflection_src),
+ FW3_LIST("reflection_zone", device, redirect, reflection_zones),
FW3_OPT("target", target, redirect, target),
if (!compare_addr(addr, &redir->ip_redir))
continue;
- strncpy(redir->dest.name, zone->name, sizeof(redir->dest.name));
+ snprintf(redir->dest.name, sizeof(redir->dest.name), "%s", zone->name);
redir->dest.set = true;
redir->_dest = zone;
}
else if (redir->ipset.set && state->disable_ipsets)
{
- warn_section("redirect", redir, e, "skipped due to disabled ipset support",
- redir->name);
+ warn_section("redirect", redir, e, "skipped due to disabled ipset support");
return false;
}
else if (redir->ipset.set &&
!(redir->ipset.ptr = fw3_lookup_ipset(state, redir->ipset.name)))
{
- warn_section("redirect", redir, e, "refers to unknown ipset '%s'", redir->name,
+ warn_section("redirect", redir, e, "refers to unknown ipset '%s'",
redir->ipset.name);
return false;
}
INIT_LIST_HEAD(&redir->proto);
INIT_LIST_HEAD(&redir->mac_src);
+ INIT_LIST_HEAD(&redir->reflection_zones);
redir->enabled = true;
redir->reflection = true;
static void
set_redirect(struct fw3_ipt_rule *r, struct fw3_port *port)
{
- char buf[sizeof("65535-65535\0")];
+ char buf[sizeof("65535-65535")];
fw3_ipt_rule_target(r, "REDIRECT");
if (port && port->set)
{
if (port->port_min == port->port_max)
- sprintf(buf, "%u", port->port_min);
+ snprintf(buf, sizeof(buf), "%u", port->port_min);
else
snprintf(buf, sizeof(buf), "%u-%u", port->port_min, port->port_max);
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")];
-
- buf[0] = '\0';
+ char buf[sizeof("255.255.255.255:65535-65535")] = {};
+ char ip[INET_ADDRSTRLEN], *p = buf;
+ size_t rem = sizeof(buf);
+ int len;
if (addr && addr->set)
{
- inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf));
+ inet_ntop(AF_INET, &addr->address.v4, ip, sizeof(ip));
+
+ len = snprintf(p, rem, "%s", ip);
+
+ if (len < 0 || len >= rem)
+ return;
+
+ rem -= len;
+ p += len;
}
if (port && port->set)
{
if (port->port_min == port->port_max)
- sprintf(buf + strlen(buf), ":%u", port->port_min);
+ snprintf(p, rem, ":%u", port->port_min);
else
- sprintf(buf + strlen(buf), ":%u-%u",
- port->port_min, port->port_max);
+ snprintf(p, rem, ":%u-%u", port->port_min, port->port_max);
}
if (target == FW3_FLAG_DNAT)
print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
struct fw3_redirect *redir, int num,
struct fw3_protocol *proto, struct fw3_address *ra,
- struct fw3_address *ia, struct fw3_address *ea)
+ struct fw3_address *ia, struct fw3_address *ea, struct fw3_device *rz)
{
struct fw3_ipt_rule *r;
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);
- fw3_ipt_rule_replace(r, "zone_%s_prerouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_prerouting", rz->name);
r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, &redir->ip_redir);
fw3_ipt_rule_sport_dport(r, NULL, &redir->port_redir);
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, "reflection");
set_snat_dnat(r, FW3_FLAG_SNAT, ra, NULL);
- fw3_ipt_rule_replace(r, "zone_%s_postrouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_postrouting", rz->name);
break;
default:
struct fw3_address *ext_addr, *int_addr, ref_addr;
struct fw3_protocol *proto;
struct fw3_mac *mac;
+ struct fw3_device *reflection_zone;
+ struct fw3_zone *zone;
if (redir->name)
info(" * Redirect '%s'", redir->name);
return;
ext_addrs = fw3_resolve_zone_addresses(redir->_src, &redir->ip_dest);
- int_addrs = fw3_resolve_zone_addresses(redir->_dest, NULL);
-
- if (!ext_addrs || !int_addrs)
- goto out;
+ if (!ext_addrs)
+ return;
list_for_each_entry(ext_addr, ext_addrs, list)
{
if (!fw3_is_family(ext_addr, handle->family))
continue;
- list_for_each_entry(int_addr, int_addrs, list)
+ for (reflection_zone = list_empty(&redir->reflection_zones)
+ ? &redir->dest
+ : list_first_entry(&redir->reflection_zones, struct fw3_device, list);
+ list_empty(&redir->reflection_zones)
+ ? (reflection_zone == &redir->dest)
+ : (&reflection_zone->list != &redir->reflection_zones);
+ reflection_zone = list_empty(&redir->reflection_zones)
+ ? NULL
+ : list_entry(reflection_zone->list.next, struct fw3_device, list))
{
- if (!fw3_is_family(int_addr, handle->family))
+ zone = fw3_lookup_zone(state, reflection_zone->name);
+
+ if (!zone)
+ continue;
+
+ int_addrs = fw3_resolve_zone_addresses(zone, NULL);
+ if (!int_addrs)
continue;
- fw3_foreach(proto, &redir->proto)
+ list_for_each_entry(int_addr, int_addrs, list)
{
- if (!proto)
+ if (!fw3_is_family(int_addr, handle->family))
continue;
- if (redir->reflection_src == FW3_REFLECTION_INTERNAL)
- ref_addr = *int_addr;
- else
- ref_addr = *ext_addr;
+ fw3_foreach(proto, &redir->proto)
+ {
+ if (!proto)
+ continue;
+
+ if (redir->reflection_src == FW3_REFLECTION_INTERNAL)
+ ref_addr = *int_addr;
+ else
+ ref_addr = *ext_addr;
- ref_addr.mask.v4.s_addr = 0xFFFFFFFF;
- ext_addr->mask.v4.s_addr = 0xFFFFFFFF;
+ ref_addr.mask.v4.s_addr = 0xFFFFFFFF;
+ ext_addr->mask.v4.s_addr = 0xFFFFFFFF;
- print_reflection(handle, state, redir, num, proto,
- &ref_addr, int_addr, ext_addr);
+ print_reflection(handle, state, redir, num, proto,
+ &ref_addr, int_addr, ext_addr, reflection_zone);
+ }
}
+
+ fw3_free_list(int_addrs);
}
}
-out:
fw3_free_list(ext_addrs);
- fw3_free_list(int_addrs);
}
void