diff options
| -rw-r--r-- | fwd.c | 44 |
1 files changed, 30 insertions, 14 deletions
@@ -1006,6 +1006,27 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr, } /** + * fwd_default_geuest_addr() - Get appropriate guest address to send to + * @c: Execution context + * @guest_addr: Updated with chosen guest address + * @template: Address to match IP version and scope of + * + * Sets @guest_addr to have the address of the guest, matching the IP version + * and scope of @template where possible. + */ +static void fwd_default_guest_addr(const struct ctx *c, + union inany_addr *guest_addr, + const union inany_addr *template) +{ + if (inany_v4(template)) + *guest_addr = inany_from_v4(c->ip4.addr_seen); + else if (inany_is_linklocal6(template)) + guest_addr->a6 = c->ip6.addr_ll_seen; + else + guest_addr->a6 = c->ip6.addr_seen; +} + +/** * fwd_nat_from_host() - Determine to forward a flow from the host interface * @c: Execution context * @rule: Forwarding rule to apply @@ -1040,13 +1061,9 @@ uint8_t fwd_nat_from_host(const struct ctx *c, */ if (c->host_lo_to_ns_lo && inany_is_loopback(&ini->oaddr)) tgt->eaddr = ini->oaddr; - else if (inany_v4(&ini->eaddr)) - tgt->eaddr = inany_from_v4(c->ip4.addr_seen); - else - tgt->eaddr.a6 = c->ip6.addr_seen; /* Let the kernel pick source address and port */ - if (inany_v4(&tgt->eaddr)) + if (inany_v4(&ini->eaddr)) tgt->oaddr = inany_any4; else tgt->oaddr = inany_any6; @@ -1056,6 +1073,9 @@ uint8_t fwd_nat_from_host(const struct ctx *c, /* But for UDP preserve the source port */ tgt->oport = ini->eport; + /* Use guest address as destination, if otherwise unspecified */ + if (inany_is_unspecified(&tgt->eaddr)) + fwd_default_guest_addr(c, &tgt->eaddr, &tgt->oaddr); return PIF_SPLICE; } @@ -1074,16 +1094,12 @@ uint8_t fwd_nat_from_host(const struct ctx *c, } tgt->oport = ini->eport; - if (!inany_is_unspecified(&rule->taddr)) { + if (!inany_is_unspecified(&rule->taddr)) tgt->eaddr = rule->taddr; - } else if (inany_v4(&tgt->oaddr)) { - tgt->eaddr = inany_from_v4(c->ip4.addr_seen); - } else { - if (inany_is_linklocal6(&tgt->oaddr)) - tgt->eaddr.a6 = c->ip6.addr_ll_seen; - else - tgt->eaddr.a6 = c->ip6.addr_seen; - } + + /* Use guest address as destination, if otherwise unspecified */ + if (inany_is_unspecified(&tgt->eaddr)) + fwd_default_guest_addr(c, &tgt->eaddr, &tgt->oaddr); return PIF_TAP; } |
