aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--fwd.c41
-rw-r--r--inany.h2
2 files changed, 29 insertions, 14 deletions
diff --git a/fwd.c b/fwd.c
index 8440094..de444d9 100644
--- a/fwd.c
+++ b/fwd.c
@@ -1006,6 +1006,24 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr,
}
/**
+ * fwd_default_guest_addr() - Get appropriate guest address to send to
+ * @c: Execution context
+ * @template: Address to match IP version and scope of
+ *
+ * Return: the address of the guest, which best matches the IP version and scope
+ * of @template
+ */
+static union inany_addr fwd_default_guest_addr(const struct ctx *c,
+ const union inany_addr *template)
+{
+ if (inany_v4(template))
+ return inany_from_v4(c->ip4.addr_seen);
+ if (inany_is_linklocal6(template))
+ return inany_from_v6(c->ip6.addr_ll_seen);
+ return inany_from_v6(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 +1058,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 +1070,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))
+ tgt->eaddr = fwd_default_guest_addr(c, &tgt->oaddr);
return PIF_SPLICE;
}
@@ -1074,16 +1091,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))
+ tgt->eaddr = fwd_default_guest_addr(c, &tgt->oaddr);
return PIF_TAP;
}
diff --git a/inany.h b/inany.h
index 5b176cc..d0befb1 100644
--- a/inany.h
+++ b/inany.h
@@ -59,6 +59,8 @@ extern const union inany_addr inany_any4;
#define inany_from_v4(a4) \
((union inany_addr)INANY_INIT4((a4)))
+#define inany_from_v6(a6_) \
+ ((union inany_addr){.a6 = (a6_)})
/** union sockaddr_inany - Either a sockaddr_in or a sockaddr_in6
* @sa_family: Address family, AF_INET or AF_INET6