[PATCH 0/5] RFC: Fix bug 209
Here are a handful of changes to forwarding ant multicast handling, that fix bug 209. It also gets us closer to correct multicast handling, though we're certainly not there yet - multicast things currently only really work at all because IP_MULTICAST_ALL defaults to on, and for the common protocols the host is likely to be already a group member. RFC, because a tmux change has broken the tests for me, and I wanted to send this out before I sort out how to fix that. I have run the subset of tests covered by "make bats", which includes the podman tests. David Gibson (5): fwd: Clarify semantics of --host-lo-to-ns-lo udp: Validate that we have a unicast source address fwd: Rework default address logic for inbound flows fwd: Reorder DNAPT and SNAT steps in fwd_nat_from_host() fwd: Don't rewrite inbound multicast destinations conf.c | 2 ++ fwd.c | 61 ++++++++++++++++++++++++++++++++++-------------------- passt.1 | 9 ++++---- udp_flow.c | 2 +- 4 files changed, 46 insertions(+), 28 deletions(-) -- 2.55.0
fwd_nat_from_host() (nearly) always rewrites the destination address for
inbound flows to the observed guest address. Usually, that makes sense:
regardless of the host address to which the new flow arrived, we want to
direct it to the guest. However, that clearly does not make sense for
multicast - it should still appear as a multicast transmission to the
guest.
In particular this can work very badly for multicast protocols which use
the same source and destination ports by convention (e.g. mDNS). In this
case, we will attempt to forword multicast packets to our own socket,
causing a forwarding loop (see bug 209 for more details).
While it's certainly not enough to make us handle multicast correctly in
all circumstances, not translating multicast destinations is closer to
correct, and prevents bug 209 at least.
Link: https://bugs.passt.top/show_bug.cgi?id=209
Signed-off-by: David Gibson
On Fri, 10 Jul 2026 16:56:11 +1000
David Gibson
fwd_nat_from_host() (nearly) always rewrites the destination address for inbound flows to the observed guest address. Usually, that makes sense: regardless of the host address to which the new flow arrived, we want to direct it to the guest. However, that clearly does not make sense for multicast - it should still appear as a multicast transmission to the guest.
In particular this can work very badly for multicast protocols which use the same source and destination ports by convention (e.g. mDNS). In this case, we will attempt to forword multicast packets to our own socket, causing a forwarding loop (see bug 209 for more details).
While it's certainly not enough to make us handle multicast correctly in all circumstances, not translating multicast destinations is closer to correct, and prevents bug 209 at least.
Link: https://bugs.passt.top/show_bug.cgi?id=209 Signed-off-by: David Gibson
--- fwd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fwd.c b/fwd.c index 7d39898e..e59413b6 100644 --- a/fwd.c +++ b/fwd.c @@ -1045,7 +1045,8 @@ uint8_t fwd_nat_from_host(const struct ctx *c, 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)) + else if (inany_is_multicast(&ini->oaddr) ||
This is a bit convoluted: if one reads this commit message it makes sense, but if one reads just the code later it's absolutely unclear that this is needed to avoid the inany_is_unspecified(&tgt->eaddr) clause at the end of the function (mostly). Should we add a comment? Right now I can't come up with any reasonable suggestion of where to place it or what to write in it, though.
+ (c->host_lo_to_ns_lo && inany_is_loopback(&ini->oaddr))) tgt->eaddr = ini->oaddr;
/* TODO: Allow splicing with specified target address */
-- Stefano
On Mon, Jul 13, 2026 at 02:39:54AM +0200, Stefano Brivio wrote:
On Fri, 10 Jul 2026 16:56:11 +1000 David Gibson
wrote: fwd_nat_from_host() (nearly) always rewrites the destination address for inbound flows to the observed guest address. Usually, that makes sense: regardless of the host address to which the new flow arrived, we want to direct it to the guest. However, that clearly does not make sense for multicast - it should still appear as a multicast transmission to the guest.
In particular this can work very badly for multicast protocols which use the same source and destination ports by convention (e.g. mDNS). In this case, we will attempt to forword multicast packets to our own socket, causing a forwarding loop (see bug 209 for more details).
While it's certainly not enough to make us handle multicast correctly in all circumstances, not translating multicast destinations is closer to correct, and prevents bug 209 at least.
Link: https://bugs.passt.top/show_bug.cgi?id=209 Signed-off-by: David Gibson
--- fwd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fwd.c b/fwd.c index 7d39898e..e59413b6 100644 --- a/fwd.c +++ b/fwd.c @@ -1045,7 +1045,8 @@ uint8_t fwd_nat_from_host(const struct ctx *c, 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)) + else if (inany_is_multicast(&ini->oaddr) ||
This is a bit convoluted: if one reads this commit message it makes sense, but if one reads just the code later it's absolutely unclear that this is needed to avoid the inany_is_unspecified(&tgt->eaddr) clause at the end of the function (mostly).
Should we add a comment? Right now I can't come up with any reasonable suggestion of where to place it or what to write in it, though.
Uh.. agreed on both points. It *is* a bit convoluted, but I'm not sure how to clarify it either. I'm hoping it will mostly go away if we can switch to selecting the target pif based on the rule rather than the bespoke logic we have here.
+ (c->host_lo_to_ns_lo && inany_is_loopback(&ini->oaddr))) tgt->eaddr = ini->oaddr;
/* TODO: Allow splicing with specified target address */
-- Stefano
-- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson
participants (2)
-
David Gibson
-
Stefano Brivio