* [PATCH v2 1/2] tcp, udp, conf: Don't silently ignore listens on unsupported IP versions
2026-01-13 3:06 [PATCH v2 0/2] Allow listen functions to return fds David Gibson
@ 2026-01-13 3:06 ` David Gibson
2026-01-13 3:06 ` [PATCH v2 2/2] tcp, udp: Make {tcp,udp}_listen() return socket fds David Gibson
1 sibling, 0 replies; 3+ messages in thread
From: David Gibson @ 2026-01-13 3:06 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Currently, it's possible to explicitly ask for forwarding from an IPv4
address, while disabling IPv4:
$ pasta -t 192.0.2.1/12345 -6
or vice versa:
$ pasta -t 2001:db8::1/12345 -4
Currently, the impossible to implement forwarding option will be silently
ignored. That's potentially confusing since in a complex setup, it might
not be obvious why the requested forward isn't taking effect.
Specifically, it's ignored at a fairly low level: tcp_listen() and
udp_listen() ignore it and return 0. Those run kind of late to give a
good error message. Change the low-level functions to return
-EAFNOSUPPORT. Most callers of {tcp,udp}_listen() ignore the return code,
so this is a no-op for them. In the remaining caller,
conf_ports_range_except() check for the case explicitly, and provide a
meaningful error message.
Of itself, this bug is insignificant, but this is a roadblock to having
{tcp,udp}_listen() return socket fds, which in turn is a roadblock to my
flexible forwarding work. So, might as well fix it.
Link: https://bugs.passt.top/show_bug.cgi?id=186
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
conf.c | 10 ++++++++++
tcp.c | 6 ++----
udp.c | 6 ++----
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/conf.c b/conf.c
index b1fc4b9f..9a0d945d 100644
--- a/conf.c
+++ b/conf.c
@@ -162,6 +162,16 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
optname, optarg);
}
+ if (addr) {
+ if (!c->ifi4 && inany_v4(addr)) {
+ die("IPv4 is disabled, can't use -%c %s",
+ optname, optarg);
+ } else if (!c->ifi6 && !inany_v4(addr)) {
+ die("IPv6 is disabled, can't use -%c %s",
+ optname, optarg);
+ }
+ }
+
for (i = first; i <= last; i++) {
if (bitmap_isset(exclude, i))
continue;
diff --git a/tcp.c b/tcp.c
index e0b874e7..664f843d 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2698,16 +2698,14 @@ int tcp_listen(const struct ctx *c, uint8_t pif,
/* Restrict to v6 only */
addr = &inany_any6;
else if (inany_v4(addr))
- /* Nothing to do */
- return 0;
+ return -EAFNOSUPPORT;
}
if (!c->ifi6) {
if (!addr)
/* Restrict to v4 only */
addr = &inany_any4;
else if (!inany_v4(addr))
- /* Nothing to do */
- return 0;
+ return -EAFNOSUPPORT;
}
if (pif == PIF_HOST) {
diff --git a/udp.c b/udp.c
index 747d4dd4..ea28f5b3 100644
--- a/udp.c
+++ b/udp.c
@@ -1162,16 +1162,14 @@ int udp_listen(const struct ctx *c, uint8_t pif,
/* Restrict to v6 only */
addr = &inany_any6;
else if (inany_v4(addr))
- /* Nothing to do */
- return 0;
+ return -EAFNOSUPPORT;
}
if (!c->ifi6) {
if (!addr)
/* Restrict to v4 only */
addr = &inany_any4;
else if (!inany_v4(addr))
- /* Nothing to do */
- return 0;
+ return -EAFNOSUPPORT;
}
s = pif_sock_l4(c, EPOLL_TYPE_UDP_LISTEN, pif,
--
2.52.0
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH v2 2/2] tcp, udp: Make {tcp,udp}_listen() return socket fds
2026-01-13 3:06 [PATCH v2 0/2] Allow listen functions to return fds David Gibson
2026-01-13 3:06 ` [PATCH v2 1/2] tcp, udp, conf: Don't silently ignore listens on unsupported IP versions David Gibson
@ 2026-01-13 3:06 ` David Gibson
1 sibling, 0 replies; 3+ messages in thread
From: David Gibson @ 2026-01-13 3:06 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
{tcp,udp}_listen() currently return 0 on success, rather than the socket
fd they created. Historically, that was because these functions could
sometimes create multiple sockets. We've now refactored things to avoid
that, so it makes more sense for them to return the socket on success.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
conf.c | 14 +++++++-------
tcp.c | 7 ++-----
udp.c | 4 ++--
3 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/conf.c b/conf.c
index 9a0d945d..3eaa6c8c 100644
--- a/conf.c
+++ b/conf.c
@@ -149,7 +149,7 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
{
bool bound_one = false;
unsigned i;
- int ret;
+ int fd;
if (first == 0) {
die("Can't forward port 0 for option '-%c %s'",
@@ -185,23 +185,23 @@ static void conf_ports_range_except(const struct ctx *c, char optname,
fwd->delta[i] = to - first;
if (optname == 't')
- ret = tcp_listen(c, PIF_HOST, addr, ifname, i);
+ fd = tcp_listen(c, PIF_HOST, addr, ifname, i);
else if (optname == 'u')
- ret = udp_listen(c, PIF_HOST, addr, ifname, i);
+ fd = udp_listen(c, PIF_HOST, addr, ifname, i);
else
/* No way to check in advance for -T and -U */
- ret = 0;
+ fd = 0;
- if (ret == -ENFILE || ret == -EMFILE) {
+ if (fd == -ENFILE || fd == -EMFILE) {
die("Can't open enough sockets for port specifier: %s",
optarg);
}
- if (!ret) {
+ if (fd >= 0) {
bound_one = true;
} else if (!weak) {
die("Failed to bind port %u (%s) for option '-%c %s'",
- i, strerror_(-ret), optname, optarg);
+ i, strerror_(-fd), optname, optarg);
}
}
diff --git a/tcp.c b/tcp.c
index 664f843d..e1b38e85 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2678,7 +2678,7 @@ void tcp_sock_handler(const struct ctx *c, union epoll_ref ref,
* @ifname: Name of interface to bind to, NULL for any
* @port: Port, host order
*
- * Return: 0 on success, negative error code on failure
+ * Return: socket fd on success, negative error code on failure
*/
int tcp_listen(const struct ctx *c, uint8_t pif,
const union inany_addr *addr, const char *ifname, in_port_t port)
@@ -2727,10 +2727,7 @@ int tcp_listen(const struct ctx *c, uint8_t pif,
socks[port][V6] = s < 0 ? -1 : s;
}
- if (s < 0)
- return s;
-
- return 0;
+ return s;
}
/**
diff --git a/udp.c b/udp.c
index ea28f5b3..993d53fc 100644
--- a/udp.c
+++ b/udp.c
@@ -1136,7 +1136,7 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif,
* @ifname: Name of interface to bind to, NULL if not configured
* @port: Port, host order
*
- * Return: 0 on success, negative error code on failure
+ * Return: socket fd on success, negative error code on failure
*/
int udp_listen(const struct ctx *c, uint8_t pif,
const union inany_addr *addr, const char *ifname, in_port_t port)
@@ -1180,7 +1180,7 @@ int udp_listen(const struct ctx *c, uint8_t pif,
if (!addr || !inany_v4(addr))
socks[V6][port] = s < 0 ? -1 : s;
- return s < 0 ? s : 0;
+ return s;
}
/**
--
2.52.0
^ permalink raw reply [flat|nested] 3+ messages in thread