{
uint32_t mask;
- if (a->family != FW3_FAMILY_V4)
+ if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4)
return false;
- mask = ~((1 << (32 - a->mask)) - 1);
+ mask = htonl(~((1 << (32 - a->mask)) - 1));
return ((a->address.v4.s_addr & mask) == (b->address.v4.s_addr & mask));
}
return false;
}
+static bool
+check_local(struct uci_element *e, struct fw3_redirect *redir,
+ struct fw3_state *state)
+{
+ struct fw3_zone *zone;
+ struct fw3_device *net;
+ struct fw3_address *addr;
+ struct list_head *addrs;
+
+ if (redir->target != FW3_FLAG_DNAT)
+ return false;
+
+ if (!redir->ip_redir.set)
+ redir->local = true;
+
+ if (redir->local)
+ return true;
+
+ list_for_each_entry(zone, &state->zones, list)
+ {
+ list_for_each_entry(net, &zone->networks, list)
+ {
+ addrs = fw3_ubus_address(net->name);
+
+ if (!addrs)
+ continue;
+
+ list_for_each_entry(addr, addrs, list)
+ {
+ if (!compare_addr(&redir->ip_redir, addr))
+ continue;
+
+ warn_elem(e, "refers to a destination address on this router, "
+ "assuming port redirection");
+
+ redir->local = true;
+ break;
+ }
+
+ fw3_free_list(addrs);
+
+ if (redir->local)
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
fw3_load_redirects(struct fw3_state *state, struct uci_package *p)
{
valid = true;
}
- if (!redir->dest.set && resolve_dest(e, redir, state))
+ if (!check_local(e, redir, state) && !redir->dest.set &&
+ resolve_dest(e, redir, state))
{
warn_elem(e, "does not specify a destination, assuming '%s'",
redir->dest.name);
{
if (redir->target == FW3_FLAG_DNAT)
{
- /* XXX: check for local ip */
- if (!redir->ip_redir.set)
+ if (redir->local)
fw3_ipt_rule_append(r, "zone_%s_input", redir->src.name);
else
fw3_ipt_rule_append(r, "zone_%s_forward", redir->src.name);
static void
set_target_filter(struct fw3_ipt_rule *r, struct fw3_redirect *redir)
{
- /* XXX: check for local ip */
- if (redir->target == FW3_FLAG_DNAT && !redir->ip_redir.set)
+ if (redir->local)
fw3_ipt_rule_extra(r, "-m conntrack --ctstate DNAT");
fw3_ipt_rule_target(r, "ACCEPT");
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, true);
set_snat_dnat(r, FW3_FLAG_DNAT, &redir->ip_redir, &redir->port_redir);
- fw3_ipt_rule_append(r, "zone_%s_prerouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_prerouting", redir->dest.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, true);
set_snat_dnat(r, FW3_FLAG_SNAT, ra, NULL);
- fw3_ipt_rule_append(r, "zone_%s_postrouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_postrouting", redir->dest.name);
break;
case FW3_TABLE_FILTER:
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, true);
fw3_ipt_rule_target(r, "zone_%s_dest_ACCEPT", redir->dest.name);
- fw3_ipt_rule_append(r, "zone_%s_forward", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_forward", redir->dest.name);
break;
default:
fw3_foreach(proto, &redir->proto)
{
- if (!proto || (proto->protocol != 6 && proto->protocol != 17))
+ if (!proto)
continue;
if (redir->reflection_src == FW3_REFLECTION_INTERNAL)