Re: [PATCH RFC] net/slirp: allow hostfwd socket paths with dashes

Christopher Richez <[email protected]>
Newsgroups org.nongnu.qemu-trivial,org.nongnu.qemu-devel
Message-ID <LDF3Kn5e3KSxpz1TFKB-WC_CeVNvAHtN8FIyWxtsKo6SaMelBeuSVbA7sMg5bx0VsCapFjpDG5z7Iqg9-bB1zCIYOO7O2MzThgv5GGOaU7s=@pm.me>
This is much neater than my patch for this, thank you for taking the time to do it this way!

-------- Original Message --------
On Tuesday, 03/17/26 at 04:32 Michael Tokarev <[email protected]> wrote:
The format of hostfwd parameter is:
  hostfwd=hostpart-guestaddr:guestport
so a minus sign can not be part of the hostpart.
If hostpart specifies a unix socket path, this becomes problematic.

To solve this, look for the LAST minus/dash char in the string,
not first.

Unfortunately, [-guestaddr] is optional (defaults to 10.0.0.15),
so we still can't parse the thing in an uniform way.

Extend get_str_sep() to accept one more parameter, to indicate if
first or last separator is needed, and modify all callers to ask
for first separator.  Update slirp_hostfwd to search for the last
separator when parsing unix domain socket path.

Inspired-by: Christopher Palmer-Richez <[email protected]>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/347
---
 net/slirp.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/net/slirp.c b/net/slirp.c
index 04925f3318..804d430890 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -49,12 +49,18 @@
 #include "migration/vmstate.h"
 #include "migration/qemu-file-types.h"

-static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
+typedef enum {
+    SEP_FIRST,
+    SEP_LAST
+} sep_type;
+
+static int get_str_sep(char *buf, int buf_size, const char **pp, int sep,
+                       sep_type which)
 {
     const char *p, *p1;
     int len;
     p = *pp;
-    p1 = strchr(p, sep);
+    p1 = which == SEP_FIRST ? strchr(p, sep) : strrchr(p, sep);
     if (!p1)
         return -1;
     len = p1 - p;
@@ -479,7 +485,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
     }

     if (vnetwork) {
-        if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
+        if (get_str_sep(buf, sizeof(buf), &vnetwork, '/', SEP_FIRST) < 0) {
             if (!inet_aton(vnetwork, &net)) {
                 error_setg(errp, "Failed to parse netmask");
                 return -1;
@@ -760,7 +766,7 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
     }

     p = src_str;
-    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (!p || get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         goto fail_syntax;
     }

@@ -772,7 +778,7 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
         goto fail_syntax;
     }

-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         goto fail_syntax;
     }
     if (buf[0] != '\0' && !inet_aton(buf, &host_addr.sin_addr)) {
@@ -827,7 +833,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
     socklen_t host_addr_size;

     p = redir_str;
-    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (!p || get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         fail_reason = "No : separators";
         goto fail_syntax;
     }
@@ -848,7 +854,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)

 #if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
     if (is_unix) {
-        if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+        if (get_str_sep(buf, sizeof(buf), &p, '-', SEP_LAST) < 0) {
             fail_reason = "Missing - separator";
             goto fail_syntax;
         }
@@ -888,7 +894,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
         host_addr.in.sin_family = AF_INET;
         host_addr.in.sin_addr.s_addr = INADDR_ANY;

-        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        if (get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
             fail_reason = "Missing : separator";
             goto fail_syntax;
         }
@@ -898,7 +904,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
             goto fail_syntax;
         }

-        if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+        if (get_str_sep(buf, sizeof(buf), &p, '-', SEP_FIRST) < 0) {
             fail_reason = "Bad host port separator";
             goto fail_syntax;
         }
@@ -913,7 +919,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
         host_addr_size = sizeof(host_addr.in);
     }

-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         fail_reason = "Missing guest address";
         goto fail_syntax;
     }
@@ -1125,19 +1131,19 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
     int port;

     p = config_str;
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         goto fail_syntax;
     }
     if (strcmp(buf, "tcp") && buf[0] != '\0') {
         goto fail_syntax;
     }
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (get_str_sep(buf, sizeof(buf), &p, ':', SEP_FIRST) < 0) {
         goto fail_syntax;
     }
     if (buf[0] != '\0' && !inet_aton(buf, &server)) {
         goto fail_syntax;
     }
-    if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+    if (get_str_sep(buf, sizeof(buf), &p, '-', SEP_FIRST) < 0) {
         goto fail_syntax;
     }
     port = strtol(buf, &end, 10);
--
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.