public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH] conf, pasta: Add --no-tap option
@ 2025-12-29  9:55 Yumei Huang
  0 siblings, 0 replies; only message in thread
From: Yumei Huang @ 2025-12-29  9:55 UTC (permalink / raw)
  To: passt-dev, sbrivio; +Cc: david, yuhuang

This patch introduces a mode where we only forward loopback connections
and traffic between two namespaces (via the loopback interface, 'lo'),
without a tap device.

With this, podman can support forwarding ::1 in custom networks when using
rootlesskit for forwarding ports.

In --no-tap mode, --host-lo-to-ns-lo, --no-icmp and --no-ra is automatically
enabled. Options requiring a tap device (--ns-ifname, --ns-mac-addr,
--config-net, --outbound-if4/6) are rejected.

Link: https://bugs.passt.top/show_bug.cgi?id=149
Signed-off-by: Yumei Huang <yuhuang@redhat.com>
---
 conf.c  | 56 +++++++++++++++++++++++++++++++++++++++++---------------
 fwd.c   |  3 +++
 passt.1 |  5 +++++
 passt.h |  2 ++
 pasta.c |  3 +++
 tap.c   | 11 +++++++----
 6 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/conf.c b/conf.c
index 84ae12b..353d0a5 100644
--- a/conf.c
+++ b/conf.c
@@ -1049,7 +1049,8 @@ pasta_opts:
 		"  --no-copy-addrs	DEPRECATED:\n"
 		"			Don't copy all addresses to namespace\n"
 		"  --ns-mac-addr ADDR	Set MAC address on tap interface\n"
-		"  --no-splice		Disable inbound socket splicing\n");
+		"  --no-splice		Disable inbound socket splicing\n"
+		"  --no-tap		Don't create tap device\n");
 
 	passt_exit(status);
 }
@@ -1451,6 +1452,7 @@ void conf(struct ctx *c, int argc, char **argv)
 		{"no-ndp",	no_argument,		&c->no_ndp,	1 },
 		{"no-ra",	no_argument,		&c->no_ra,	1 },
 		{"no-splice",	no_argument,		&c->no_splice,	1 },
+		{"no-tap",	no_argument,		&c->no_tap,	1 },
 		{"freebind",	no_argument,		&c->freebind,	1 },
 		{"no-map-gw",	no_argument,		&no_map_gw,	1 },
 		{"ipv4-only",	no_argument,		NULL,		'4' },
@@ -1947,8 +1949,11 @@ void conf(struct ctx *c, int argc, char **argv)
 		}
 	} while (name != -1);
 
-	if (c->mode != MODE_PASTA)
+	if (c->mode != MODE_PASTA) {
 		c->no_splice = 1;
+		if (c->no_tap)
+			die("--no-tap is for pasta mode only");
+	}
 
 	if (c->mode == MODE_PASTA && !c->pasta_conf_ns) {
 		if (copy_routes_opt)
@@ -1957,6 +1962,25 @@ void conf(struct ctx *c, int argc, char **argv)
 			die("--no-copy-addrs needs --config-net");
 	}
 
+	if (c->mode == MODE_PASTA && c->no_tap) {
+		if (c->no_splice)
+			die("--no-tap is incompatible with --no-splice");
+		if (*c->ip4.ifname_out || *c->ip6.ifname_out)
+			die("--no-tap is incompatible with --outbound-if4/6");
+		if (*c->pasta_ifn)
+			die("--no-tap is incompatible with --ns-ifname");
+		if (*c->guest_mac)
+			die("--no-tap is incompatible with --ns-mac-addr");
+		if (c->pasta_conf_ns)
+			die("--no-tap is incompatible with --config-net");
+
+		c->host_lo_to_ns_lo = 1;
+		c->no_icmp = 1;
+		c->no_ra = 1;
+		c->no_dns = 1;
+		c->no_dns_search = 1;
+	}
+
 	if (!ifi4 && *c->ip4.ifname_out)
 		ifi4 = if_nametoindex(c->ip4.ifname_out);
 
@@ -1980,9 +2004,9 @@ void conf(struct ctx *c, int argc, char **argv)
 	log_conf_parsed = true;		/* Stop printing everything */
 
 	nl_sock_init(c, false);
-	if (!v6_only)
+	if (!v6_only && !c->no_tap)
 		c->ifi4 = conf_ip4(ifi4, &c->ip4);
-	if (!v4_only)
+	if (!v4_only && !c->no_tap)
 		c->ifi6 = conf_ip6(ifi6, &c->ip6);
 
 	if (c->ifi4 && c->mtu < IPV4_MIN_MTU) {
@@ -1998,30 +2022,32 @@ void conf(struct ctx *c, int argc, char **argv)
 	    (*c->ip6.ifname_out && !c->ifi6))
 		die("External interface not usable");
 
-	if (!c->ifi4 && !c->ifi6 && !*c->pasta_ifn) {
+	if (!c->ifi4 && !c->ifi6 && !*c->pasta_ifn && !c->no_tap) {
 		strncpy(c->pasta_ifn, pasta_default_ifn,
 			sizeof(c->pasta_ifn) - 1);
 	}
 
 	if (!c->ifi4 && !v6_only) {
-		info("IPv4: no external interface as template, use local mode");
-
-		conf_ip4_local(&c->ip4);
+		if (!c->no_tap) {
+			info("IPv4: no external interface as template, use local mode");
+			conf_ip4_local(&c->ip4);
+		}
 		c->ifi4 = -1;
 	}
 
 	if (!c->ifi6 && !v4_only) {
-		info("IPv6: no external interface as template, use local mode");
-
-		conf_ip6_local(&c->ip6);
+		if (!c->no_tap) {
+			info("IPv6: no external interface as template, use local mode");
+			conf_ip6_local(&c->ip6);
+		}
 		c->ifi6 = -1;
 	}
 
-	if (c->ifi4 && !no_map_gw &&
+	if (c->ifi4 > 0 && !no_map_gw &&
 	    IN4_IS_ADDR_UNSPECIFIED(&c->ip4.map_host_loopback))
 		c->ip4.map_host_loopback = c->ip4.guest_gw;
 
-	if (c->ifi6 && !no_map_gw &&
+	if (c->ifi6 > 0 && !no_map_gw &&
 	    IN6_IS_ADDR_UNSPECIFIED(&c->ip6.map_host_loopback))
 		c->ip6.map_host_loopback = c->ip6.guest_gw;
 
@@ -2116,10 +2142,10 @@ void conf(struct ctx *c, int argc, char **argv)
 			conf_ports(c, name, optarg, &c->udp.fwd_out);
 	} while (name != -1);
 
-	if (!c->ifi4)
+	if (c->ifi4 <= 0)
 		c->no_dhcp = 1;
 
-	if (!c->ifi6) {
+	if (c->ifi6 <= 0) {
 		c->no_ndp = 1;
 		c->no_dhcpv6 = 1;
 	} else if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr)) {
diff --git a/fwd.c b/fwd.c
index 44a0e10..2f4a89a 100644
--- a/fwd.c
+++ b/fwd.c
@@ -780,6 +780,9 @@ uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto,
 		return PIF_SPLICE;
 	}
 
+	if (c->no_tap)
+		return PIF_NONE;
+
 	if (!nat_inbound(c, &ini->eaddr, &tgt->oaddr)) {
 		if (inany_v4(&ini->eaddr)) {
 			if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.our_tap_addr))
diff --git a/passt.1 b/passt.1
index db0d662..2d643f7 100644
--- a/passt.1
+++ b/passt.1
@@ -755,6 +755,11 @@ Default is to let the tap driver build a pseudorandom hardware address.
 Disable the bypass path for inbound, local traffic. See the section \fBHandling
 of local traffic in pasta\fR in the \fBNOTES\fR for more details.
 
+.TP
+.BR \-\-no-tap
+Do not create a tap device in the namespace. In this mode, only local loopback
+traffic between namespaces is forwarded using splice.
+
 .SH EXAMPLES
 
 .SS \fBpasta
diff --git a/passt.h b/passt.h
index 79d01dd..0c1ec4c 100644
--- a/passt.h
+++ b/passt.h
@@ -200,6 +200,7 @@ struct ip6_ctx {
  * @no_ndp:		Disable NDP handler altogether
  * @no_ra:		Disable router advertisements
  * @no_splice:		Disable socket splicing for inbound traffic
+ * @no_tap:		Do not create tap device
  * @host_lo_to_ns_lo:	Map host loopback addresses to ns loopback addresses
  * @freebind:		Allow binding of non-local addresses for forwarding
  * @low_wmem:		Low probed net.core.wmem_max
@@ -277,6 +278,7 @@ struct ctx {
 	int no_ndp;
 	int no_ra;
 	int no_splice;
+	int no_tap;
 	int host_lo_to_ns_lo;
 	int freebind;
 
diff --git a/pasta.c b/pasta.c
index 0ddd6b0..3510ec5 100644
--- a/pasta.c
+++ b/pasta.c
@@ -316,6 +316,9 @@ void pasta_ns_conf(struct ctx *c)
 		die("Couldn't bring up loopback interface in namespace: %s",
 		    strerror_(-rc));
 
+	if (c->no_tap)
+		return;
+
 	/* Get or set MAC in target namespace */
 	if (MAC_IS_ZERO(c->guest_mac))
 		nl_link_get_mac(nl_sock_ns, c->pasta_ifi, c->guest_mac);
diff --git a/tap.c b/tap.c
index 9d1344b..9b4eedc 100644
--- a/tap.c
+++ b/tap.c
@@ -1491,13 +1491,16 @@ static int tap_ns_tun(void *arg)
  */
 static void tap_sock_tun_init(struct ctx *c)
 {
-	NS_CALL(tap_ns_tun, c);
-	if (c->fd_tap == -1)
-		die("Failed to set up tap device in namespace");
+	if (!c->no_tap) {
+		NS_CALL(tap_ns_tun, c);
+		if (c->fd_tap == -1)
+			die("Failed to set up tap device in namespace");
+	}
 
 	pasta_ns_conf(c);
 
-	tap_start_connection(c);
+	if (!c->no_tap)
+		tap_start_connection(c);
 }
 
 /**
-- 
2.49.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-12-29  9:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-29  9:55 [PATCH] conf, pasta: Add --no-tap option Yumei Huang

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).