<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/fwd.c, branch bug165c</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>fwd: Preserve non-standard loopback address when splice forwarding</title>
<updated>2025-12-02T22:07:42+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-12-02T04:02:15+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=fdbb4efd38f7211881e05f7284c364df5d4856be'/>
<id>fdbb4efd38f7211881e05f7284c364df5d4856be</id>
<content type='text'>
When forwarding "spliced" connections outwards (-T or -U) we listen on the
guest's loopback and always forward to 127.0.0.1 (or ::1) on the host.
However, it's also possible for clients on the guest to attempt connecting
to other addresses in 127.0.0.0/8 (systemd-resolved uses 127.0.0.53 in
practice).  If the host side server is only listening on that specific
non-standard loopback address, the forward won't work.  Fix this by
preserving the specific (loopback) address when forwarding such
connections.

Link: https://bugs.passt.top/show_bug.cgi?id=113
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When forwarding "spliced" connections outwards (-T or -U) we listen on the
guest's loopback and always forward to 127.0.0.1 (or ::1) on the host.
However, it's also possible for clients on the guest to attempt connecting
to other addresses in 127.0.0.0/8 (systemd-resolved uses 127.0.0.53 in
practice).  If the host side server is only listening on that specific
non-standard loopback address, the forward won't work.  Fix this by
preserving the specific (loopback) address when forwarding such
connections.

Link: https://bugs.passt.top/show_bug.cgi?id=113
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Don't explicitly exclude reverse-direction TCP ports for UDP</title>
<updated>2025-11-21T03:17:22+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-11-19T04:26:34+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=be1583f6ea608ed4f7b1409e7ed35237c79a14df'/>
<id>be1583f6ea608ed4f7b1409e7ed35237c79a14df</id>
<content type='text'>
In auto-forwarding mode, we forward UDP ports for which there isn't (yet)
a listening UDP port on the other side, but where there is a listening
TCP socket for the same port number.  This is useful for certain protocols
such as iperf3.

Correspondinly, when excluding ports from forwarding, we also exclude TCP
ports from the other direction.  That sounds like it makes sense, but is
unnecessary: for the purposes of exclusion, we don't care why we have a
listening UDP socket for that port, just whether we have one.  That is
already incorporated into the UDP bitmap alone.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In auto-forwarding mode, we forward UDP ports for which there isn't (yet)
a listening UDP port on the other side, but where there is a listening
TCP socket for the same port number.  This is useful for certain protocols
such as iperf3.

Correspondinly, when excluding ports from forwarding, we also exclude TCP
ports from the other direction.  That sounds like it makes sense, but is
unnecessary: for the purposes of exclusion, we don't care why we have a
listening UDP socket for that port, just whether we have one.  That is
already incorporated into the UDP bitmap alone.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Exclude ports based on prior mapping state</title>
<updated>2025-11-21T03:17:14+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-11-19T04:26:33+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=fd3fc8d33d6c4344c59a60af16b074515b3da739'/>
<id>fd3fc8d33d6c4344c59a60af16b074515b3da739</id>
<content type='text'>
With auto port-forwarding modes we scan for listening ports on the host
and/or guest and create forwardings for them.  To avoid circular forwarding
we need to exclude our own listening ports.  We do this by masking out
the forwarding map for one direction from the other.

Since 1bc7d5485c10, some of our scans take place while the forward maps are
out of sync with what our actual listening ports are though: the map
represents what we intend to forward shortly, rather than what we have
open sockets for right now.

What we have sockets for right now is what matters for the purposes of
excluding from the scan, though, so that was incorrect.  So, restore
correct behaviour by saving the map of ports to exclude before we start
updating any of the forwarding maps with new scans.  This allows us to
keep all the scans separate from all the rebinds, and therefore several
minor cleanups that permitted.

As a bonus, pre-creating the exclusion bitmaps this way should make this
code easier to adapt as we change the forwarding data structures to allow
more flexible configuration.

Fixes: 1bc7d5485c10 ("fwd: Consolidate scans (not rebinds) in fwd.c")
Link: https://bugs.passt.top/show_bug.cgi?id=176
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
With auto port-forwarding modes we scan for listening ports on the host
and/or guest and create forwardings for them.  To avoid circular forwarding
we need to exclude our own listening ports.  We do this by masking out
the forwarding map for one direction from the other.

Since 1bc7d5485c10, some of our scans take place while the forward maps are
out of sync with what our actual listening ports are though: the map
represents what we intend to forward shortly, rather than what we have
open sockets for right now.

What we have sockets for right now is what matters for the purposes of
excluding from the scan, though, so that was incorrect.  So, restore
correct behaviour by saving the map of ports to exclude before we start
updating any of the forwarding maps with new scans.  This allows us to
keep all the scans separate from all the rebinds, and therefore several
minor cleanups that permitted.

As a bonus, pre-creating the exclusion bitmaps this way should make this
code easier to adapt as we change the forwarding data structures to allow
more flexible configuration.

Fixes: 1bc7d5485c10 ("fwd: Consolidate scans (not rebinds) in fwd.c")
Link: https://bugs.passt.top/show_bug.cgi?id=176
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Revert "fwd: Update all port maps before applying exclusions"</title>
<updated>2025-11-21T03:16:57+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-11-19T04:26:32+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=bdbdf4ed42ef8c30d3008d306ac237c28824221d'/>
<id>bdbdf4ed42ef8c30d3008d306ac237c28824221d</id>
<content type='text'>
This reverts commit 81942a2417357ff10b02ccc8275cde2d4d6fbfbe.

That commit was based on the premise of trying to make all the exclusions
use the "latest" scan data.  That was a fundamentally wrong approach: what
we need to exclude is listening ports that pasta itself has created.  That
is, we need to exclude ports that we were _already_ listening on, not ones
that we intend to listen once we rebind - we *want* the old data.

Reverting this reduces the cases in which bug 176 occurs, but it's not a
complete fix.

Link: https://bugs.passt.top/show_bug.cgi?id=176
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This reverts commit 81942a2417357ff10b02ccc8275cde2d4d6fbfbe.

That commit was based on the premise of trying to make all the exclusions
use the "latest" scan data.  That was a fundamentally wrong approach: what
we need to exclude is listening ports that pasta itself has created.  That
is, we need to exclude ports that we were _already_ listening on, not ones
that we intend to listen once we rebind - we *want* the old data.

Reverting this reduces the cases in which bug 176 occurs, but it's not a
complete fix.

Link: https://bugs.passt.top/show_bug.cgi?id=176
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Update all port maps before applying exclusions</title>
<updated>2025-10-31T23:23:06+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:29+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=81942a2417357ff10b02ccc8275cde2d4d6fbfbe'/>
<id>81942a2417357ff10b02ccc8275cde2d4d6fbfbe</id>
<content type='text'>
In fwd_scan_ports() we go through each of the automatic forwarding cases
(tcp, udp, inbound and outbound) in turn, scanning and calculating the
new forwarding map.  However, to avoid avoid circular forwarding, some of
these maps affect each other.  This has the odd effect that the ones
handled earlier are based on the previous scan of other maps, whereas
the later ones are based on the latest scan.

That's not generally harmful, but it is counter-intuitive and results in a
few odd edge cases.  Avoid this by performing all the scans first, without
regard to other maps, then applying the exclusions afterwards.

One case has an extra wrinkle: for UDP we forwarded not just ports that
were listening on UDP but ones listening on TCP as well, for the benefit of
protocols like iperf3.  We therefore also excluded listening ports from
both UDP and TCP from the other direction to avoid circular forwarding.

This doesn't really make sense, though.  To avoid circular forwarding, we
don't care *why* the other side is listening on UDP, just that it *is*
listening.  This was only needed because the reverse map might have been
one cycle out of date and therefore not included a port opened because of
the corresponding TCP port.

Now that we avoid that out of date map possibility, it's sufficient to
just mask out UDP listening ports in the other direction.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In fwd_scan_ports() we go through each of the automatic forwarding cases
(tcp, udp, inbound and outbound) in turn, scanning and calculating the
new forwarding map.  However, to avoid avoid circular forwarding, some of
these maps affect each other.  This has the odd effect that the ones
handled earlier are based on the previous scan of other maps, whereas
the later ones are based on the latest scan.

That's not generally harmful, but it is counter-intuitive and results in a
few odd edge cases.  Avoid this by performing all the scans first, without
regard to other maps, then applying the exclusions afterwards.

One case has an extra wrinkle: for UDP we forwarded not just ports that
were listening on UDP but ones listening on TCP as well, for the benefit of
protocols like iperf3.  We therefore also excluded listening ports from
both UDP and TCP from the other direction to avoid circular forwarding.

This doesn't really make sense, though.  To avoid circular forwarding, we
don't care *why* the other side is listening on UDP, just that it *is*
listening.  This was only needed because the reverse map might have been
one cycle out of date and therefore not included a port opened because of
the corresponding TCP port.

Now that we avoid that out of date map possibility, it's sufficient to
just mask out UDP listening ports in the other direction.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Check forwarding mode in fwd_scan_ports_*() rather than caller</title>
<updated>2025-10-31T23:23:04+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:28+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=942bfdb801732e9076ebc90e9d8206513ddbcd90'/>
<id>942bfdb801732e9076ebc90e9d8206513ddbcd90</id>
<content type='text'>
fwd_scan_ports() needs to check for FWD_AUTO mode before calling each
scan function - otherwise it would clobber the forwarding bitmap which
should retain the user's fixed configuration.

Make this slightly cleaner and safer by moving the mode check into
fwd_scan_ports_{tcp,udp}().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
fwd_scan_ports() needs to check for FWD_AUTO mode before calling each
scan function - otherwise it would clobber the forwarding bitmap which
should retain the user's fixed configuration.

Make this slightly cleaner and safer by moving the mode check into
fwd_scan_ports_{tcp,udp}().

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Share port scanning logic between init and timer cases</title>
<updated>2025-10-31T23:23:02+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:27+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=06c3dcc2a6e2a814b52dc2549ef3db8c0771b454'/>
<id>06c3dcc2a6e2a814b52dc2549ef3db8c0771b454</id>
<content type='text'>
When using -t auto and the like, we scan for listening ports once at
startup, then repeatedly on a timer.  With previous rearrangements the
logic for each of these cases is very nearly repeated.  Factor it out into
a fwd_scan_ports() function.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When using -t auto and the like, we scan for listening ports once at
startup, then repeatedly on a timer.  With previous rearrangements the
logic for each of these cases is very nearly repeated.  Factor it out into
a fwd_scan_ports() function.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Move port exclusion handling from procfs_scan_listen() to callers</title>
<updated>2025-10-31T23:23:00+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:26+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=1754f61e9ac81c051b5c165059a549a3e9156dfc'/>
<id>1754f61e9ac81c051b5c165059a549a3e9156dfc</id>
<content type='text'>
To avoid forwarding loops, we need to exclude certain ports from being
auto-forwarded.  To accomplish this, procfs_scan_listen() takes a bitmap
of exclusions.  As it detects each port, it checks against that bitmap.
This is a complicated way of accomplishing what we need.  We can instead
mask out the excluded ports in the callers using a new bitmap_and_not()
helper.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
To avoid forwarding loops, we need to exclude certain ports from being
auto-forwarded.  To accomplish this, procfs_scan_listen() takes a bitmap
of exclusions.  As it detects each port, it checks against that bitmap.
This is a complicated way of accomplishing what we need.  We can instead
mask out the excluded ports in the callers using a new bitmap_and_not()
helper.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd: Consolidate scans (not rebinds) in fwd.c</title>
<updated>2025-10-31T23:22:58+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:25+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=1bc7d5485c103497643ce681b1c30133cba6dd19'/>
<id>1bc7d5485c103497643ce681b1c30133cba6dd19</id>
<content type='text'>
fwd_scan_ports_timer(), via the things it calls, goes through all the auto
forwarding cases (tcp, udp, inbound, outbound) and for each one first scans
for listening ports, then rebinds - that is, closes or opens our own
listening ports to match.

Rearrange to do all the scans first, then all the rebinds after.  This lets
us consolidate all the scans into fwd.c, and will enable further cleanups.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
fwd_scan_ports_timer(), via the things it calls, goes through all the auto
forwarding cases (tcp, udp, inbound, outbound) and for each one first scans
for listening ports, then rebinds - that is, closes or opens our own
listening ports to match.

Rearrange to do all the scans first, then all the rebinds after.  This lets
us consolidate all the scans into fwd.c, and will enable further cleanups.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tcp, udp, fwd: Run all port scanning from a single timer</title>
<updated>2025-10-31T23:22:55+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-10-31T04:19:24+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=260075bde769b6abbf6350e930f44b9fc7d5303a'/>
<id>260075bde769b6abbf6350e930f44b9fc7d5303a</id>
<content type='text'>
With -t auto and similar options we need to periodically scan /proc for
listening ports.  Currently we do this separately for TCP and UDP, from
tcp_timer() and udp_timer().

For upcoming changes (leading eventually to a more general forwarding
table), it's awkward to have these separate.  Move them to a single common
timer.  For now this just calls new tcp_scan_ports() and udp_scan_ports()
functions, but we'll consolidate more thoroughly in later patches.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
With -t auto and similar options we need to periodically scan /proc for
listening ports.  Currently we do this separately for TCP and UDP, from
tcp_timer() and udp_timer().

For upcoming changes (leading eventually to a more general forwarding
table), it's awkward to have these separate.  Move them to a single common
timer.  For now this just calls new tcp_scan_ports() and udp_scan_ports()
functions, but we'll consolidate more thoroughly in later patches.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
