Skip to contentSkip to conversation

Fix NBD hostname parsing issues

PATCH Applied Ján Tomko 2 participants 8 messages Jun 3, 2013 – Jun 18, 2013 Block layer

lore
Share & tools
lore

Ján Tomko

author
#0 lore raw

cover Fix NBD hostname parsing issues

Fix parsing of NBD URIs with IPv6 addresses, broken by v1.4.0-736-gf17c90b and fix parsing of NBD filenames with hostnames starting with a digit (fixed by the same commit, but only for NBD URIs):
https://lists.gnu.org/archive/html/qemu-devel/2013-05/msg04719.html

Ján Tomko (2):
qemu-socket: allow hostnames starting with a digit
nbd: strip braces from literal IPv6 address in URI

 block/nbd.c         | 11 ++++++++++-
 util/qemu-sockets.c | 13 ++++---------
 2 files changed, 14 insertions(+), 10 deletions(-)
Signature · 1 line
1.8.1.5
author
#1 lore raw

PATCH 1/2 qemu-socket: allow hostnames starting with a digit

According to RFC 1123 [1], hostnames can start with a digit too.

[1] http://tools.ietf.org/html/rfc1123#page-13

---
 util/qemu-sockets.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
util/qemu-sockets.c +4 -9
index fdd8dc4..727dafa 100644
@@ -24,7 +24,6 @@
 
 #include "monitor/monitor.h"
 #include "qemu/sockets.h"
-#include "qemu-common.h" /* for qemu_isdigit */
 #include "qemu/main-loop.h"
 
 #ifndef AI_ADDRCONFIG
@@ -511,19 +510,15 @@ InetSocketAddress *inet_parse(const char *str, Error **errp)
             goto fail;
         }
         addr->ipv6 = addr->has_ipv6 = true;
-    } else if (qemu_isdigit(str[0])) {
-        /* IPv4 addr */
-        if (2 != sscanf(str, "%64[0-9.]:%32[^,]%n", host, port, &pos)) {
-            error_setg(errp, "error parsing IPv4 address '%s'", str);
-            goto fail;
-        }
-        addr->ipv4 = addr->has_ipv4 = true;
     } else {
-        /* hostname */
+        /* hostname or IPv4 addr */
         if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
             error_setg(errp, "error parsing address '%s'", str);
             goto fail;
         }
+        if (strcspn(host, "0123456789.") == 0) {
+            addr->ipv4 = addr->has_ipv4 = true;
+        }
     }
 
     addr->host = g_strdup(host);
Signature · 1 line
1.8.1.5
#2 lore raw

Re: [Qemu-devel] [PATCH 1/2] qemu-socket: allow hostnames starting with a digit

Il 03/06/2013 17:54, Ján Tomko ha scritto:

Quoted 30 lines

According to RFC 1123 [1], hostnames can start with a digit too.

[1] http://tools.ietf.org/html/rfc1123#page-13

---
 util/qemu-sockets.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
util/qemu-sockets.c +0 -6
index fdd8dc4..727dafa 100644
@@ -24,7 +24,6 @@
 
 #include "monitor/monitor.h"
 #include "qemu/sockets.h"
-#include "qemu-common.h" /* for qemu_isdigit */
 #include "qemu/main-loop.h"
 
 #ifndef AI_ADDRCONFIG
@@ -511,19 +510,15 @@ InetSocketAddress *inet_parse(const char *str, Error **errp)
             goto fail;
         }
         addr->ipv6 = addr->has_ipv6 = true;
-    } else if (qemu_isdigit(str[0])) {
-        /* IPv4 addr */
-        if (2 != sscanf(str, "%64[0-9.]:%32[^,]%n", host, port, &pos)) {
-            error_setg(errp, "error parsing IPv4 address '%s'", str);
-            goto fail;

util/qemu-sockets.c InetSocketAddress *inet_parse(const char *str, Error **errp) · line 519

Quoted 10 lines
util/qemu-sockets.c +2 -3
-        }
-        addr->ipv4 = addr->has_ipv4 = true;
     } else {
-        /* hostname */
+        /* hostname or IPv4 addr */
         if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
             error_setg(errp, "error parsing address '%s'", str);
             goto fail;
         }
+        if (strcspn(host, "0123456789.") == 0) {

I think what you want here is:

        if (host[strspn(host, "0123456789.")] == '\0') {

Otherwise, you're still basically testing

	qemu_isdigit(str[0]) || str[0] == '.'

Paolo

Quoted 6 lines
util/qemu-sockets.c +2 -0
+            addr->ipv4 = addr->has_ipv4 = true;
+        }
     }
 
     addr->host = g_strdup(host);
author
#3 lore raw

Re: [Qemu-devel] [PATCH 1/2] qemu-socket: allow hostnames starting with a digit

Quoted 17 lines · Paolo Bonzini

Il 03/06/2013 17:54, Ján Tomko ha scritto:

Quoted 8 lines

According to RFC 1123 [1], hostnames can start with a digit too.

[1] http://tools.ietf.org/html/rfc1123#page-13

---

     } else {

util/qemu-sockets.c InetSocketAddress *inet_parse(const char *str, Error **errp) · line 519

Quoted 7 lines
util/qemu-sockets.c +2 -1
-        /* hostname */
+        /* hostname or IPv4 addr */
         if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
             error_setg(errp, "error parsing address '%s'", str);
             goto fail;
         }
+        if (strcspn(host, "0123456789.") == 0) {
Quoted 4 lines

I think what you want here is:

        if (host[strspn(host, "0123456789.")] == '\0') {

Yes, thank you for catching that.

Jan

Quoted 14 lines

Otherwise, you're still basically testing

	qemu_isdigit(str[0]) || str[0] == '.'

Paolo

Quoted 6 lines
util/qemu-sockets.c +2 -0
+            addr->ipv4 = addr->has_ipv4 = true;
+        }
     }
 
     addr->host = g_strdup(host);
author
#4 lore raw

PATCH 2/2 nbd: strip braces from literal IPv6 address in URI

In reply to Ján Tomko

Otherwise they would get passed to getaddrinfo and fail with:
address resolution failed for [::1]:1234: Name or service not known

(Broken by commit v1.4.0-736-gf17c90b)

---
 block/nbd.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
block/nbd.c +10 -1
index 30e3b78..9c480b8 100644
@@ -118,13 +118,22 @@ static int nbd_parse_uri(const char *filename, QDict *options)
         }
         qdict_put(options, "path", qstring_from_str(qp->p[0].value));
     } else {
+        QString *host;
         /* nbd[+tcp]://host[:port]/export */
         if (!uri->server) {
             ret = -EINVAL;
             goto out;
         }
 
-        qdict_put(options, "host", qstring_from_str(uri->server));
+        /* strip braces from literal IPv6 address */
+        if (uri->server[0] == '[') {
+            host = qstring_from_substr(uri->server, 1,
+                                       strlen(uri->server) - 2);
+        } else {
+            host = qstring_from_str(uri->server);
+        }
+
+        qdict_put(options, "host", host);
         if (uri->port) {
             char* port_str = g_strdup_printf("%d", uri->port);
             qdict_put(options, "port", qstring_from_str(port_str));
Signature · 1 line
1.8.1.5
#5 lore raw

Re: [Qemu-devel] [PATCH 2/2] nbd: strip braces from literal IPv6 address in URI

Il 03/06/2013 17:54, Ján Tomko ha scritto:

Quoted 2 lines

Otherwise they would get passed to getaddrinfo and fail with:
address resolution failed for [::1]:1234: Name or service not known

Hmm... Hai Huang found a similar problem:

error: internal error unable to execute QEMU command 'nbd-server-start':
address resolution failed for [::]:5900: Name or service not known

This one is a libvirt bug, but perhaps it's simpler to just have a wrapper for getaddrinfo that strips brackets (and not strip the brackets in inet_parse, too).

Paolo

Quoted 36 lines

(Broken by commit v1.4.0-736-gf17c90b)

---
 block/nbd.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
block/nbd.c +10 -1
index 30e3b78..9c480b8 100644
@@ -118,13 +118,22 @@ static int nbd_parse_uri(const char *filename, QDict *options)
         }
         qdict_put(options, "path", qstring_from_str(qp->p[0].value));
     } else {
+        QString *host;
         /* nbd[+tcp]://host[:port]/export */
         if (!uri->server) {
             ret = -EINVAL;
             goto out;
         }
 
-        qdict_put(options, "host", qstring_from_str(uri->server));
+        /* strip braces from literal IPv6 address */
+        if (uri->server[0] == '[') {
+            host = qstring_from_substr(uri->server, 1,
+                                       strlen(uri->server) - 2);
+        } else {
+            host = qstring_from_str(uri->server);
+        }
+
+        qdict_put(options, "host", host);
         if (uri->port) {
             char* port_str = g_strdup_printf("%d", uri->port);
             qdict_put(options, "port", qstring_from_str(port_str));
author
#6 lore raw

Re: [Qemu-devel] [PATCH 2/2] nbd: strip braces from literal IPv6 address in URI

Quoted 9 lines · Paolo Bonzini

Il 03/06/2013 17:54, Ján Tomko ha scritto:

Quoted 2 lines

Otherwise they would get passed to getaddrinfo and fail with:
address resolution failed for [::1]:1234: Name or service not known

Hmm... Hai Huang found a similar problem:

error: internal error unable to execute QEMU command 'nbd-server-start':
address resolution failed for [::]:5900: Name or service not known

That one should be fixed in libvirt-1.0.5.2 and libvirt-1.0.6 now. [1]

Quoted 3 lines

This one is a libvirt bug, but perhaps it's simpler to just have a wrapper for getaddrinfo that strips brackets (and not strip the brackets in inet_parse, too).

I'm not sure if there are places other than calling getaddrinfo where having brackets would be bad, I'm not that familiar with QEMU code.

I've thought about stripping the brackets in uri_parse too, as we do in libvirt when parsing URIs. This wouldn't fix the case of someone specifying a bracket-ecaped hostname where there is no need for escaping it, like the libvirt bug.

And my patch is incomplete, because there are other block drivers calling uri_parse without stripping the brackets.

Jan

[1] http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=3accd7eb

#7 lore raw
In reply to Ján Tomko

Il 03/06/2013 17:54, Ján Tomko ha scritto:

Quoted 5 lines

Fix parsing of NBD URIs with IPv6 addresses, broken by v1.4.0-736-gf17c90b and fix parsing of NBD filenames with hostnames starting with a digit (fixed by the same commit, but only for NBD URIs):
https://lists.gnu.org/archive/html/qemu-devel/2013-05/msg04719.html

Quoted 8 lines

Ján Tomko (2):
qemu-socket: allow hostnames starting with a digit
nbd: strip braces from literal IPv6 address in URI

 block/nbd.c         | 11 ++++++++++-
 util/qemu-sockets.c | 13 ++++---------
 2 files changed, 14 insertions(+), 10 deletions(-)

Thanks, applied both to nbd-next tree.

Paolo