For IPv6 UDP, the PORT_GUA flag is set for a port when we get a
"connection" from ip6.addr, that is from the host's global address. An
exactly analogous situation is possible for IPv4, but we don't handle it
the same way. In practice it will only show up if addr_seen is different
from addr, which is unusual. Nonetheless we should handle this the same
way for IPv4 and IPv6.
Signed-off-by: David Gibson
---
udp.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/udp.c b/udp.c
index d7e1020..950d5a9 100644
--- a/udp.c
+++ b/udp.c
@@ -596,7 +596,8 @@ static size_t udp_update_hdr4(const struct ctx *c, int n, in_port_t dstport,
IN4_ARE_ADDR_EQUAL(src, &c->ip4.dns_host) && src_port == 53) {
b->iph.saddr = c->ip4.dns_match.s_addr;
} else if (IN4_IS_ADDR_LOOPBACK(src) ||
- IN4_ARE_ADDR_EQUAL(src, &c->ip4.addr_seen)) {
+ IN4_ARE_ADDR_EQUAL(src, &c->ip4.addr_seen) ||
+ IN4_ARE_ADDR_EQUAL(src, &c->ip4.addr)) {
b->iph.saddr = c->ip4.gw.s_addr;
udp_tap_map[V4][src_port].ts = now->tv_sec;
udp_tap_map[V4][src_port].flags |= PORT_LOCAL;
@@ -606,6 +607,11 @@ static size_t udp_update_hdr4(const struct ctx *c, int n, in_port_t dstport,
else
udp_tap_map[V4][src_port].flags &= ~PORT_LOOPBACK;
+ if (IN4_ARE_ADDR_EQUAL(src, &c->ip4.addr))
+ udp_tap_map[V4][src_port].flags |= PORT_GUA;
+ else
+ udp_tap_map[V4][src_port].flags &= ~PORT_GUA;
+
bitmap_set(udp_act[V4][UDP_ACT_TAP], src_port);
} else {
b->iph.saddr = src->s_addr;
@@ -852,6 +858,8 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
(udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ else if (udp_tap_map[V4][dst].flags & PORT_GUA)
+ s_in.sin_addr = c->ip4.addr;
else
s_in.sin_addr = c->ip4.addr_seen;
}
--
2.40.1