public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH v3 03/14] conf: Accurately record ifname and address for outbound forwards
Date: Thu,  8 Jan 2026 13:29:37 +1100	[thread overview]
Message-ID: <20260108022948.2657573-4-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260108022948.2657573-1-david@gibson.dropbear.id.au>

-T and -U options don't allow specifying a listening address.  Usually this
will listen on *%lo in the guest.  However on kernels without unprivileged
SO_BINDTODEVICE that's not possible so we instead listen separately on
127.0.0.1 and ::1.

Currently that's handled at the point we actually set up the listens,
we record both address and ifname as NULL in the forwarding table
entry.  That will cause trouble for future extensions we want, so
update this to accurately create the forwarding table: either a single
rule with ifname == "lo" or two rules with addresses of 127.0.0.1 and
::1.

As a bonus, this gives the user a warning if they specify an explicit
outbound forwarding on a kernel without SO_BINDTODEVICE.  The existing
warning for missing SO_BINDTODEVICE incorrectly covered only the case
of -T auto or -U auto.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 conf.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/conf.c b/conf.c
index 127e69f5..b486fefe 100644
--- a/conf.c
+++ b/conf.c
@@ -157,12 +157,6 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
 		    optname, optarg);
 	}
 
-	if (ifname && c->no_bindtodevice) {
-		die(
-"Device binding for '-%c %s' unsupported (requires kernel 5.7+)",
-		    optname, optarg);
-	}
-
 	if (addr) {
 		if (!c->ifi4 && inany_v4(addr)) {
 			die("IPv4 is disabled, can't use -%c %s",
@@ -209,8 +203,27 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
 			}
 		}
 
-		fwd_rule_add(fwd, flags, addr, ifname, base, i - 1,
-			     base + delta);
+		if ((optname == 'T' || optname == 'U') && c->no_bindtodevice) {
+			/* FIXME: Once the fwd bitmaps are removed, move this
+			 * workaround to the caller
+			 */
+			ASSERT(!addr && ifname && !strcmp(ifname, "lo"));
+			warn(
+"SO_BINDTODEVICE unavailable, forwarding only 127.0.0.1 and ::1 for '-%c %s'",
+			     optname, optarg);
+
+			if (c->ifi4) {
+				fwd_rule_add(fwd, flags, &inany_loopback4, NULL,
+					     base, i - 1, base + delta);
+			}
+			if (c->ifi6) {
+				fwd_rule_add(fwd, flags, &inany_loopback6, NULL,
+					     base, i - 1, base + delta);
+			}
+		} else {
+			fwd_rule_add(fwd, flags, addr, ifname,
+				     base, i - 1, base + delta);
+		}
 		base = i - 1;
 	}
 
@@ -357,6 +370,15 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
 		}
 	} while ((p = next_chunk(p, ',')));
 
+	if (ifname && c->no_bindtodevice) {
+		die(
+"Device binding for '-%c %s' unsupported (requires kernel 5.7+)",
+		    optname, optarg);
+	}
+	/* Outbound forwards come from guest loopback */
+	if ((optname == 'T' || optname == 'U') && !ifname)
+		ifname = "lo";
+
 	if (exclude_only) {
 		/* Exclude ephemeral ports */
 		for (i = 0; i < NUM_PORTS; i++)
-- 
2.52.0


  parent reply	other threads:[~2026-01-08  2:29 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-08  2:29 [PATCH v3 00/14] Introduce forwarding table David Gibson
2026-01-08  2:29 ` [PATCH v3 01/14] inany: Extend inany_ntop() to treat NULL as a fully unspecified address David Gibson
2026-01-08 13:16   ` Laurent Vivier
2026-01-08  2:29 ` [PATCH v3 02/14] conf, fwd: Keep a table of our port forwarding configuration David Gibson
2026-01-08  2:29 ` David Gibson [this message]
2026-01-08  2:29 ` [PATCH v3 04/14] conf, fwd: Record "auto" port forwards in forwarding table David Gibson
2026-01-08  2:29 ` [PATCH v3 05/14] fwd: Make space to store listening sockets in forward table David Gibson
2026-01-08  2:29 ` [PATCH v3 06/14] ip: Add ipproto_name() function David Gibson
2026-01-08 13:22   ` Laurent Vivier
2026-01-08 23:12     ` David Gibson
2026-01-08  2:29 ` [PATCH v3 07/14] fwd, tcp, udp: Set up listening sockets based on forward table David Gibson
2026-01-08  2:29 ` [PATCH v3 08/14] tcp, udp: Remove old auto-forwarding socket arrays David Gibson
2026-01-08  2:29 ` [PATCH v3 09/14] conf, fwd: Check forwarding table for conflicting rules David Gibson
2026-01-08  2:29 ` [PATCH v3 10/14] fwd: Generate auto-forward exclusions from socket fd tables David Gibson
2026-01-08  2:29 ` [PATCH v3 11/14] flow, fwd: Consult rules table when forwarding a new flow from socket David Gibson
2026-01-08  2:29 ` [PATCH v3 12/14] fwd: Remap ports based directly on forwarding rule David Gibson
2026-01-08  2:29 ` [PATCH v3 13/14] fwd, tcp, udp: Add forwarding rule to listening socket epoll references David Gibson
2026-01-08  2:29 ` [PATCH v3 14/14] flow, fwd: Optimise forwarding rule lookup using epoll ref when possible 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=20260108022948.2657573-4-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).