From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202606 header.b=BtKx1Rp7; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 5C6D75A026D for ; Fri, 10 Jul 2026 08:56:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202606; t=1783666574; bh=fIzzWdvvhgqFyOSDGym0OLZop0QjCKVRQSWUsncJtLM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BtKx1Rp7QRicYlxJyNUZbMy5j5FcvxEvrHPsAFtAZ0bA8+Ahgq2Z5WIgEAeOy/tNN pztKL6E6Sxe1G2/N6SpEYx4L3J970kzp6l0bIwVNnENPrrO03usbmLLczf/lL88ruk SBJYM7u+Rf+zvJ1pTJtK2rCcHaNDEjFPJzVCdYN5odlaXE6gw3QSPYPrL/+s3r57qD iUbUY+EqJpy8JwvZOeUzDqZn05KWX4nUf8v9oiZamw1V1YC/eRYmKQy28nrIb9LUUG GRMMWkni1mYowkszH0Y88vBislYit2sNUdwmUdZ0R08T33KBQhLlzvxdGAhnPGPNNB LDYi/vlj7Z2yg== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4gxN0G4rDYz58dW; Fri, 10 Jul 2026 16:56:14 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 4/5] fwd: Reorder DNAPT and SNAT steps in fwd_nat_from_host() Date: Fri, 10 Jul 2026 16:56:10 +1000 Message-ID: <20260710065611.530947-5-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260710065611.530947-1-david@gibson.dropbear.id.au> References: <20260710065611.530947-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 7DKJFNSD3X4XJ7VWSECJAZSCZUEH2XV6 X-Message-ID-Hash: 7DKJFNSD3X4XJ7VWSECJAZSCZUEH2XV6 X-MailFrom: dgibson@gandalf.ozlabs.org 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: 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: The order in which we translate source and destination addresses is a bit unclear in fwd_nat_from_host(). Reorder things to make it clearer: 1. Pick guest-side destination address, where options require it 2. Pick guest-side source address (needs to be different for SPLICE and TAP) 3. If (1) didn't determine destination, pick a fallback to match family and scope of source address from (2). As a small bonus this lets us make step (1) common between SPLICE and TAP paths. The value of this is a bit dubious right now, but it will make some future changes clearer. Signed-off-by: David Gibson --- fwd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fwd.c b/fwd.c index 90297ef7..7d39898e 100644 --- a/fwd.c +++ b/fwd.c @@ -1041,8 +1041,12 @@ uint8_t fwd_nat_from_host(const struct ctx *c, const struct fwd_rule *rule, uint8_t proto, const struct flowside *ini, struct flowside *tgt) { - /* Common for spliced and non-spliced cases */ + /* DNAPT: Common for splice and non-spliced where possible */ tgt->eport = rule->to + (ini->oport - rule->first); + if (!inany_is_unspecified(&rule->taddr)) + tgt->eaddr = rule->taddr; + else if (c->host_lo_to_ns_lo && inany_is_loopback(&ini->oaddr)) + tgt->eaddr = ini->oaddr; /* TODO: Allow splicing with specified target address */ if (!c->no_splice && inany_is_unspecified(&rule->taddr) && @@ -1059,10 +1063,8 @@ uint8_t fwd_nat_from_host(const struct ctx *c, * In either case, let the kernel pick the source address to * match. */ - if (c->host_lo_to_ns_lo && inany_is_loopback(&ini->oaddr)) - tgt->eaddr = ini->oaddr; - /* Let the kernel pick source address and port */ + /* SNAT: (implicit) let the kernel pick source addr/port */ if (inany_v4(&ini->eaddr)) tgt->oaddr = inany_any4; else @@ -1082,6 +1084,7 @@ uint8_t fwd_nat_from_host(const struct ctx *c, if (c->splice_only) return PIF_NONE; + /* SNAT: translate source address if necessary */ if (!nat_inbound(c, &ini->eaddr, &tgt->oaddr)) { if (inany_v4(&ini->eaddr)) { if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.our_tap_addr)) @@ -1094,9 +1097,6 @@ uint8_t fwd_nat_from_host(const struct ctx *c, } tgt->oport = ini->eport; - if (!inany_is_unspecified(&rule->taddr)) - tgt->eaddr = rule->taddr; - /* Use guest address as destination, if otherwise unspecified */ if (inany_is_unspecified(&tgt->eaddr)) fwd_default_guest_addr(c, &tgt->eaddr, &tgt->oaddr); -- 2.55.0