From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by passt.top (Postfix, from userid 1000) id 4445A5A026D; Thu, 23 Jul 2026 01:26:39 +0200 (CEST) From: Stefano Brivio To: passt-dev@passt.top Subject: [PATCH 2/2] conf, fwd: Prefer same-scope address as inbound source address from host Date: Thu, 23 Jul 2026 01:26:39 +0200 Message-ID: <20260722232639.1105561-3-sbrivio@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260722232639.1105561-1-sbrivio@redhat.com> References: <20260722232639.1105561-1-sbrivio@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 42EVBFCDG7J5EFUIUU6ZMNYCR72BAPKD X-Message-ID-Hash: 42EVBFCDG7J5EFUIUU6ZMNYCR72BAPKD X-MailFrom: sbrivio@passt.top X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: =?UTF-8?q?Jan=20Rod=C3=A1k?= , Paul Holzinger , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: We might have situations, such as the one described in https://bugs.passt.top/show_bug.cgi?id=217, where using a link-local address as source in a given namespace doesn't guarantee that we can reach the intended destination, because, for instance, the inbound traffic we forward is in turn forwarded to a different interface, such as a bridge. In that case, the assumption from 9618d247006a ("ndp, dhcpv6, tcp, udp: Always use link-local as source if gateway isn't") isn't a safe one: the user might have specified a valid gateway address, matching the scope of the destination address, but we won't use it as address of last resort, and prefer a link-local address with a mismatch in scope instead. This should only be an issue in IPv6 local mode, because, otherwise, we source address and default gateway address (presumably compatible) from the host. So, in local mode, if the user specifies a given default gateway address for IPv6, note that as 'our_tap_addr', like we would do with with IPv4, and stick to Rule 2 of RFC 6724, Section 5, when selecting a source address, by preferring an address with the same scope, if available. Reported-by: Paul Holzinger Link: https://bugs.passt.top/show_bug.cgi?id=217 Signed-off-by: Stefano Brivio --- conf.c | 6 ++++-- fwd.c | 6 +++++- passt.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/conf.c b/conf.c index 7908123..1998004 100644 --- a/conf.c +++ b/conf.c @@ -507,10 +507,12 @@ static void conf_ip6_local(struct ip6_ctx *ip6) if (IN6_IS_ADDR_UNSPECIFIED(&ip6->guest_gw)) ip6->guest_gw = IP6_LL_GUEST_GW; - if (IN6_IS_ADDR_LINKLOCAL(&ip6->guest_gw)) + if (IN6_IS_ADDR_LINKLOCAL(&ip6->guest_gw)) { ip6->our_tap_ll = ip6->guest_gw; - else + } else { + ip6->our_tap_addr = ip6->guest_gw; ip6->our_tap_ll = IP6_LL_GUEST_GW; + } ip6->no_copy_addrs = ip6->no_copy_routes = true; } diff --git a/fwd.c b/fwd.c index 7152169..4ba0af3 100644 --- a/fwd.c +++ b/fwd.c @@ -1090,7 +1090,11 @@ uint8_t fwd_nat_from_host(const struct ctx *c, return PIF_NONE; tgt->oaddr = inany_from_v4(c->ip4.our_tap_addr); } else { - tgt->oaddr.a6 = c->ip6.our_tap_ll; + if (inany_is_linklocal6(&tgt->eaddr) || + IN6_IS_ADDR_UNSPECIFIED(&c->ip6.our_tap_addr)) + tgt->oaddr.a6 = c->ip6.our_tap_ll; + else + tgt->oaddr.a6 = c->ip6.our_tap_addr; } } tgt->oport = ini->eport; diff --git a/passt.h b/passt.h index a61baca..51ccd4f 100644 --- a/passt.h +++ b/passt.h @@ -121,6 +121,7 @@ struct ip4_ctx { * @dns: DNS addresses for DHCPv6 and NDP * @dns_match: Forward DNS query if sent to this address * @our_tap_ll: Link-local IPv6 address for passt's use on tap + * @our_tap_addr: Non-LL IPv6 address for passt's use on tap (if any) * @dns_host: Use this DNS on the host for forwarding * @addr_out: Optional source address for outbound traffic * @ifname_out: Optional interface name to bind outbound sockets to @@ -140,6 +141,7 @@ struct ip6_ctx { struct in6_addr dns[MAXNS]; struct in6_addr dns_match; struct in6_addr our_tap_ll; + struct in6_addr our_tap_addr; /* PIF_HOST addresses */ struct in6_addr dns_host; -- 2.43.0