Depending on the original source address, udp_update_hdr6() can take one of several paths to handle the cases where we need NAT or other adjustments. In each path we explicitly set the source IPv6 address in the packet buffer. Simplify this slightly to update src to point to the corrected source address in each branch, then have a common write to the packet buffer. This will enable future cleanups. To make this work we do need a slightly re-order to avoid making tests on the update 'src' when we need to test the original source. Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- udp.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/udp.c b/udp.c index 39c59d4..361f24c 100644 --- a/udp.c +++ b/udp.c @@ -632,35 +632,26 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport, const struct timespec *now) { struct udp6_l2_buf_t *b = &udp6_l2_buf[n]; - struct in6_addr *src; - in_port_t src_port; + in_port_t src_port = ntohs(b->s_in6.sin6_port); + const struct in6_addr *src = &b->s_in6.sin6_addr; size_t ip_len; - src = &b->s_in6.sin6_addr; - src_port = ntohs(b->s_in6.sin6_port); - ip_len = udp6_l2_mh_sock[n].msg_len + sizeof(b->ip6h) + sizeof(b->uh); b->ip6h.payload_len = htons(udp6_l2_mh_sock[n].msg_len + sizeof(b->uh)); if (IN6_IS_ADDR_LINKLOCAL(src)) { b->ip6h.daddr = c->ip6.addr_ll_seen; - b->ip6h.saddr = b->s_in6.sin6_addr; } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) && IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) && src_port == 53) { b->ip6h.daddr = c->ip6.addr_seen; - b->ip6h.saddr = c->ip6.dns_match; + src = &c->ip6.dns_match; } else if (IN6_IS_ADDR_LOOPBACK(src) || IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) || IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) { b->ip6h.daddr = c->ip6.addr_ll_seen; - if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw)) - b->ip6h.saddr = c->ip6.gw; - else - b->ip6h.saddr = c->ip6.addr_ll; - udp_tap_map[V6][src_port].ts = now->tv_sec; udp_tap_map[V6][src_port].flags |= PORT_LOCAL; @@ -675,11 +666,17 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport, udp_tap_map[V6][src_port].flags &= ~PORT_GUA; bitmap_set(udp_act[V6][UDP_ACT_TAP], src_port); + + if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw)) + src = &c->ip6.gw; + else + src = &c->ip6.addr_ll; } else { b->ip6h.daddr = c->ip6.addr_seen; - b->ip6h.saddr = b->s_in6.sin6_addr; } + b->ip6h.saddr = *src; + b->uh.source = b->s_in6.sin6_port; b->uh.dest = htons(dstport); b->uh.len = b->ip6h.payload_len; -- 2.40.1