X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=redirects.c;h=de3d42e2b8023fe63683cac2336a4c4e58761cb7;hp=aec47fdf46db19ae4feeeb5ade2858655bddb346;hb=2dbfd733c34311df6217da809c0045c195ba8b9e;hpb=6b27a6665c288937eb5028063064e3350dcab545 diff --git a/redirects.c b/redirects.c index aec47fd..de3d42e 100644 --- a/redirects.c +++ b/redirects.c @@ -32,14 +32,14 @@ const struct fw3_option fw3_redirect_opts[] = { FW3_LIST("proto", protocol, redirect, proto), - FW3_OPT("src_ip", address, redirect, ip_src), + FW3_OPT("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", address, redirect, ip_dest), + FW3_OPT("src_dip", network, redirect, ip_dest), FW3_OPT("src_dport", port, redirect, port_dest), - FW3_OPT("dest_ip", address, redirect, ip_redir), + FW3_OPT("dest_ip", network, redirect, ip_redir), FW3_OPT("dest_port", port, redirect, port_redir), FW3_OPT("extra", string, redirect, extra), @@ -109,6 +109,58 @@ check_families(struct uci_element *e, struct fw3_redirect *r) return true; } +static bool +compare_addr(struct fw3_address *a, struct fw3_address *b) +{ + uint32_t mask; + + if (a->family != FW3_FAMILY_V4) + return false; + + mask = ~((1 << (32 - a->mask)) - 1); + + return ((a->address.v4.s_addr & mask) == (b->address.v4.s_addr & mask)); +} + +static bool +resolve_dest(struct uci_element *e, struct fw3_redirect *redir, + struct fw3_state *state) +{ + struct fw3_zone *zone; + struct fw3_address *addr; + struct list_head *addrs; + + if (!redir->ip_redir.set) + return false; + + list_for_each_entry(zone, &state->zones, list) + { + addrs = fw3_resolve_zone_addresses(zone); + + if (!addrs) + continue; + + list_for_each_entry(addr, addrs, list) + { + if (!compare_addr(addr, &redir->ip_redir)) + continue; + + strncpy(redir->dest.name, zone->name, sizeof(redir->dest.name)); + redir->dest.set = true; + redir->_dest = zone; + + break; + } + + fw3_free_list(addrs); + + if (redir->_dest) + return true; + } + + return false; +} + void fw3_load_redirects(struct fw3_state *state, struct uci_package *p) { @@ -214,6 +266,12 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) valid = true; } + if (!redir->dest.set && resolve_dest(e, redir, state)) + { + warn_elem(e, "does not specify a destination, assuming '%s'", + redir->dest.name); + } + if (redir->reflection && redir->_dest && redir->_src->masq) { set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_ACCEPT); @@ -463,7 +521,6 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state, { struct list_head *ext_addrs, *int_addrs; struct fw3_address *ext_addr, *int_addr, ref_addr; - struct fw3_device *ext_net, *int_net; struct fw3_protocol *proto; struct fw3_mac *mac; @@ -483,7 +540,11 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state, !fw3_is_family(&redir->ip_dest, handle->family) || !fw3_is_family(&redir->ip_redir, handle->family)) { - info(" ! Skipping due to different family of ip address"); + if (!redir->ip_src.resolved || + !redir->ip_dest.resolved || + !redir->ip_redir.resolved) + info(" ! Skipping due to different family of ip address"); + return; } @@ -517,28 +578,24 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state, if (!redir->_dest || !redir->_src->masq) return; - list_for_each_entry(ext_net, &redir->_src->networks, list) - { - ext_addrs = fw3_ubus_address(ext_net->name); + ext_addrs = fw3_resolve_zone_addresses(redir->_src); + int_addrs = fw3_resolve_zone_addresses(redir->_dest); + + if (!ext_addrs || !int_addrs) + goto out; - if (!ext_addrs || list_empty(ext_addrs)) + list_for_each_entry(ext_addr, ext_addrs, list) + { + if (!fw3_is_family(ext_addr, handle->family)) continue; - list_for_each_entry(int_net, &redir->_dest->networks, list) + list_for_each_entry(int_addr, int_addrs, list) { - int_addrs = fw3_ubus_address(int_net->name); - - if (!int_addrs || list_empty(int_addrs)) + if (!fw3_is_family(int_addr, handle->family)) continue; - fw3_foreach(ext_addr, ext_addrs) - fw3_foreach(int_addr, int_addrs) fw3_foreach(proto, &redir->proto) { - if (!fw3_is_family(int_addr, handle->family) || - !fw3_is_family(ext_addr, handle->family)) - continue; - if (!proto || (proto->protocol != 6 && proto->protocol != 17)) continue; @@ -553,12 +610,12 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state, print_reflection(handle, state, redir, num, proto, &ref_addr, int_addr, ext_addr); } - - fw3_ubus_address_free(int_addrs); } - - fw3_ubus_address_free(ext_addrs); } + +out: + fw3_free_list(ext_addrs); + fw3_free_list(int_addrs); } void