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 <david(a)gibson.dropbear.id.au> --- 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