From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 7/8] fwd: Update all port maps before applying exclusions
Date: Sat, 11 Oct 2025 15:48:26 +1100 [thread overview]
Message-ID: <20251011044827.862757-8-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20251011044827.862757-1-david@gibson.dropbear.id.au>
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. I believe the explicit handling of the reverse TCP map 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 <david@gibson.dropbear.id.au>
---
fwd.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/fwd.c b/fwd.c
index 57941759..395b0def 100644
--- a/fwd.c
+++ b/fwd.c
@@ -146,10 +146,8 @@ static void procfs_scan_listen(int fd, unsigned int lstate, uint8_t *map)
/**
* fwd_scan_ports_tcp() - Scan /proc to update TCP forwarding map
* @fwd: Forwarding information to update
- * @rev: Forwarding information for the reverse direction
*/
-static void fwd_scan_ports_tcp(struct fwd_ports *fwd,
- const struct fwd_ports *rev)
+static void fwd_scan_ports_tcp(struct fwd_ports *fwd)
{
if (fwd->mode != FWD_AUTO)
return;
@@ -157,20 +155,15 @@ static void fwd_scan_ports_tcp(struct fwd_ports *fwd,
memset(fwd->map, 0, PORT_BITMAP_SIZE);
procfs_scan_listen(fwd->scan4, TCP_LISTEN, fwd->map);
procfs_scan_listen(fwd->scan6, TCP_LISTEN, fwd->map);
- bitmap_andc(fwd->map, PORT_BITMAP_SIZE, fwd->map, rev->map);
}
/**
* fwd_scan_ports_udp() - Scan /proc to update UDP forwarding map
* @fwd: Forwarding information to update
- * @rev: Forwarding information for the reverse direction
* @tcp_fwd: Corresponding TCP forwarding information
- * @tcp_rev: TCP forwarding information for the reverse direction
*/
static void fwd_scan_ports_udp(struct fwd_ports *fwd,
- const struct fwd_ports *rev,
- const struct fwd_ports *tcp_fwd,
- const struct fwd_ports *tcp_rev)
+ const struct fwd_ports *tcp_fwd)
{
if (fwd->mode != FWD_AUTO)
return;
@@ -186,15 +179,6 @@ static void fwd_scan_ports_udp(struct fwd_ports *fwd,
*/
procfs_scan_listen(tcp_fwd->scan4, TCP_LISTEN, fwd->map);
procfs_scan_listen(tcp_fwd->scan6, TCP_LISTEN, fwd->map);
-
- /*
- * This means we need to skip numbers of TCP ports bound on the other
- * side, too. Otherwise, we would detect corresponding UDP ports as
- * bound and try to forward them from the opposite side, but it's
- * already us handling them.
- */
- bitmap_andc(fwd->map, PORT_BITMAP_SIZE, fwd->map, rev->map);
- bitmap_andc(fwd->map, PORT_BITMAP_SIZE, fwd->map, tcp_rev->map);
}
/**
@@ -203,12 +187,28 @@ static void fwd_scan_ports_udp(struct fwd_ports *fwd,
*/
static void fwd_scan_ports(struct ctx *c)
{
- fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
- fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
- fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.fwd_in,
- &c->tcp.fwd_out, &c->tcp.fwd_in);
- fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.fwd_out,
- &c->tcp.fwd_in, &c->tcp.fwd_out);
+ fwd_scan_ports_tcp(&c->tcp.fwd_out);
+ fwd_scan_ports_tcp(&c->tcp.fwd_in);
+ fwd_scan_ports_udp(&c->udp.fwd_out, &c->tcp.fwd_out);
+ fwd_scan_ports_udp(&c->udp.fwd_in, &c->tcp.fwd_in);
+
+ if (c->tcp.fwd_out.mode == FWD_AUTO) {
+ bitmap_andc(c->tcp.fwd_out.map, PORT_BITMAP_SIZE,
+ c->tcp.fwd_out.map, c->tcp.fwd_in.map);
+ }
+ if (c->tcp.fwd_in.mode == FWD_AUTO) {
+ bitmap_andc(c->tcp.fwd_in.map, PORT_BITMAP_SIZE,
+ c->tcp.fwd_in.map, c->tcp.fwd_out.map);
+ }
+
+ if (c->udp.fwd_out.mode == FWD_AUTO) {
+ bitmap_andc(c->udp.fwd_out.map, PORT_BITMAP_SIZE,
+ c->udp.fwd_out.map, c->udp.fwd_in.map);
+ }
+ if (c->udp.fwd_in.mode == FWD_AUTO) {
+ bitmap_andc(c->udp.fwd_in.map, PORT_BITMAP_SIZE,
+ c->udp.fwd_in.map, c->udp.fwd_out.map);
+ }
}
/**
--
2.51.0
next prev parent reply other threads:[~2025-10-11 4:49 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-11 4:48 [PATCH 0/8] RFC: Cleanups to auto port scanning David Gibson
2025-10-11 4:48 ` [PATCH 1/8] icmp: Remove vestiges of ICMP timer David Gibson
2025-10-11 4:48 ` [PATCH 2/8] tcp, udp, fwd: Run all port scanning from a single timer David Gibson
2025-10-11 4:48 ` [PATCH 3/8] fwd: Consolidate scans (not rebinds) in fwd.c David Gibson
2025-10-11 4:48 ` [PATCH 4/8] fwd: Move port exclusion handling from procfs_scan_listen() to callers David Gibson
2025-10-11 4:48 ` [PATCH 5/8] fwd: Share port scanning logic between init and timer cases David Gibson
2025-10-11 4:48 ` [PATCH 6/8] fwd: Check forwarding mode in fwd_scan_ports_*() rather than caller David Gibson
2025-10-11 4:48 ` David Gibson [this message]
2025-10-11 4:48 ` [PATCH 8/8] tcp, udp: Don't exclude ports in {tcp,udp}_port_rebind() David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251011044827.862757-8-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).