qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server
@ 2017-01-05 16:06 Daniel P. Berrange
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

This series is dependant on the IO series just posted to support
DNS resolution separately from socket creation.

There are two core feature changes in this series

 - If a DNS name resolves to multiple distinct IP addresses,
   the VNC server is now able to listen on all of them

 - The -vnc argument syntax is extended to allow the 'vnc'
   and 'websocket' arguments to be listed multiple times.
   This allows a single VNC server to listen on multiple
   different names / addresses.

Daniel P. Berrange (8):
  ui: fix regression handling bare 'websocket' option to -vnc
  ui: fix reporting of VNC auth in query-vnc-servers
  ui: refactor VncDisplay to allow multiple listening sockets
  ui: refactor code for populating SocketAddress from vnc_display_open
  ui: extract code to connect/listen from vnc_display_open
  ui: let VNC server listen on all resolved IP addresses
  util: add qemu_opt_get_all() to get repeated opts
  ui: add ability to specify multiple VNC listen addresses

 include/qemu/option.h |   1 +
 qapi-schema.json      |  26 +-
 qemu-options.hx       |  12 +-
 ui/vnc.c              | 653 +++++++++++++++++++++++++++++++++++---------------
 ui/vnc.h              |  10 +-
 util/qemu-option.c    |  22 ++
 6 files changed, 523 insertions(+), 201 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 13:39   ` Eric Blake
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

The -vnc argument is documented as accepting two syntaxes for
the 'websocket' option, either a bare option name, or a port
number. If using the bare option name, it is supposed to apply
the display number as an offset to base port 5700. e.g.

  -vnc localhost:3,websocket

should listen on port 5703, however, this was broken in 2.3.0 since

  commit 4db14629c38611061fc19ec6927405923de84f08
  Author: Gerd Hoffmann <kraxel@redhat.com>
  Date:   Tue Sep 16 12:33:03 2014 +0200

    vnc: switch to QemuOpts, allow multiple servers

instead qemu tries to listen on port "on" which gets looked up in
/etc/services and fails.

Fixes bug: #1455912

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 ui/vnc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 2c28a59..5039bd4 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3582,7 +3582,13 @@ void vnc_display_open(const char *id, Error **errp)
                 wsaddr->type = SOCKET_ADDRESS_KIND_INET;
                 inet = wsaddr->u.inet.data = g_new0(InetSocketAddress, 1);
                 inet->host = g_strdup(saddr->u.inet.data->host);
-                inet->port = g_strdup(websocket);
+                if (g_str_equal(websocket, "") ||
+                    g_str_equal(websocket, "on")) {
+                    inet->port = g_strdup_printf(
+                        "%d", (int)baseport + 5700);
+                } else {
+                    inet->port = g_strdup(websocket);
+                }
 
                 if (to) {
                     inet->has_to = true;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 15:06   ` Eric Blake
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets Daniel P. Berrange
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

Currently the VNC authentication info is emitted at the
top level of the query-vnc-servers data. This is wrong
because the authentication scheme differs between plain
and websockets when TLS is enabled. We should instead
report auth against the individual servers. e.g.

(QEMU) query-vnc-servers
{
    "return": [
        {
            "clients": [],
            "id": "default",
            "auth": "vencrypt",
            "vencrypt": "x509-vnc",
            "server": [
                {
                    "host": "127.0.0.1"
                    "service": "5901",
                    "websocket": false,
                    "family": "ipv4",
                    "auth": "vencrypt",
                    "vencrypt": "x509-vnc",
                }
                {
                    "host": "127.0.0.1",
                    "service": "5902",
                    "websocket": true,
                    "family": "ipv4",
                    "auth": "vnc"
                },
            ]
        }
    ]
}

This also future proofs the QMP schema so that we can
cope with multiple VNC server instances, listening on
different interfaces or ports, with different auth
setup.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 qapi-schema.json | 26 +++++++++++++++--
 ui/vnc.c         | 85 +++++++++++++++++++++++++++++++++-----------------------
 2 files changed, 73 insertions(+), 38 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index d605c1e..e3055e3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1104,7 +1104,8 @@
 #
 # The network connection information for server
 #
-# @auth: #optional, authentication method
+# @auth: #optional, authentication method used for
+#        the plain (non-websocket) VNC server
 #
 # Since: 2.1
 ##
@@ -1195,6 +1196,25 @@
             'tls-plain', 'x509-plain',
             'tls-sasl',  'x509-sasl' ] }
 
+
+##
+# @VncServerInfo2
+#
+# The network connection information for server
+#
+# @auth: The current authentication type used by the server
+#
+# @vencrypt: #optional The vencrypt sub authentication type used by the server,
+#            only specified in case auth == vencrypt.
+#
+# Since: 2.8
+##
+{ 'struct': 'VncServerInfo2',
+  'base': 'VncBasicInfo',
+  'data': { 'auth'      : 'VncPrimaryAuth',
+            '*vencrypt' : 'VncVencryptSubAuth' } }
+
+
 ##
 # @VncInfo2:
 #
@@ -1210,7 +1230,7 @@
 # @clients: A list of @VncClientInfo of all currently connected clients.
 #           The list can be empty, for obvious reasons.
 #
-# @auth: The current authentication type used by the server
+# @auth: The current authentication type used by the non-websockets server
 #
 # @vencrypt: #optional The vencrypt sub authentication type used by the server,
 #            only specified in case auth == vencrypt.
@@ -1221,7 +1241,7 @@
 ##
 { 'struct': 'VncInfo2',
   'data': { 'id'        : 'str',
-            'server'    : ['VncBasicInfo'],
+            'server'    : ['VncServerInfo2'],
             'clients'   : ['VncClientInfo'],
             'auth'      : 'VncPrimaryAuth',
             '*vencrypt' : 'VncVencryptSubAuth',
diff --git a/ui/vnc.c b/ui/vnc.c
index 5039bd4..28ee3e3 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -429,12 +429,20 @@ out_error:
     return NULL;
 }
 
-static VncBasicInfoList *qmp_query_server_entry(QIOChannelSocket *ioc,
-                                                bool websocket,
-                                                VncBasicInfoList *prev)
+
+static void qmp_query_auth(int auth, int subauth,
+                           VncPrimaryAuth *qmp_auth,
+                           VncVencryptSubAuth *qmp_vencrypt,
+                           bool *qmp_has_vencrypt);
+
+static VncServerInfo2List *qmp_query_server_entry(QIOChannelSocket *ioc,
+                                                  bool websocket,
+                                                  int auth,
+                                                  int subauth,
+                                                  VncServerInfo2List *prev)
 {
-    VncBasicInfoList *list;
-    VncBasicInfo *info;
+    VncServerInfo2List *list;
+    VncServerInfo2 *info;
     Error *err = NULL;
     SocketAddress *addr;
 
@@ -444,85 +452,91 @@ static VncBasicInfoList *qmp_query_server_entry(QIOChannelSocket *ioc,
         return prev;
     }
 
-    info = g_new0(VncBasicInfo, 1);
-    vnc_init_basic_info(addr, info, &err);
+    info = g_new0(VncServerInfo2, 1);
+    vnc_init_basic_info(addr, qapi_VncServerInfo2_base(info), &err);
     qapi_free_SocketAddress(addr);
     if (err) {
-        qapi_free_VncBasicInfo(info);
+        qapi_free_VncServerInfo2(info);
         error_free(err);
         return prev;
     }
     info->websocket = websocket;
 
-    list = g_new0(VncBasicInfoList, 1);
+    qmp_query_auth(auth, subauth, &info->auth,
+                   &info->vencrypt, &info->has_vencrypt);
+
+    list = g_new0(VncServerInfo2List, 1);
     list->value = info;
     list->next = prev;
     return list;
 }
 
-static void qmp_query_auth(VncDisplay *vd, VncInfo2 *info)
+static void qmp_query_auth(int auth, int subauth,
+                           VncPrimaryAuth *qmp_auth,
+                           VncVencryptSubAuth *qmp_vencrypt,
+                           bool *qmp_has_vencrypt)
 {
-    switch (vd->auth) {
+    switch (auth) {
     case VNC_AUTH_VNC:
-        info->auth = VNC_PRIMARY_AUTH_VNC;
+        *qmp_auth = VNC_PRIMARY_AUTH_VNC;
         break;
     case VNC_AUTH_RA2:
-        info->auth = VNC_PRIMARY_AUTH_RA2;
+        *qmp_auth = VNC_PRIMARY_AUTH_RA2;
         break;
     case VNC_AUTH_RA2NE:
-        info->auth = VNC_PRIMARY_AUTH_RA2NE;
+        *qmp_auth = VNC_PRIMARY_AUTH_RA2NE;
         break;
     case VNC_AUTH_TIGHT:
-        info->auth = VNC_PRIMARY_AUTH_TIGHT;
+        *qmp_auth = VNC_PRIMARY_AUTH_TIGHT;
         break;
     case VNC_AUTH_ULTRA:
-        info->auth = VNC_PRIMARY_AUTH_ULTRA;
+        *qmp_auth = VNC_PRIMARY_AUTH_ULTRA;
         break;
     case VNC_AUTH_TLS:
-        info->auth = VNC_PRIMARY_AUTH_TLS;
+        *qmp_auth = VNC_PRIMARY_AUTH_TLS;
         break;
     case VNC_AUTH_VENCRYPT:
-        info->auth = VNC_PRIMARY_AUTH_VENCRYPT;
-        info->has_vencrypt = true;
-        switch (vd->subauth) {
+        *qmp_auth = VNC_PRIMARY_AUTH_VENCRYPT;
+        *qmp_has_vencrypt = true;
+        switch (subauth) {
         case VNC_AUTH_VENCRYPT_PLAIN:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN;
             break;
         case VNC_AUTH_VENCRYPT_TLSNONE:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE;
             break;
         case VNC_AUTH_VENCRYPT_TLSVNC:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC;
             break;
         case VNC_AUTH_VENCRYPT_TLSPLAIN:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN;
             break;
         case VNC_AUTH_VENCRYPT_X509NONE:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE;
             break;
         case VNC_AUTH_VENCRYPT_X509VNC:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC;
             break;
         case VNC_AUTH_VENCRYPT_X509PLAIN:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN;
             break;
         case VNC_AUTH_VENCRYPT_TLSSASL:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL;
             break;
         case VNC_AUTH_VENCRYPT_X509SASL:
-            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL;
+            *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL;
             break;
         default:
-            info->has_vencrypt = false;
+            *qmp_has_vencrypt = false;
             break;
         }
         break;
     case VNC_AUTH_SASL:
-        info->auth = VNC_PRIMARY_AUTH_SASL;
+        *qmp_auth = VNC_PRIMARY_AUTH_SASL;
         break;
     case VNC_AUTH_NONE:
     default:
-        info->auth = VNC_PRIMARY_AUTH_NONE;
+        *qmp_auth = VNC_PRIMARY_AUTH_NONE;
         break;
     }
 }
@@ -538,7 +552,8 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
         info = g_new0(VncInfo2, 1);
         info->id = g_strdup(vd->id);
         info->clients = qmp_query_client_list(vd);
-        qmp_query_auth(vd, info);
+        qmp_query_auth(vd->auth, vd->subauth, &info->auth,
+                       &info->vencrypt, &info->has_vencrypt);
         if (vd->dcl.con) {
             dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con),
                                                   "device", NULL));
@@ -547,11 +562,11 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
         }
         if (vd->lsock != NULL) {
             info->server = qmp_query_server_entry(
-                vd->lsock, false, info->server);
+                vd->lsock, false, vd->auth, vd->subauth, info->server);
         }
         if (vd->lwebsock != NULL) {
             info->server = qmp_query_server_entry(
-                vd->lwebsock, true, info->server);
+                vd->lwebsock, true, vd->ws_auth, vd->ws_subauth, info->server);
         }
 
         item = g_new0(VncInfo2List, 1);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 15:23   ` Eric Blake
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

Currently there is only a single listener for plain VNC and
a single listener for websockets VNC. This means that is
getaddrinfo() returns multiple IP addresses, for a hostname,
the VNC server can only listen on one of them. This is
just bearable if listening on wildcard interface, or if
the host only has a single network interface to listen on,
but if there are multiple NICs and the VNC server needs
to listen on 2 or more specific IP addresses, it can't be
done.

This refactors the VncDisplay state so that it holds an
array of listening sockets, but still only listens on
one socket.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 ui/vnc.c | 103 +++++++++++++++++++++++++++++++++++++++++----------------------
 ui/vnc.h |  10 ++++---
 2 files changed, 73 insertions(+), 40 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 28ee3e3..b37aab4 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -224,8 +224,12 @@ static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
     VncServerInfo *info;
     Error *err = NULL;
 
+    if (!vd->nlsock) {
+        return NULL;
+    }
+
     info = g_malloc0(sizeof(*info));
-    vnc_init_basic_info_from_server_addr(vd->lsock,
+    vnc_init_basic_info_from_server_addr(vd->lsock[0],
                                          qapi_VncServerInfo_base(info), &err);
     info->has_auth = true;
     info->auth = g_strdup(vnc_auth_name(vd));
@@ -371,7 +375,7 @@ VncInfo *qmp_query_vnc(Error **errp)
     VncDisplay *vd = vnc_display_find(NULL);
     SocketAddress *addr = NULL;
 
-    if (vd == NULL || !vd->lsock) {
+    if (vd == NULL || !vd->nlsock) {
         info->enabled = false;
     } else {
         info->enabled = true;
@@ -384,7 +388,7 @@ VncInfo *qmp_query_vnc(Error **errp)
             return info;
         }
 
-        addr = qio_channel_socket_get_local_address(vd->lsock, errp);
+        addr = qio_channel_socket_get_local_address(vd->lsock[0], errp);
         if (!addr) {
             goto out_error;
         }
@@ -547,6 +551,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
     VncInfo2 *info;
     VncDisplay *vd;
     DeviceState *dev;
+    size_t i;
 
     QTAILQ_FOREACH(vd, &vnc_displays, next) {
         info = g_new0(VncInfo2, 1);
@@ -560,13 +565,14 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
             info->has_display = true;
             info->display = g_strdup(dev->id);
         }
-        if (vd->lsock != NULL) {
+        for (i = 0; i < vd->nlsock; i++) {
             info->server = qmp_query_server_entry(
-                vd->lsock, false, vd->auth, vd->subauth, info->server);
+                vd->lsock[i], false, vd->auth, vd->subauth, info->server);
         }
-        if (vd->lwebsock != NULL) {
+        for (i = 0; i < vd->nlwebsock; i++) {
             info->server = qmp_query_server_entry(
-                vd->lwebsock, true, vd->ws_auth, vd->ws_subauth, info->server);
+                vd->lwebsock[i], true, vd->ws_auth,
+                vd->ws_subauth, info->server);
         }
 
         item = g_new0(VncInfo2List, 1);
@@ -3112,15 +3118,22 @@ static gboolean vnc_listen_io(QIOChannel *ioc,
     VncDisplay *vd = opaque;
     QIOChannelSocket *sioc = NULL;
     Error *err = NULL;
+    bool isWebsock = false;
+    size_t i;
+
+    for (i = 0; i < vd->nlwebsock; i++) {
+        if (ioc == QIO_CHANNEL(vd->lwebsock[i])) {
+            isWebsock = true;
+            break;
+        }
+    }
 
     sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), &err);
     if (sioc != NULL) {
         qio_channel_set_name(QIO_CHANNEL(sioc),
-                             ioc != QIO_CHANNEL(vd->lsock) ?
-                             "vnc-ws-server" : "vnc-server");
+                             isWebsock ? "vnc-ws-server" : "vnc-server");
         qio_channel_set_delay(QIO_CHANNEL(sioc), false);
-        vnc_connect(vd, sioc, false,
-                    ioc != QIO_CHANNEL(vd->lsock));
+        vnc_connect(vd, sioc, false, isWebsock);
         object_unref(OBJECT(sioc));
     } else {
         /* client probably closed connection before we got there */
@@ -3180,24 +3193,33 @@ void vnc_display_init(const char *id)
 
 static void vnc_display_close(VncDisplay *vd)
 {
+    size_t i;
     if (!vd) {
         return;
     }
     vd->is_unix = false;
-    if (vd->lsock != NULL) {
-        if (vd->lsock_tag) {
-            g_source_remove(vd->lsock_tag);
+    for (i = 0; i < vd->nlsock; i++) {
+        if (vd->lsock_tag[i]) {
+            g_source_remove(vd->lsock_tag[i]);
         }
-        object_unref(OBJECT(vd->lsock));
-        vd->lsock = NULL;
+        object_unref(OBJECT(vd->lsock[i]));
     }
-    if (vd->lwebsock != NULL) {
-        if (vd->lwebsock_tag) {
-            g_source_remove(vd->lwebsock_tag);
+    g_free(vd->lsock);
+    g_free(vd->lsock_tag);
+    vd->lsock = NULL;
+    vd->nlsock = 0;
+
+    for (i = 0; i < vd->nlwebsock; i++) {
+        if (vd->lwebsock_tag[i]) {
+            g_source_remove(vd->lwebsock_tag[i]);
         }
-        object_unref(OBJECT(vd->lwebsock));
-        vd->lwebsock = NULL;
+        object_unref(OBJECT(vd->lwebsock[i]));
     }
+    g_free(vd->lwebsock);
+    g_free(vd->lwebsock_tag);
+    vd->lwebsock = NULL;
+    vd->nlwebsock = 0;
+
     vd->auth = VNC_AUTH_INVALID;
     vd->subauth = VNC_AUTH_INVALID;
     if (vd->tlscreds) {
@@ -3244,7 +3266,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
     SocketAddress *addr;
     Error *err = NULL;
 
-    addr = qio_channel_socket_get_local_address(vd->lsock, &err);
+    if (!vd->nlsock) {
+        return;
+    }
+
+    addr = qio_channel_socket_get_local_address(vd->lsock[0], &err);
     if (!addr) {
         return;
     }
@@ -3804,8 +3830,6 @@ void vnc_display_open(const char *id, Error **errp)
     if (reverse) {
         /* connect to viewer */
         QIOChannelSocket *sioc = NULL;
-        vd->lsock = NULL;
-        vd->lwebsock = NULL;
         if (ws_enabled) {
             error_setg(errp, "Cannot use websockets in reverse mode");
             goto fail;
@@ -3819,30 +3843,36 @@ void vnc_display_open(const char *id, Error **errp)
         vnc_connect(vd, sioc, false, false);
         object_unref(OBJECT(sioc));
     } else {
-        vd->lsock = qio_channel_socket_new();
-        qio_channel_set_name(QIO_CHANNEL(vd->lsock), "vnc-listen");
-        if (qio_channel_socket_listen_sync(vd->lsock, saddr, errp) < 0) {
+        vd->nlsock = 1;
+        vd->lsock = g_new0(QIOChannelSocket *, 1);
+        vd->lsock_tag = g_new0(guint, 1);
+
+        vd->lsock[0] = qio_channel_socket_new();
+        qio_channel_set_name(QIO_CHANNEL(vd->lsock[0]), "vnc-listen");
+        if (qio_channel_socket_listen_sync(vd->lsock[0], saddr, errp) < 0) {
             goto fail;
         }
         vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
 
         if (ws_enabled) {
-            vd->lwebsock = qio_channel_socket_new();
-            qio_channel_set_name(QIO_CHANNEL(vd->lwebsock), "vnc-ws-listen");
-            if (qio_channel_socket_listen_sync(vd->lwebsock,
+            vd->nlwebsock = 1;
+            vd->lwebsock = g_new0(QIOChannelSocket *, 1);
+            vd->lwebsock_tag = g_new0(guint, 1);
+
+            vd->lwebsock[0] = qio_channel_socket_new();
+            qio_channel_set_name(QIO_CHANNEL(vd->lwebsock[0]), "vnc-ws-listen");
+            if (qio_channel_socket_listen_sync(vd->lwebsock[0],
                                                wsaddr, errp) < 0) {
-                object_unref(OBJECT(vd->lsock));
-                vd->lsock = NULL;
                 goto fail;
             }
         }
 
-        vd->lsock_tag = qio_channel_add_watch(
-            QIO_CHANNEL(vd->lsock),
+        vd->lsock_tag[0] = qio_channel_add_watch(
+            QIO_CHANNEL(vd->lsock[0]),
             G_IO_IN, vnc_listen_io, vd, NULL);
         if (ws_enabled) {
-            vd->lwebsock_tag = qio_channel_add_watch(
-                QIO_CHANNEL(vd->lwebsock),
+            vd->lwebsock_tag[0] = qio_channel_add_watch(
+                QIO_CHANNEL(vd->lwebsock[0]),
                 G_IO_IN, vnc_listen_io, vd, NULL);
         }
     }
@@ -3856,6 +3886,7 @@ void vnc_display_open(const char *id, Error **errp)
     return;
 
 fail:
+    vnc_display_close(vd);
     qapi_free_SocketAddress(saddr);
     qapi_free_SocketAddress(wsaddr);
     ws_enabled = false;
diff --git a/ui/vnc.h b/ui/vnc.h
index d20b154..453695a 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -146,10 +146,12 @@ struct VncDisplay
     int num_exclusive;
     int connections_limit;
     VncSharePolicy share_policy;
-    QIOChannelSocket *lsock;
-    guint lsock_tag;
-    QIOChannelSocket *lwebsock;
-    guint lwebsock_tag;
+    size_t nlsock;
+    QIOChannelSocket **lsock;
+    guint *lsock_tag;
+    size_t nlwebsock;
+    QIOChannelSocket **lwebsock;
+    guint *lwebsock_tag;
     DisplaySurface *ds;
     DisplayChangeListener dcl;
     kbd_layout_t *kbd_layout;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (2 preceding siblings ...)
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 15:47   ` Eric Blake
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen " Daniel P. Berrange
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

The code which interprets the CLI args to populate the SocketAddress
objects for plain & websockets VNC is quite complex already and will
need further enhancements shortly. Refactor it into separate methods
to avoid vnc_display_open getting even larger. As a side effect of
the refactoring, it is now possible to specify a listen address for
the websocket server explicitly. e.g,

  -vnc localhost:5900,websockets=0.0.0.0:8080

will listen on localhost for the plain VNC server, but expose the
websockets VNC server on the public interface. This refactoring
also removes the restriction that prevents enabling websockets
when the plain VNC server is listening on a UNIX socket.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 qemu-options.hx |  12 ++-
 ui/vnc.c        | 282 ++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 189 insertions(+), 105 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index c534a2f..7470def 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1297,10 +1297,14 @@ is a TCP port number, not a display number.
 @item websocket
 
 Opens an additional TCP listening port dedicated to VNC Websocket connections.
-By definition the Websocket port is 5700+@var{display}. If @var{host} is
-specified connections will only be allowed from this host.
-As an alternative the Websocket port could be specified by using
-@code{websocket}=@var{port}.
+If a bare @var{websocket} option is given, the Websocket port is
+5700+@var{display}. An alternative port can be specified with the
+syntax @code{websocket}=@var{port}.
+
+If @var{host} is specified connections will only be allowed from this host.
+It is possible to control the websocket listen address independantly using
+the syntax @code{websocket}=@var{host}:@var{port}.
+
 If no TLS credentials are provided, the websocket connection runs in
 unencrypted mode. If TLS credentials are provided, the websocket connection
 requires encrypted client connections.
diff --git a/ui/vnc.c b/ui/vnc.c
index b37aab4..8d3f9c1 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3519,6 +3519,178 @@ vnc_display_create_creds(bool x509,
 }
 
 
+static int vnc_display_get_address(const char *addrstr,
+                                   bool websocket,
+                                   int displaynum,
+                                   int to,
+                                   bool has_ipv4,
+                                   bool has_ipv6,
+                                   bool ipv4,
+                                   bool ipv6,
+                                   SocketAddress **retaddr,
+                                   Error **errp)
+{
+    int ret = -1;
+    SocketAddress *addr = NULL;
+
+    addr = g_new0(SocketAddress, 1);
+
+    if (strncmp(addrstr, "unix:", 5) == 0) {
+        addr->type = SOCKET_ADDRESS_KIND_UNIX;
+        addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+        addr->u.q_unix.data->path = g_strdup(addrstr + 5);
+
+        if (websocket) {
+            error_setg(errp, "UNIX sockets not supported with websock");
+            goto cleanup;
+        }
+
+        if (to) {
+            error_setg(errp, "Port range not support with UNIX socket");
+            goto cleanup;
+        }
+        ret = 0;
+    } else {
+        const char *port;
+        size_t hostlen;
+        unsigned long long baseport;
+        InetSocketAddress *inet;
+
+        port = strrchr(addrstr, ':');
+        if (!port) {
+            if (websocket) {
+                hostlen = 0;
+                port = addrstr;
+            } else {
+                error_setg(errp, "no vnc port specified");
+                goto cleanup;
+            }
+        } else {
+            hostlen = port - addrstr;
+            port++;
+            if (*port == '\0') {
+                error_setg(errp, "vnc port cannot be empty");
+                goto cleanup;
+            }
+        }
+
+        addr->type = SOCKET_ADDRESS_KIND_INET;
+        inet = addr->u.inet.data = g_new0(InetSocketAddress, 1);
+        if (addrstr[0] == '[' && addrstr[hostlen - 1] == ']') {
+            inet->host = g_strndup(addrstr + 1, hostlen - 2);
+        } else {
+            inet->host = g_strndup(addrstr, hostlen);
+        }
+        /* plain VNC port is just an offset, for websocket
+         * port is absolute */
+        if (websocket) {
+            if (g_str_equal(addrstr, "") ||
+                g_str_equal(addrstr, "on")) {
+                inet->port = g_strdup_printf(
+                    "%d", displaynum + 5700);
+                if (to) {
+                    inet->has_to = true;
+                    inet->to = to + 5700;
+                }
+            } else {
+                inet->port = g_strdup(port);
+            }
+        } else {
+            if (parse_uint_full(port, &baseport, 10) < 0) {
+                error_setg(errp, "can't convert to a number: %s", port);
+                goto cleanup;
+            }
+            if (baseport > 65535 ||
+                baseport + 5900 > 65535) {
+                error_setg(errp, "port %s out of range", port);
+                goto cleanup;
+            }
+            inet->port = g_strdup_printf(
+                "%d", (int)baseport + 5900);
+
+            if (to) {
+                inet->has_to = true;
+                inet->to = to + 5900;
+            }
+        }
+
+        inet->ipv4 = ipv4;
+        inet->has_ipv4 = has_ipv4;
+        inet->ipv6 = ipv6;
+        inet->has_ipv6 = has_ipv6;
+
+        ret = baseport;
+    }
+
+    *retaddr = addr;
+
+ cleanup:
+    if (ret < 0) {
+        qapi_free_SocketAddress(addr);
+    }
+    return ret;
+}
+
+static int vnc_display_get_addresses(QemuOpts *opts,
+                                     SocketAddress **retsaddr,
+                                     SocketAddress **retwsaddr,
+                                     Error **errp)
+{
+    SocketAddress *saddr = NULL;
+    SocketAddress *wsaddr = NULL;
+    const char *saddrstr = qemu_opt_get(opts, "vnc");
+    const char *wsaddrstr = qemu_opt_get(opts, "websocket");
+    int to = qemu_opt_get_number(opts, "to", 0);
+    bool has_ipv4 = qemu_opt_get(opts, "ipv4");
+    bool has_ipv6 = qemu_opt_get(opts, "ipv6");
+    bool ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
+    bool ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
+
+    if (!saddrstr || strcmp(saddrstr, "none") == 0) {
+        *retsaddr = NULL;
+        *retwsaddr = NULL;
+        return 0;
+    }
+
+    if (wsaddrstr &&
+        !qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
+        error_setg(errp,
+                   "SHA1 hash support is required for websockets");
+        goto error;
+    }
+
+    int displaynum = vnc_display_get_address(saddrstr, false, 0, to,
+                                             has_ipv4, has_ipv6,
+                                             ipv4, ipv6,
+                                             &saddr, errp);
+    if (displaynum < 0) {
+        goto error;
+    }
+    if (wsaddrstr) {
+        if (vnc_display_get_address(wsaddrstr, true, displaynum, to,
+                                    has_ipv4, has_ipv6,
+                                    ipv4, ipv6,
+                                    &wsaddr, errp) < 0) {
+            goto error;
+        }
+        if (saddr->type == SOCKET_ADDRESS_KIND_INET &&
+            wsaddr->type == SOCKET_ADDRESS_KIND_INET &&
+            g_str_equal(wsaddr->u.inet.data->host, "") &&
+            !g_str_equal(saddr->u.inet.data->host, "")) {
+            g_free(wsaddr->u.inet.data->host);
+            wsaddr->u.inet.data->host = g_strdup(saddr->u.inet.data->host);
+        }
+    }
+    *retsaddr = saddr;
+    *retwsaddr = wsaddr;
+    return 0;
+
+ error:
+    qapi_free_SocketAddress(saddr);
+    qapi_free_SocketAddress(wsaddr);
+    return -1;
+}
+
 void vnc_display_open(const char *id, Error **errp)
 {
     VncDisplay *vd = vnc_display_find(id);
@@ -3528,10 +3700,7 @@ void vnc_display_open(const char *id, Error **errp)
     QemuConsole *con;
     bool password = false;
     bool reverse = false;
-    const char *vnc;
-    char *h;
     const char *credid;
-    int show_vnc_port = 0;
     bool sasl = false;
 #ifdef CONFIG_VNC_SASL
     int saslErr;
@@ -3539,7 +3708,6 @@ void vnc_display_open(const char *id, Error **errp)
     int acl = 0;
     int lock_key_sync = 1;
     int key_delay_ms;
-    bool ws_enabled = false;
 
     if (!vd) {
         error_setg(errp, "VNC display not active");
@@ -3550,102 +3718,15 @@ void vnc_display_open(const char *id, Error **errp)
     if (!opts) {
         return;
     }
-    vnc = qemu_opt_get(opts, "vnc");
-    if (!vnc || strcmp(vnc, "none") == 0) {
-        return;
-    }
-
-    h = strrchr(vnc, ':');
-    if (h) {
-        size_t hlen = h - vnc;
 
-        const char *websocket = qemu_opt_get(opts, "websocket");
-        int to = qemu_opt_get_number(opts, "to", 0);
-        bool has_ipv4 = qemu_opt_get(opts, "ipv4");
-        bool has_ipv6 = qemu_opt_get(opts, "ipv6");
-        bool ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
-        bool ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
-
-        saddr = g_new0(SocketAddress, 1);
-        if (websocket) {
-            if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
-                error_setg(errp,
-                           "SHA1 hash support is required for websockets");
-                goto fail;
-            }
-
-            wsaddr = g_new0(SocketAddress, 1);
-            ws_enabled = true;
-        }
-
-        if (strncmp(vnc, "unix:", 5) == 0) {
-            saddr->type = SOCKET_ADDRESS_KIND_UNIX;
-            saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
-            saddr->u.q_unix.data->path = g_strdup(vnc + 5);
-
-            if (ws_enabled) {
-                error_setg(errp, "UNIX sockets not supported with websock");
-                goto fail;
-            }
-        } else {
-            unsigned long long baseport;
-            InetSocketAddress *inet;
-            saddr->type = SOCKET_ADDRESS_KIND_INET;
-            inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
-            if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
-                inet->host = g_strndup(vnc + 1, hlen - 2);
-            } else {
-                inet->host = g_strndup(vnc, hlen);
-            }
-            if (parse_uint_full(h + 1, &baseport, 10) < 0) {
-                error_setg(errp, "can't convert to a number: %s", h + 1);
-                goto fail;
-            }
-            if (baseport > 65535 ||
-                baseport + 5900 > 65535) {
-                error_setg(errp, "port %s out of range", h + 1);
-                goto fail;
-            }
-            inet->port = g_strdup_printf(
-                "%d", (int)baseport + 5900);
-
-            if (to) {
-                inet->has_to = true;
-                inet->to = to + 5900;
-                show_vnc_port = 1;
-            }
-            inet->ipv4 = ipv4;
-            inet->has_ipv4 = has_ipv4;
-            inet->ipv6 = ipv6;
-            inet->has_ipv6 = has_ipv6;
-
-            if (ws_enabled) {
-                wsaddr->type = SOCKET_ADDRESS_KIND_INET;
-                inet = wsaddr->u.inet.data = g_new0(InetSocketAddress, 1);
-                inet->host = g_strdup(saddr->u.inet.data->host);
-                if (g_str_equal(websocket, "") ||
-                    g_str_equal(websocket, "on")) {
-                    inet->port = g_strdup_printf(
-                        "%d", (int)baseport + 5700);
-                } else {
-                    inet->port = g_strdup(websocket);
-                }
-
-                if (to) {
-                    inet->has_to = true;
-                    inet->to = to;
-                }
-                inet->ipv4 = ipv4;
-                inet->has_ipv4 = has_ipv4;
-                inet->ipv6 = ipv6;
-                inet->has_ipv6 = has_ipv6;
-            }
-        }
-    } else {
-        error_setg(errp, "no vnc port specified");
+    if (vnc_display_get_addresses(opts, &saddr, &wsaddr, errp) < 0) {
         goto fail;
     }
 
+    if (saddr == NULL) {
+        return;
+    }
+
     password = qemu_opt_get_bool(opts, "password", false);
     if (password) {
         if (fips_get_state()) {
@@ -3830,7 +3911,7 @@ void vnc_display_open(const char *id, Error **errp)
     if (reverse) {
         /* connect to viewer */
         QIOChannelSocket *sioc = NULL;
-        if (ws_enabled) {
+        if (wsaddr) {
             error_setg(errp, "Cannot use websockets in reverse mode");
             goto fail;
         }
@@ -3854,7 +3935,7 @@ void vnc_display_open(const char *id, Error **errp)
         }
         vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
 
-        if (ws_enabled) {
+        if (wsaddr) {
             vd->nlwebsock = 1;
             vd->lwebsock = g_new0(QIOChannelSocket *, 1);
             vd->lwebsock_tag = g_new0(guint, 1);
@@ -3870,14 +3951,14 @@ void vnc_display_open(const char *id, Error **errp)
         vd->lsock_tag[0] = qio_channel_add_watch(
             QIO_CHANNEL(vd->lsock[0]),
             G_IO_IN, vnc_listen_io, vd, NULL);
-        if (ws_enabled) {
+        if (wsaddr) {
             vd->lwebsock_tag[0] = qio_channel_add_watch(
                 QIO_CHANNEL(vd->lwebsock[0]),
                 G_IO_IN, vnc_listen_io, vd, NULL);
         }
     }
 
-    if (show_vnc_port) {
+    if (qemu_opt_get(opts, "to")) {
         vnc_display_print_local_addr(vd);
     }
 
@@ -3889,7 +3970,6 @@ fail:
     vnc_display_close(vd);
     qapi_free_SocketAddress(saddr);
     qapi_free_SocketAddress(wsaddr);
-    ws_enabled = false;
 }
 
 void vnc_display_add_client(const char *id, int csock, bool skipauth)
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen from vnc_display_open
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (3 preceding siblings ...)
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 16:00   ` Eric Blake
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

The code which takes a SocketAddress and connects/listens on the
network is going to get more complicated to deal with multiple
listeners. Pull it out into a separate method to avoid making the
vnc_display_open method even more complex.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 ui/vnc.c | 122 +++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 80 insertions(+), 42 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 8d3f9c1..94135c8 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3691,6 +3691,84 @@ static int vnc_display_get_addresses(QemuOpts *opts,
     return -1;
 }
 
+static int vnc_display_connect(VncDisplay *vd,
+                               SocketAddress *saddr,
+                               SocketAddress *wsaddr,
+                               Error **errp)
+{
+    /* connect to viewer */
+    QIOChannelSocket *sioc = NULL;
+    if (wsaddr) {
+        error_setg(errp, "Cannot use websockets in reverse mode");
+        return -1;
+    }
+    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
+    sioc = qio_channel_socket_new();
+    qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
+    if (qio_channel_socket_connect_sync(sioc, saddr, errp) < 0) {
+        return -1;
+    }
+    vnc_connect(vd, sioc, false, false);
+    object_unref(OBJECT(sioc));
+    return 0;
+}
+
+
+static int vnc_display_listen_addr(VncDisplay *vd,
+                                   SocketAddress *addr,
+                                   const char *name,
+                                   QIOChannelSocket ***lsock,
+                                   guint **lsock_tag,
+                                   size_t *nlsock,
+                                   Error **errp)
+{
+    *nlsock = 1;
+    *lsock = g_new0(QIOChannelSocket *, 1);
+    *lsock_tag = g_new0(guint, 1);
+
+    (*lsock)[0] = qio_channel_socket_new();
+    qio_channel_set_name(QIO_CHANNEL((*lsock)[0]), name);
+    if (qio_channel_socket_listen_sync((*lsock)[0], addr, errp) < 0) {
+        return -1;
+    }
+
+    (*lsock_tag)[0] = qio_channel_add_watch(
+        QIO_CHANNEL((*lsock)[0]),
+        G_IO_IN, vnc_listen_io, vd, NULL);
+
+    return 0;
+}
+
+
+static int vnc_display_listen(VncDisplay *vd,
+                              SocketAddress *saddr,
+                              SocketAddress *wsaddr,
+                              Error **errp)
+{
+    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
+
+    if (vnc_display_listen_addr(vd, saddr,
+                                "vnc-listen",
+                                &vd->lsock,
+                                &vd->lsock_tag,
+                                &vd->nlsock,
+                                errp) < 0) {
+        return -1;
+    }
+    if (wsaddr &&
+        vnc_display_listen_addr(vd, wsaddr,
+                                "vnc-ws-listen",
+                                &vd->lwebsock,
+                                &vd->lwebsock_tag,
+                                &vd->nlwebsock,
+                                errp) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+
 void vnc_display_open(const char *id, Error **errp)
 {
     VncDisplay *vd = vnc_display_find(id);
@@ -3909,53 +3987,13 @@ void vnc_display_open(const char *id, Error **errp)
     }
 
     if (reverse) {
-        /* connect to viewer */
-        QIOChannelSocket *sioc = NULL;
-        if (wsaddr) {
-            error_setg(errp, "Cannot use websockets in reverse mode");
-            goto fail;
-        }
-        vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
-        sioc = qio_channel_socket_new();
-        qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
-        if (qio_channel_socket_connect_sync(sioc, saddr, errp) < 0) {
+        if (vnc_display_connect(vd, saddr, wsaddr, errp) < 0) {
             goto fail;
         }
-        vnc_connect(vd, sioc, false, false);
-        object_unref(OBJECT(sioc));
     } else {
-        vd->nlsock = 1;
-        vd->lsock = g_new0(QIOChannelSocket *, 1);
-        vd->lsock_tag = g_new0(guint, 1);
-
-        vd->lsock[0] = qio_channel_socket_new();
-        qio_channel_set_name(QIO_CHANNEL(vd->lsock[0]), "vnc-listen");
-        if (qio_channel_socket_listen_sync(vd->lsock[0], saddr, errp) < 0) {
+        if (vnc_display_listen(vd, saddr, wsaddr, errp) < 0) {
             goto fail;
         }
-        vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
-
-        if (wsaddr) {
-            vd->nlwebsock = 1;
-            vd->lwebsock = g_new0(QIOChannelSocket *, 1);
-            vd->lwebsock_tag = g_new0(guint, 1);
-
-            vd->lwebsock[0] = qio_channel_socket_new();
-            qio_channel_set_name(QIO_CHANNEL(vd->lwebsock[0]), "vnc-ws-listen");
-            if (qio_channel_socket_listen_sync(vd->lwebsock[0],
-                                               wsaddr, errp) < 0) {
-                goto fail;
-            }
-        }
-
-        vd->lsock_tag[0] = qio_channel_add_watch(
-            QIO_CHANNEL(vd->lsock[0]),
-            G_IO_IN, vnc_listen_io, vd, NULL);
-        if (wsaddr) {
-            vd->lwebsock_tag[0] = qio_channel_add_watch(
-                QIO_CHANNEL(vd->lwebsock[0]),
-                G_IO_IN, vnc_listen_io, vd, NULL);
-        }
     }
 
     if (qemu_opt_get(opts, "to")) {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (4 preceding siblings ...)
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen " Daniel P. Berrange
@ 2017-01-05 16:06 ` Daniel P. Berrange
  2017-01-06 16:14   ` Eric Blake
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts Daniel P. Berrange
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

Remove the limitation that the VNC server can only listen on
a single resolved IP address. This uses the new DNS resolver
API to resolve a SocketAddress struct into an array of
SocketAddress structs containing raw IP addresses. The VNC
server will then attempt to listen on all resolve IP addresses.
An error will be returned if it was not possible to listen on
all of the IP addresses.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 ui/vnc.c | 52 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 94135c8..d21ede9 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -45,6 +45,7 @@
 #include "crypto/tlscredsx509.h"
 #include "qom/object_interfaces.h"
 #include "qemu/cutils.h"
+#include "io/dns-resolver.h"
 
 #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
 #define VNC_REFRESH_INTERVAL_INC  50
@@ -3722,19 +3723,52 @@ static int vnc_display_listen_addr(VncDisplay *vd,
                                    size_t *nlsock,
                                    Error **errp)
 {
-    *nlsock = 1;
-    *lsock = g_new0(QIOChannelSocket *, 1);
-    *lsock_tag = g_new0(guint, 1);
+    QIODNSResolver *resolver = qio_dns_resolver_get_instance();
+    SocketAddress **rawaddrs = NULL;
+    size_t nrawaddrs = 0;
+    Error *listenerr = NULL;
+    size_t i;
 
-    (*lsock)[0] = qio_channel_socket_new();
-    qio_channel_set_name(QIO_CHANNEL((*lsock)[0]), name);
-    if (qio_channel_socket_listen_sync((*lsock)[0], addr, errp) < 0) {
+    if (qio_dns_resolver_lookup_sync(resolver, addr, &nrawaddrs,
+                                     &rawaddrs, errp) < 0) {
         return -1;
     }
 
-    (*lsock_tag)[0] = qio_channel_add_watch(
-        QIO_CHANNEL((*lsock)[0]),
-        G_IO_IN, vnc_listen_io, vd, NULL);
+    for (i = 0; i < nrawaddrs; i++) {
+        QIOChannelSocket *sioc = qio_channel_socket_new();
+
+        qio_channel_set_name(QIO_CHANNEL(sioc), name);
+        if (qio_channel_socket_listen_sync(
+                sioc, rawaddrs[i], listenerr == NULL ? &listenerr : NULL) < 0) {
+            continue;
+        }
+        (*nlsock)++;
+        *lsock = g_renew(QIOChannelSocket *, *lsock, *nlsock);
+        *lsock_tag = g_renew(guint, *lsock_tag, *nlsock);
+
+        (*lsock)[*nlsock - 1] = sioc;
+        (*lsock_tag)[*nlsock - 1] = 0;
+    }
+
+    for (i = 0; i < nrawaddrs; i++) {
+        qapi_free_SocketAddress(rawaddrs[i]);
+    }
+    g_free(rawaddrs);
+
+    if (listenerr) {
+        if (*nlsock == 0) {
+            error_propagate(errp, listenerr);
+            return -1;
+        } else {
+            error_free(listenerr);
+        }
+    }
+
+    for (i = 0; i < *nlsock; i++) {
+        (*lsock_tag)[i] = qio_channel_add_watch(
+            QIO_CHANNEL((*lsock)[i]),
+            G_IO_IN, vnc_listen_io, vd, NULL);
+    }
 
     return 0;
 }
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (5 preceding siblings ...)
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
@ 2017-01-05 16:07 ` Daniel P. Berrange
  2017-01-06 16:22   ` Eric Blake
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
  2017-01-05 17:26 ` [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server no-reply
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

The QemuOpts parser accepts repeated option names, storing
all the provided values. qemu_opt_get() then just returns
the last value. There is no way to get the other values
without using a callback function to iterate over all
option names. Add a qemu_opt_get_all() method to return
a string list of all values.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 include/qemu/option.h |  1 +
 util/qemu-option.c    | 22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index 1f9e3f9..689e0a8 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -65,6 +65,7 @@ struct QemuOptsList {
 };
 
 const char *qemu_opt_get(QemuOpts *opts, const char *name);
+size_t qemu_opt_get_all(QemuOpts *opts, const char *name, char ***vals);
 char *qemu_opt_get_del(QemuOpts *opts, const char *name);
 /**
  * qemu_opt_has_help_opt:
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 3467dc2..0418d71 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -332,6 +332,28 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
     return opt ? opt->str : NULL;
 }
 
+size_t qemu_opt_get_all(QemuOpts *opts, const char *name, char ***vals)
+{
+    QemuOpt *opt;
+    size_t nvals = 0;
+
+    *vals = NULL;
+
+    QTAILQ_FOREACH(opt, &opts->head, next) {
+        if (!g_str_equal(opt->name, name)) {
+            continue;
+        }
+
+        *vals = g_renew(char *, *vals, nvals + 1);
+        (*vals)[nvals++] = g_strdup(opt->str);
+    }
+    if (nvals) {
+        *vals = g_renew(char *, *vals, nvals + 1);
+        (*vals)[nvals] = NULL;
+    }
+    return nvals;
+}
+
 /* Get a known option (or its default) and remove it from the list
  * all in one action. Return a malloced string of the option value.
  * Result must be freed by caller with g_free().
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (6 preceding siblings ...)
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts Daniel P. Berrange
@ 2017-01-05 16:07 ` Daniel P. Berrange
  2017-01-06 16:34   ` Eric Blake
  2017-01-05 17:26 ` [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server no-reply
  8 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-05 16:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Daniel P. Berrange

This change allows the listen address and websocket address
options for -vnc to be repeated. This causes the VNC server
to listen on multiple addresses. e.g.

 $ $QEMU -vnc vnc=localhost:1,vnc=unix:/tmp/vnc,\
              websocket=127.0.0.1:8080,websocket=[::]:8081

results in listening on

127.0.0.1:5901, 127.0.0.1:8080, ::1:5901, :::8081 & /tmp/vnc

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 ui/vnc.c | 191 +++++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 130 insertions(+), 61 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index d21ede9..1de9099 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3587,6 +3587,10 @@ static int vnc_display_get_address(const char *addrstr,
         if (websocket) {
             if (g_str_equal(addrstr, "") ||
                 g_str_equal(addrstr, "on")) {
+                if (displaynum == -1) {
+                    error_setg(errp, "explicit websocket port is required");
+                    goto cleanup;
+                }
                 inet->port = g_strdup_printf(
                     "%d", displaynum + 5700);
                 if (to) {
@@ -3633,80 +3637,130 @@ static int vnc_display_get_address(const char *addrstr,
 }
 
 static int vnc_display_get_addresses(QemuOpts *opts,
-                                     SocketAddress **retsaddr,
-                                     SocketAddress **retwsaddr,
+                                     SocketAddress ***retsaddr,
+                                     size_t *retnsaddr,
+                                     SocketAddress ***retwsaddr,
+                                     size_t *retnwsaddr,
                                      Error **errp)
 {
     SocketAddress *saddr = NULL;
     SocketAddress *wsaddr = NULL;
-    const char *saddrstr = qemu_opt_get(opts, "vnc");
-    const char *wsaddrstr = qemu_opt_get(opts, "websocket");
+    char **saddrstr, **wsaddrstr;
+    size_t nsaddrstr, nwsaddrstr;
     int to = qemu_opt_get_number(opts, "to", 0);
     bool has_ipv4 = qemu_opt_get(opts, "ipv4");
     bool has_ipv6 = qemu_opt_get(opts, "ipv6");
     bool ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
     bool ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
+    size_t i;
+    int displaynum = -1;
+    int ret = -1;
 
-    if (!saddrstr || strcmp(saddrstr, "none") == 0) {
-        *retsaddr = NULL;
-        *retwsaddr = NULL;
-        return 0;
+    nsaddrstr = qemu_opt_get_all(opts, "vnc", &saddrstr);
+    nwsaddrstr = qemu_opt_get_all(opts, "websocket", &wsaddrstr);
+
+    *retsaddr = NULL;
+    *retnsaddr = 0;
+    *retwsaddr = NULL;
+    *retnwsaddr = 0;
+
+    if (nsaddrstr == 0 || strcmp(saddrstr[0], "none") == 0) {
+        ret = 0;
+        goto cleanup;
     }
 
     if (wsaddrstr &&
         !qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
         error_setg(errp,
                    "SHA1 hash support is required for websockets");
-        goto error;
+        goto cleanup;
     }
 
-    int displaynum = vnc_display_get_address(saddrstr, false, 0, to,
-                                             has_ipv4, has_ipv6,
-                                             ipv4, ipv6,
-                                             &saddr, errp);
-    if (displaynum < 0) {
-        goto error;
+    for (i = 0; i < nsaddrstr; i++) {
+        int rv;
+        rv = vnc_display_get_address(saddrstr[i], false, 0, to,
+                                     has_ipv4, has_ipv6,
+                                     ipv4, ipv6,
+                                     &saddr, errp);
+        if (rv < 0) {
+            goto cleanup;
+        }
+        /* Historical compat - if only a single listen address was
+         * provided, then the display num can be used to set the
+         * default websocket port
+         */
+        if (nsaddrstr == 1) {
+            displaynum = rv;
+        }
+        *retsaddr = g_renew(SocketAddress *, *retsaddr, *retnsaddr + 1);
+        (*retsaddr)[(*retnsaddr)++] = saddr;
     }
-    if (wsaddrstr) {
-        if (vnc_display_get_address(wsaddrstr, true, displaynum, to,
+    for (i = 0; i < nwsaddrstr; i++) {
+        if (vnc_display_get_address(wsaddrstr[i], true, displaynum, to,
                                     has_ipv4, has_ipv6,
                                     ipv4, ipv6,
                                     &wsaddr, errp) < 0) {
-            goto error;
+            goto cleanup;
         }
-        if (saddr->type == SOCKET_ADDRESS_KIND_INET &&
+
+        /* Historical compat - if only a single listen address was
+         * provided, then this is used to set the default listen
+         * address for websocket too
+         */
+        if (*retnsaddr == 1 &&
+            (*retsaddr)[0]->type == SOCKET_ADDRESS_KIND_INET &&
             wsaddr->type == SOCKET_ADDRESS_KIND_INET &&
             g_str_equal(wsaddr->u.inet.data->host, "") &&
-            !g_str_equal(saddr->u.inet.data->host, "")) {
+            !g_str_equal((*retsaddr)[0]->u.inet.data->host, "")) {
             g_free(wsaddr->u.inet.data->host);
-            wsaddr->u.inet.data->host = g_strdup(saddr->u.inet.data->host);
+            wsaddr->u.inet.data->host =
+                g_strdup((*retsaddr)[0]->u.inet.data->host);
         }
+
+        *retwsaddr = g_renew(SocketAddress *, *retwsaddr, *retnwsaddr + 1);
+        (*retwsaddr)[(*retnwsaddr)++] = wsaddr;
     }
-    *retsaddr = saddr;
-    *retwsaddr = wsaddr;
-    return 0;
 
- error:
-    qapi_free_SocketAddress(saddr);
-    qapi_free_SocketAddress(wsaddr);
-    return -1;
+    ret = 0;
+ cleanup:
+    g_strfreev(saddrstr);
+    g_strfreev(wsaddrstr);
+    if (ret < 0) {
+        for (i = 0; i < *retnsaddr; i++) {
+            qapi_free_SocketAddress((*retsaddr)[i]);
+        }
+        g_free(*retsaddr);
+        for (i = 0; i < *retnwsaddr; i++) {
+            qapi_free_SocketAddress((*retwsaddr)[i]);
+        }
+        g_free(*retwsaddr);
+        *retsaddr = *retwsaddr = NULL;
+        *retnsaddr = *retnwsaddr = 0;
+    }
+    return ret;
 }
 
 static int vnc_display_connect(VncDisplay *vd,
-                               SocketAddress *saddr,
-                               SocketAddress *wsaddr,
+                               SocketAddress **saddr,
+                               size_t nsaddr,
+                               SocketAddress **wsaddr,
+                               size_t nwsaddr,
                                Error **errp)
 {
     /* connect to viewer */
     QIOChannelSocket *sioc = NULL;
-    if (wsaddr) {
+    if (nwsaddr != 0) {
         error_setg(errp, "Cannot use websockets in reverse mode");
         return -1;
     }
-    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
+    if (nsaddr != 1) {
+        error_setg(errp, "Expected a single address in reverse mo");
+        return -1;
+    }
+    vd->is_unix = saddr[0]->type == SOCKET_ADDRESS_KIND_UNIX;
     sioc = qio_channel_socket_new();
     qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
-    if (qio_channel_socket_connect_sync(sioc, saddr, errp) < 0) {
+    if (qio_channel_socket_connect_sync(sioc, saddr[0], errp) < 0) {
         return -1;
     }
     vnc_connect(vd, sioc, false, false);
@@ -3727,6 +3781,7 @@ static int vnc_display_listen_addr(VncDisplay *vd,
     SocketAddress **rawaddrs = NULL;
     size_t nrawaddrs = 0;
     Error *listenerr = NULL;
+    bool listening = false;
     size_t i;
 
     if (qio_dns_resolver_lookup_sync(resolver, addr, &nrawaddrs,
@@ -3742,6 +3797,7 @@ static int vnc_display_listen_addr(VncDisplay *vd,
                 sioc, rawaddrs[i], listenerr == NULL ? &listenerr : NULL) < 0) {
             continue;
         }
+        listening = true;
         (*nlsock)++;
         *lsock = g_renew(QIOChannelSocket *, *lsock, *nlsock);
         *lsock_tag = g_renew(guint, *lsock_tag, *nlsock);
@@ -3756,7 +3812,7 @@ static int vnc_display_listen_addr(VncDisplay *vd,
     g_free(rawaddrs);
 
     if (listenerr) {
-        if (*nlsock == 0) {
+        if (!listening) {
             error_propagate(errp, listenerr);
             return -1;
         } else {
@@ -3775,28 +3831,33 @@ static int vnc_display_listen_addr(VncDisplay *vd,
 
 
 static int vnc_display_listen(VncDisplay *vd,
-                              SocketAddress *saddr,
-                              SocketAddress *wsaddr,
+                              SocketAddress **saddr,
+                              size_t nsaddr,
+                              SocketAddress **wsaddr,
+                              size_t nwsaddr,
                               Error **errp)
 {
-    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
-
-    if (vnc_display_listen_addr(vd, saddr,
-                                "vnc-listen",
-                                &vd->lsock,
-                                &vd->lsock_tag,
-                                &vd->nlsock,
-                                errp) < 0) {
-        return -1;
+    size_t i;
+
+    for (i = 0; i < nsaddr; i++) {
+        if (vnc_display_listen_addr(vd, saddr[i],
+                                    "vnc-listen",
+                                    &vd->lsock,
+                                    &vd->lsock_tag,
+                                    &vd->nlsock,
+                                    errp) < 0) {
+            return -1;
+        }
     }
-    if (wsaddr &&
-        vnc_display_listen_addr(vd, wsaddr,
-                                "vnc-ws-listen",
-                                &vd->lwebsock,
-                                &vd->lwebsock_tag,
-                                &vd->nlwebsock,
-                                errp) < 0) {
-        return -1;
+    for (i = 0; i < nwsaddr; i++) {
+        if (vnc_display_listen_addr(vd, wsaddr[i],
+                                    "vnc-ws-listen",
+                                    &vd->lwebsock,
+                                    &vd->lwebsock_tag,
+                                    &vd->nlwebsock,
+                                    errp) < 0) {
+            return -1;
+        }
     }
 
     return 0;
@@ -3807,7 +3868,8 @@ void vnc_display_open(const char *id, Error **errp)
 {
     VncDisplay *vd = vnc_display_find(id);
     QemuOpts *opts = qemu_opts_find(&qemu_vnc_opts, id);
-    SocketAddress *saddr = NULL, *wsaddr = NULL;
+    SocketAddress **saddr = NULL, **wsaddr = NULL;
+    size_t nsaddr, nwsaddr;
     const char *share, *device_id;
     QemuConsole *con;
     bool password = false;
@@ -3820,6 +3882,7 @@ void vnc_display_open(const char *id, Error **errp)
     int acl = 0;
     int lock_key_sync = 1;
     int key_delay_ms;
+    size_t i;
 
     if (!vd) {
         error_setg(errp, "VNC display not active");
@@ -3831,7 +3894,9 @@ void vnc_display_open(const char *id, Error **errp)
         return;
     }
 
-    if (vnc_display_get_addresses(opts, &saddr, &wsaddr, errp) < 0) {
+    if (vnc_display_get_addresses(opts, &saddr, &nsaddr,
+                                  &wsaddr, &nwsaddr, errp) < 0) {
+        g_printerr("failing\n");
         goto fail;
     }
 
@@ -4021,11 +4086,11 @@ void vnc_display_open(const char *id, Error **errp)
     }
 
     if (reverse) {
-        if (vnc_display_connect(vd, saddr, wsaddr, errp) < 0) {
+        if (vnc_display_connect(vd, saddr, nsaddr, wsaddr, nwsaddr, errp) < 0) {
             goto fail;
         }
     } else {
-        if (vnc_display_listen(vd, saddr, wsaddr, errp) < 0) {
+        if (vnc_display_listen(vd, saddr, nsaddr, wsaddr, nwsaddr, errp) < 0) {
             goto fail;
         }
     }
@@ -4034,14 +4099,18 @@ void vnc_display_open(const char *id, Error **errp)
         vnc_display_print_local_addr(vd);
     }
 
-    qapi_free_SocketAddress(saddr);
-    qapi_free_SocketAddress(wsaddr);
+ cleanup:
+    for (i = 0; i < nsaddr; i++) {
+        qapi_free_SocketAddress(saddr[i]);
+    }
+    for (i = 0; i < nwsaddr; i++) {
+        qapi_free_SocketAddress(wsaddr[i]);
+    }
     return;
 
 fail:
     vnc_display_close(vd);
-    qapi_free_SocketAddress(saddr);
-    qapi_free_SocketAddress(wsaddr);
+    goto cleanup;
 }
 
 void vnc_display_add_client(const char *id, int csock, bool skipauth)
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server
  2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
                   ` (7 preceding siblings ...)
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
@ 2017-01-05 17:26 ` no-reply
  8 siblings, 0 replies; 19+ messages in thread
From: no-reply @ 2017-01-05 17:26 UTC (permalink / raw)
  To: berrange; +Cc: famz, qemu-devel, kraxel

Hi,

Your series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Message-id: 20170105160701.22118-1-berrange@redhat.com
Type: series
Subject: [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=16
make docker-test-quick@centos6
make docker-test-mingw@fedora
make docker-test-build@min-glib
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
b205d2a ui: add ability to specify multiple VNC listen addresses
28aff19 util: add qemu_opt_get_all() to get repeated opts
b0f616f ui: let VNC server listen on all resolved IP addresses
6cfe3ab ui: extract code to connect/listen from vnc_display_open
f8a6718 ui: refactor code for populating SocketAddress from vnc_display_open
7ca6bec ui: refactor VncDisplay to allow multiple listening sockets
14700a3 ui: fix reporting of VNC auth in query-vnc-servers
46aee05 ui: fix regression handling bare 'websocket' option to -vnc

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 'dtc'...
Submodule path 'dtc': checked out '65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf'
  BUILD   centos6
make[1]: Entering directory `/var/tmp/patchew-tester-tmp-h90nw6rj/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY    RUNNER
    RUN test-quick in qemu:centos6 
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=libfdt-devel ccache     tar git make gcc g++     zlib-devel glib2-devel SDL-devel pixman-devel     epel-release
HOSTNAME=f6a79ee9e6d4
TERM=xterm
MAKEFLAGS= -j16
HISTSIZE=1000
J=16
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /var/tmp/qemu-build/install
BIOS directory    /var/tmp/qemu-build/install/share/qemu
binary directory  /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install/etc
local state directory   /var/tmp/qemu-build/install/var
Manual directory  /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
C compiler        cc
Host C compiler   cc
C++ compiler      
Objective-C compiler cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1    -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all
LDFLAGS           -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
tcg debug enabled no
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
pixman            system
SDL support       yes (1.2.14)
GTK support       no 
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    no
GNUTLS rnd        no
libgcrypt         no
libgcrypt kdf     no
nettle            no 
nettle kdf        no
libtasn1          no
curses support    no
virgl support     no
curl support      no
mingw32 support   no
Audio drivers     oss
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
VNC support       yes
VNC SASL support  no
VNC JPEG support  no
VNC PNG support   no
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               yes
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
COLO support      yes
RDMA support      no
TCG interpreter   no
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends    log
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
GlusterFS support no
Archipelago support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   yes
QOM debugging     yes
lzo support       no
snappy support    no
bzip2 support     no
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     aarch64-softmmu/config-devices.mak.tmp
  GEN     config-host.h
  GEN     qemu-options.def
  GEN     qmp-commands.h
  GEN     qapi-types.h
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     qmp-introspect.h
  GEN     module_block.h
  GEN     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace/generated-tracers.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     trace/generated-tcg-tracers.h
  GEN     aarch64-softmmu/config-devices.mak
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     config-all-devices.mak
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  GEN     qmp-introspect.c
  GEN     qapi-types.c
  GEN     qapi-visit.c
  CC      qapi/qobject-input-visitor.o
  GEN     qapi-event.c
  CC      qapi/qapi-visit-core.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qint.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qfloat.o
  CC      qobject/qbool.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  GEN     trace/generated-tracers.c
  CC      trace/control.o
  CC      trace/qmp.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/compatfd.o
  CC      util/event_notifier-posix.o
  CC      util/mmap-alloc.o
  CC      util/oslib-posix.o
  CC      util/qemu-openpty.o
  CC      util/qemu-thread-posix.o
  CC      util/memfd.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-ucontext.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/arch-query-cpu-def.o
  CC      stubs/arch-query-cpu-model-expansion.o
  CC      stubs/arch-query-cpu-model-comparison.o
  CC      stubs/arch-query-cpu-model-baseline.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset-add-fd.o
  CC      stubs/fdset-find-fd.o
  CC      stubs/fdset-get-fd.o
  CC      stubs/fdset-remove-fd.o
  CC      stubs/gdbstub.o
  CC      stubs/get-fd.o
  CC      stubs/get-next-serial.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/mon-is-qmp.o
  CC      stubs/monitor-init.o
  CC      stubs/notify-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/replay-user.o
  CC      stubs/reset.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/cpus.o
  CC      stubs/kvm.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/vhost.o
  CC      stubs/iohandler.o
  CC      stubs/smbios_type_38.o
  CC      stubs/ipmi.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/migration-colo.o
  CC      contrib/ivshmem-client/ivshmem-client.o
  CC      contrib/ivshmem-client/main.o
  CC      contrib/ivshmem-server/ivshmem-server.o
  CC      contrib/ivshmem-server/main.o
  CC      qemu-nbd.o
  CC      thread-pool.o
  CC      async.o
  CC      block.o
  CC      blockjob.o
  CC      main-loop.o
  CC      iohandler.o
  CC      qemu-timer.o
  CC      aio-posix.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw_bsd.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qed.o
  CC      block/qed-gencb.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/raw-posix.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/nbd.o
  CC      block/throttle-groups.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
  CC      block/replication.o
  CC      block/crypto.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-glib.o
  CC      crypto/hmac.o
  CC      crypto/hmac-glib.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-platform.o
  CC      crypto/pbkdf.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  GEN     qemu-img-cmds.h
  CC      qemu-io.o
  CC      qemu-bridge-helper.o
  CC      blockdev.o
  CC      blockdev-nbd.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-posix.o
  CC      qemu-char.o
  CC      page_cache.o
  CC      accel.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      tpm.o
  CC      vl.o
  CC      device_tree.o
  GEN     qmp-marshal.c
  CC      qmp.o
  CC      hmp.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/ossaudio.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/rng-random.o
  CC      backends/msmouse.o
  CC      backends/testdev.o
  CC      backends/tpm.o
  CC      backends/hostmem-ram.o
  CC      backends/hostmem.o
  CC      backends/hostmem-file.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      disas/arm.o
  CC      disas/i386.o
  CC      fsdev/qemu-fsdev-dummy.o
  CC      fsdev/qemu-fsdev-opts.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/memory_hotplug_acpi_table.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/ipmi.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/block/nvme.o
  CC      hw/bt/core.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/null-machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/blizzard.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/tc6393xb.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/gpio_key.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/i2c-ddc.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/atapi.o
  CC      hw/ide/qdev.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ahci.o
  CC      hw/input/hid.o
  CC      hw/ide/ich.o
  CC      hw/input/lm832x.o
  CC      hw/input/pckbd.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/vmmouse.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/input/virtio-input-host.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
  CC      hw/net/ne2000-isa.o
  CC      hw/net/xgmac.o
  CC      hw/net/allwinner_emac.o
  CC      hw/net/imx_fec.o
  CC      hw/net/cadence_gem.o
  CC      hw/net/stellaris_enet.o
  CC      hw/net/rocker/rocker.o
  CC      hw/net/rocker/rocker_fp.o
  CC      hw/net/rocker/rocker_desc.o
  CC      hw/net/rocker/rocker_world.o
  CC      hw/net/rocker/rocker_of_dpa.o
  CC      hw/nvram/eeprom93xx.o
  CC      hw/nvram/fw_cfg.o
  CC      hw/nvram/chrp_nvram.o
  CC      hw/pci-bridge/pci_bridge_dev.o
  CC      hw/pci-bridge/pci_expander_bridge.o
  CC      hw/pci-bridge/xio3130_upstream.o
  CC      hw/pci-bridge/xio3130_downstream.o
  CC      hw/pci-bridge/ioh3420.o
  CC      hw/pci-bridge/i82801b11.o
  CC      hw/pci-host/pam.o
  CC      hw/pci-host/versatile.o
  CC      hw/pci-host/piix.o
  CC      hw/pci-host/q35.o
  CC      hw/pci-host/gpex.o
  CC      hw/pci/pci.o
  CC      hw/pci/pci_bridge.o
  CC      hw/pci/msix.o
  CC      hw/pci/msi.o
  CC      hw/pci/shpc.o
  CC      hw/pci/slotid_cap.o
  CC      hw/pci/pci_host.o
  CC      hw/pci/pcie_host.o
  CC      hw/pci/pcie.o
  CC      hw/pci/pcie_aer.o
  CC      hw/pci/pcie_port.o
  CC      hw/pci/pci-stub.o
  CC      hw/pcmcia/pcmcia.o
  CC      hw/scsi/scsi-disk.o
  CC      hw/scsi/scsi-generic.o
  CC      hw/scsi/scsi-bus.o
  CC      hw/scsi/lsi53c895a.o
  CC      hw/scsi/mptsas.o
/tmp/qemu-test/src/hw/nvram/fw_cfg.c: In function ‘fw_cfg_dma_transfer’:
/tmp/qemu-test/src/hw/nvram/fw_cfg.c:329: warning: ‘read’ may be used uninitialized in this function
  CC      hw/scsi/mptconfig.o
  CC      hw/scsi/mptendian.o
  CC      hw/scsi/megasas.o
  CC      hw/scsi/vmw_pvscsi.o
  CC      hw/scsi/esp.o
  CC      hw/scsi/esp-pci.o
  CC      hw/sd/pl181.o
  CC      hw/sd/ssi-sd.o
  CC      hw/sd/sd.o
  CC      hw/sd/core.o
  CC      hw/sd/sdhci.o
  CC      hw/smbios/smbios.o
  CC      hw/smbios/smbios_type_38.o
  CC      hw/ssi/pl022.o
  CC      hw/ssi/ssi.o
  CC      hw/ssi/xilinx_spips.o
  CC      hw/ssi/aspeed_smc.o
  CC      hw/ssi/stm32f2xx_spi.o
  CC      hw/timer/arm_timer.o
  CC      hw/timer/arm_mptimer.o
  CC      hw/timer/a9gtimer.o
  CC      hw/timer/cadence_ttc.o
  CC      hw/timer/ds1338.o
  CC      hw/timer/hpet.o
  CC      hw/timer/i8254_common.o
  CC      hw/timer/i8254.o
  CC      hw/timer/pl031.o
  CC      hw/timer/twl92230.o
  CC      hw/timer/imx_epit.o
  CC      hw/timer/imx_gpt.o
  CC      hw/timer/stm32f2xx_timer.o
  CC      hw/timer/aspeed_timer.o
  CC      hw/tpm/tpm_passthrough.o
  CC      hw/tpm/tpm_tis.o
  CC      hw/tpm/tpm_util.o
  CC      hw/usb/core.o
  CC      hw/usb/combined-packet.o
  CC      hw/usb/bus.o
  CC      hw/usb/libhw.o
  CC      hw/usb/desc.o
  CC      hw/usb/desc-msos.o
  CC      hw/usb/hcd-uhci.o
  CC      hw/usb/hcd-ohci.o
  CC      hw/usb/hcd-ehci.o
  CC      hw/usb/hcd-ehci-sysbus.o
  CC      hw/usb/hcd-ehci-pci.o
  CC      hw/usb/hcd-xhci.o
  CC      hw/usb/hcd-musb.o
  CC      hw/usb/dev-hub.o
  CC      hw/usb/dev-hid.o
  CC      hw/usb/dev-wacom.o
  CC      hw/usb/dev-storage.o
  CC      hw/usb/dev-uas.o
  CC      hw/usb/dev-audio.o
  CC      hw/usb/dev-serial.o
  CC      hw/usb/dev-network.o
  CC      hw/usb/dev-bluetooth.o
  CC      hw/usb/dev-smartcard-reader.o
  CC      hw/usb/dev-mtp.o
  CC      hw/usb/host-stub.o
  CC      hw/virtio/virtio-rng.o
  CC      hw/virtio/virtio-pci.o
  CC      hw/virtio/virtio-bus.o
  CC      hw/virtio/virtio-mmio.o
  CC      hw/watchdog/watchdog.o
  CC      hw/watchdog/wdt_i6300esb.o
  CC      hw/watchdog/wdt_ib700.o
  CC      migration/migration.o
  CC      migration/socket.o
  CC      migration/fd.o
  CC      migration/exec.o
  CC      migration/tls.o
  CC      migration/colo-comm.o
  CC      migration/colo.o
  CC      migration/colo-failover.o
  CC      migration/vmstate.o
  CC      migration/qemu-file.o
  CC      migration/qemu-file-channel.o
  CC      migration/xbzrle.o
  CC      migration/postcopy-ram.o
  CC      migration/qjson.o
  CC      migration/block.o
  CC      net/net.o
  CC      net/queue.o
  CC      net/util.o
  CC      net/checksum.o
  CC      net/hub.o
  CC      net/socket.o
  CC      net/dump.o
  CC      net/eth.o
  CC      net/l2tpv3.o
  CC      net/tap.o
  CC      net/vhost-user.o
  CC      net/tap-linux.o
  CC      net/slirp.o
  CC      net/filter.o
  CC      net/filter-buffer.o
  CC      net/filter-mirror.o
  CC      net/colo-compare.o
  CC      net/colo.o
  CC      net/filter-rewriter.o
  CC      qom/cpu.o
  CC      replay/replay.o
  CC      replay/replay-internal.o
  CC      replay/replay-events.o
  CC      replay/replay-time.o
  CC      replay/replay-input.o
  CC      replay/replay-char.o
  CC      replay/replay-snapshot.o
  CC      slirp/cksum.o
  CC      slirp/if.o
  CC      slirp/ip_icmp.o
  CC      slirp/ip6_icmp.o
  CC      slirp/ip6_input.o
  CC      slirp/ip6_output.o
  CC      slirp/ip_input.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC      slirp/ip_output.o
  CC      slirp/dnssearch.o
  CC      slirp/dhcpv6.o
  CC      slirp/slirp.o
  CC      slirp/mbuf.o
  CC      slirp/misc.o
  CC      slirp/sbuf.o
  CC      slirp/socket.o
  CC      slirp/tcp_input.o
  CC      slirp/tcp_output.o
  CC      slirp/tcp_subr.o
  CC      slirp/tcp_timer.o
  CC      slirp/udp.o
  CC      slirp/udp6.o
  CC      slirp/bootp.o
  CC      slirp/arp_table.o
  CC      slirp/tftp.o
  CC      slirp/ndp_table.o
  CC      ui/keymaps.o
  CC      ui/console.o
  CC      ui/cursor.o
  CC      ui/qemu-pixman.o
  CC      ui/input.o
  CC      ui/input-keymap.o
  CC      ui/input-legacy.o
  CC      ui/input-linux.o
  CC      ui/sdl.o
  CC      ui/sdl_zoom.o
  CC      ui/x_keymap.o
  CC      ui/vnc.o
  CC      ui/vnc-enc-zlib.o
  CC      ui/vnc-enc-hextile.o
  CC      ui/vnc-enc-tight.o
  CC      ui/vnc-palette.o
  CC      ui/vnc-enc-zrle.o
  CC      ui/vnc-auth-vencrypt.o
  CC      ui/vnc-ws.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
  CC      ui/vnc-jobs.o
  LINK    tests/qemu-iotests/socket_scm_helper
  CC      qga/commands.o
  CC      qga/guest-agent-command-state.o
  CC      qga/main.o
  CC      qga/commands-posix.o
  AS      optionrom/multiboot.o
  AS      optionrom/linuxboot.o
  CC      optionrom/linuxboot_dma.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
  AS      optionrom/kvmvapic.o
  BUILD   optionrom/multiboot.img
  BUILD   optionrom/linuxboot.img
  BUILD   optionrom/linuxboot_dma.img
  CC      qga/channel-posix.o
  BUILD   optionrom/kvmvapic.img
  BUILD   optionrom/multiboot.raw
  BUILD   optionrom/linuxboot.raw
  BUILD   optionrom/linuxboot_dma.raw
  BUILD   optionrom/kvmvapic.raw
  SIGN    optionrom/multiboot.bin
  SIGN    optionrom/linuxboot.bin
  SIGN    optionrom/linuxboot_dma.bin
  SIGN    optionrom/kvmvapic.bin
  CC      qga/qapi-generated/qga-qapi-types.o
  CC      qga/qapi-generated/qga-qapi-visit.o
  CC      qga/qapi-generated/qga-qmp-marshal.o
  CC      qmp-introspect.o
  CC      qapi-types.o
/tmp/qemu-test/src/ui/vnc.c:48:29: error: io/dns-resolver.h: No such file or directory
/tmp/qemu-test/src/ui/vnc.c: In function ‘vnc_display_listen_addr’:
/tmp/qemu-test/src/ui/vnc.c:3780: error: ‘QIODNSResolver’ undeclared (first use in this function)
/tmp/qemu-test/src/ui/vnc.c:3780: error: (Each undeclared identifier is reported only once
/tmp/qemu-test/src/ui/vnc.c:3780: error: for each function it appears in.)
/tmp/qemu-test/src/ui/vnc.c:3780: error: ‘resolver’ undeclared (first use in this function)
/tmp/qemu-test/src/ui/vnc.c:3780: warning: implicit declaration of function ‘qio_dns_resolver_get_instance’
/tmp/qemu-test/src/ui/vnc.c:3780: warning: nested extern declaration of ‘qio_dns_resolver_get_instance’
/tmp/qemu-test/src/ui/vnc.c:3787: warning: implicit declaration of function ‘qio_dns_resolver_lookup_sync’
/tmp/qemu-test/src/ui/vnc.c:3787: warning: nested extern declaration of ‘qio_dns_resolver_lookup_sync’
  CC      qapi-visit.o
make: *** [ui/vnc.o] Error 1
make: *** Waiting for unfinished jobs....
make[1]: *** [docker-run] Error 2
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-h90nw6rj/src'
make: *** [docker-run-test-quick@centos6] Error 2
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
@ 2017-01-06 13:39   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 13:39 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 1060 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> The -vnc argument is documented as accepting two syntaxes for
> the 'websocket' option, either a bare option name, or a port
> number. If using the bare option name, it is supposed to apply
> the display number as an offset to base port 5700. e.g.
> 
>   -vnc localhost:3,websocket
> 
> should listen on port 5703, however, this was broken in 2.3.0 since
> 
>   commit 4db14629c38611061fc19ec6927405923de84f08
>   Author: Gerd Hoffmann <kraxel@redhat.com>
>   Date:   Tue Sep 16 12:33:03 2014 +0200
> 
>     vnc: switch to QemuOpts, allow multiple servers
> 
> instead qemu tries to listen on port "on" which gets looked up in
> /etc/services and fails.
> 
> Fixes bug: #1455912
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  ui/vnc.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
@ 2017-01-06 15:06   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 15:06 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 3129 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> Currently the VNC authentication info is emitted at the
> top level of the query-vnc-servers data. This is wrong
> because the authentication scheme differs between plain
> and websockets when TLS is enabled. We should instead
> report auth against the individual servers. e.g.
> 
> (QEMU) query-vnc-servers
> {
>     "return": [
>         {
>             "clients": [],
>             "id": "default",
>             "auth": "vencrypt",

So we have to keep the old location for back-compat,...

>             "vencrypt": "x509-vnc",
>             "server": [
>                 {
>                     "host": "127.0.0.1"
>                     "service": "5901",
>                     "websocket": false,
>                     "family": "ipv4",
>                     "auth": "vencrypt",
>                     "vencrypt": "x509-vnc",

No trailing comma (JSON is too picky)

>                 }
>                 {
>                     "host": "127.0.0.1",
>                     "service": "5902",
>                     "websocket": true,
>                     "family": "ipv4",
>                     "auth": "vnc"

...but add the new location to fix the problem.
>                 },

No trailing comma

>             ]
>         }
>     ]
> }
> 
> This also future proofs the QMP schema so that we can
> cope with multiple VNC server instances, listening on
> different interfaces or ports, with different auth
> setup.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  qapi-schema.json | 26 +++++++++++++++--
>  ui/vnc.c         | 85 +++++++++++++++++++++++++++++++++-----------------------
>  2 files changed, 73 insertions(+), 38 deletions(-)
> 

>  
> +
> +##
> +# @VncServerInfo2
> +#
> +# The network connection information for server
> +#
> +# @auth: The current authentication type used by the server
> +#
> +# @vencrypt: #optional The vencrypt sub authentication type used by the server,
> +#            only specified in case auth == vencrypt.
> +#
> +# Since: 2.8

2.9, actually

> @@ -1210,7 +1230,7 @@
>  # @clients: A list of @VncClientInfo of all currently connected clients.
>  #           The list can be empty, for obvious reasons.
>  #
> -# @auth: The current authentication type used by the server
> +# @auth: The current authentication type used by the non-websockets server

Since server is an array, should this read 'servers' or even 'server(s)'?

>  #
>  # @vencrypt: #optional The vencrypt sub authentication type used by the server,
>  #            only specified in case auth == vencrypt.
> @@ -1221,7 +1241,7 @@
>  ##
>  { 'struct': 'VncInfo2',
>    'data': { 'id'        : 'str',
> -            'server'    : ['VncBasicInfo'],
> +            'server'    : ['VncServerInfo2'],

Backwards-compatible, so you're fine making the change.

Once the nits are resolved, you can add:
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets Daniel P. Berrange
@ 2017-01-06 15:23   ` Eric Blake
  2017-01-06 15:28     ` Daniel P. Berrange
  0 siblings, 1 reply; 19+ messages in thread
From: Eric Blake @ 2017-01-06 15:23 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 2458 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> Currently there is only a single listener for plain VNC and
> a single listener for websockets VNC. This means that is

s/is/if/

> getaddrinfo() returns multiple IP addresses, for a hostname,
> the VNC server can only listen on one of them. This is
> just bearable if listening on wildcard interface, or if
> the host only has a single network interface to listen on,
> but if there are multiple NICs and the VNC server needs
> to listen on 2 or more specific IP addresses, it can't be
> done.
> 
> This refactors the VncDisplay state so that it holds an
> array of listening sockets, but still only listens on
> one socket.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  ui/vnc.c | 103 +++++++++++++++++++++++++++++++++++++++++----------------------
>  ui/vnc.h |  10 ++++---
>  2 files changed, 73 insertions(+), 40 deletions(-)

Are you using git's order directives to put .h files first?


> @@ -3819,30 +3843,36 @@ void vnc_display_open(const char *id, Error **errp)
>          vnc_connect(vd, sioc, false, false);
>          object_unref(OBJECT(sioc));
>      } else {
> -        vd->lsock = qio_channel_socket_new();
> -        qio_channel_set_name(QIO_CHANNEL(vd->lsock), "vnc-listen");
> -        if (qio_channel_socket_listen_sync(vd->lsock, saddr, errp) < 0) {
> +        vd->nlsock = 1;
> +        vd->lsock = g_new0(QIOChannelSocket *, 1);
> +        vd->lsock_tag = g_new0(guint, 1);

Is guint really the best type here...

> +++ b/ui/vnc.h
> @@ -146,10 +146,12 @@ struct VncDisplay
>      int num_exclusive;
>      int connections_limit;
>      VncSharePolicy share_policy;
> -    QIOChannelSocket *lsock;
> -    guint lsock_tag;
> -    QIOChannelSocket *lwebsock;
> -    guint lwebsock_tag;
> +    size_t nlsock;
> +    QIOChannelSocket **lsock;
> +    guint *lsock_tag;

...and here?

> +    size_t nlwebsock;
> +    QIOChannelSocket **lwebsock;
> +    guint *lwebsock_tag;
>      DisplaySurface *ds;
>      DisplayChangeListener dcl;
>      kbd_layout_t *kbd_layout;
> 

Whether or not you tweak the types to something a little more direct (I
thing guint is more hassle than it's worth when not directly passing the
field to glib functions),
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets
  2017-01-06 15:23   ` Eric Blake
@ 2017-01-06 15:28     ` Daniel P. Berrange
  0 siblings, 0 replies; 19+ messages in thread
From: Daniel P. Berrange @ 2017-01-06 15:28 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, Gerd Hoffmann

On Fri, Jan 06, 2017 at 09:23:24AM -0600, Eric Blake wrote:
> On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> > Currently there is only a single listener for plain VNC and
> > a single listener for websockets VNC. This means that is
> 
> s/is/if/
> 
> > getaddrinfo() returns multiple IP addresses, for a hostname,
> > the VNC server can only listen on one of them. This is
> > just bearable if listening on wildcard interface, or if
> > the host only has a single network interface to listen on,
> > but if there are multiple NICs and the VNC server needs
> > to listen on 2 or more specific IP addresses, it can't be
> > done.
> > 
> > This refactors the VncDisplay state so that it holds an
> > array of listening sockets, but still only listens on
> > one socket.
> > 
> > Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> > ---
> >  ui/vnc.c | 103 +++++++++++++++++++++++++++++++++++++++++----------------------
> >  ui/vnc.h |  10 ++++---
> >  2 files changed, 73 insertions(+), 40 deletions(-)
> 
> Are you using git's order directives to put .h files first?

No special git config at all.

> > @@ -3819,30 +3843,36 @@ void vnc_display_open(const char *id, Error **errp)
> >          vnc_connect(vd, sioc, false, false);
> >          object_unref(OBJECT(sioc));
> >      } else {
> > -        vd->lsock = qio_channel_socket_new();
> > -        qio_channel_set_name(QIO_CHANNEL(vd->lsock), "vnc-listen");
> > -        if (qio_channel_socket_listen_sync(vd->lsock, saddr, errp) < 0) {
> > +        vd->nlsock = 1;
> > +        vd->lsock = g_new0(QIOChannelSocket *, 1);
> > +        vd->lsock_tag = g_new0(guint, 1);
> 
> Is guint really the best type here...

Yep, guint is what the the Glib main loop uses as the type for
tracking GSource IDs. e.g.

https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-get-id

> 
> > +++ b/ui/vnc.h
> > @@ -146,10 +146,12 @@ struct VncDisplay
> >      int num_exclusive;
> >      int connections_limit;
> >      VncSharePolicy share_policy;
> > -    QIOChannelSocket *lsock;
> > -    guint lsock_tag;
> > -    QIOChannelSocket *lwebsock;
> > -    guint lwebsock_tag;
> > +    size_t nlsock;
> > +    QIOChannelSocket **lsock;
> > +    guint *lsock_tag;
> 
> ...and here?
> 
> > +    size_t nlwebsock;
> > +    QIOChannelSocket **lwebsock;
> > +    guint *lwebsock_tag;
> >      DisplaySurface *ds;
> >      DisplayChangeListener dcl;
> >      kbd_layout_t *kbd_layout;
> > 
> 
> Whether or not you tweak the types to something a little more direct (I
> thing guint is more hassle than it's worth when not directly passing the
> field to glib functions),

It'll be passed to g_source_remove later which expects guint

https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-remove

> Reviewed-by: Eric Blake <eblake@redhat.com>

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
@ 2017-01-06 15:47   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 15:47 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 2544 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> The code which interprets the CLI args to populate the SocketAddress
> objects for plain & websockets VNC is quite complex already and will
> need further enhancements shortly. Refactor it into separate methods
> to avoid vnc_display_open getting even larger. As a side effect of
> the refactoring, it is now possible to specify a listen address for
> the websocket server explicitly. e.g,
> 
>   -vnc localhost:5900,websockets=0.0.0.0:8080
> 
> will listen on localhost for the plain VNC server, but expose the
> websockets VNC server on the public interface. This refactoring
> also removes the restriction that prevents enabling websockets
> when the plain VNC server is listening on a UNIX socket.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  qemu-options.hx |  12 ++-
>  ui/vnc.c        | 282 ++++++++++++++++++++++++++++++++++++--------------------
>  2 files changed, 189 insertions(+), 105 deletions(-)
> 
> diff --git a/qemu-options.hx b/qemu-options.hx
> index c534a2f..7470def 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1297,10 +1297,14 @@ is a TCP port number, not a display number.
>  @item websocket
>  
>  Opens an additional TCP listening port dedicated to VNC Websocket connections.
> -By definition the Websocket port is 5700+@var{display}. If @var{host} is
> -specified connections will only be allowed from this host.
> -As an alternative the Websocket port could be specified by using
> -@code{websocket}=@var{port}.
> +If a bare @var{websocket} option is given, the Websocket port is
> +5700+@var{display}. An alternative port can be specified with the
> +syntax @code{websocket}=@var{port}.
> +
> +If @var{host} is specified connections will only be allowed from this host.
> +It is possible to control the websocket listen address independantly using

s/independantly/independently,/

> +the syntax @code{websocket}=@var{host}:@var{port}.
> +
>  If no TLS credentials are provided, the websocket connection runs in
>  unencrypted mode. If TLS credentials are provided, the websocket connection
>  requires encrypted client connections.
> diff --git a/ui/vnc.c b/ui/vnc.c
> index b37aab4..8d3f9c1 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3519,6 +3519,178 @@ vnc_display_create_creds(bool x509,
>  }
>  
>  

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen from vnc_display_open
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen " Daniel P. Berrange
@ 2017-01-06 16:00   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 16:00 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 3301 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> The code which takes a SocketAddress and connects/listens on the
> network is going to get more complicated to deal with multiple
> listeners. Pull it out into a separate method to avoid making the
> vnc_display_open method even more complex.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  ui/vnc.c | 122 +++++++++++++++++++++++++++++++++++++++++----------------------
>  1 file changed, 80 insertions(+), 42 deletions(-)
> 

> +static int vnc_display_listen(VncDisplay *vd,
> +                              SocketAddress *saddr,
> +                              SocketAddress *wsaddr,
> +                              Error **errp)
> +{
> +    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
> +
> +    if (vnc_display_listen_addr(vd, saddr,
> +                                "vnc-listen",
> +                                &vd->lsock,
> +                                &vd->lsock_tag,
> +                                &vd->nlsock,
> +                                errp) < 0) {
> +        return -1;

If this succeeds,

> +    }
> +    if (wsaddr &&
> +        vnc_display_listen_addr(vd, wsaddr,
> +                                "vnc-ws-listen",
> +                                &vd->lwebsock,
> +                                &vd->lwebsock_tag,
> +                                &vd->nlwebsock,
> +                                errp) < 0) {
> +        return -1;

but this fails, you are relying on the caller to clean up the successful
port allocation.  Then again, in the old code:

> @@ -3909,53 +3987,13 @@ void vnc_display_open(const char *id, Error **errp)

>      } else {
> -        vd->nlsock = 1;
> -        vd->lsock = g_new0(QIOChannelSocket *, 1);
> -        vd->lsock_tag = g_new0(guint, 1);
> -
> -        vd->lsock[0] = qio_channel_socket_new();
> -        qio_channel_set_name(QIO_CHANNEL(vd->lsock[0]), "vnc-listen");
> -        if (qio_channel_socket_listen_sync(vd->lsock[0], saddr, errp) < 0) {
> +        if (vnc_display_listen(vd, saddr, wsaddr, errp) < 0) {
>              goto fail;
>          }
> -        vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
> -
> -        if (wsaddr) {
> -            vd->nlwebsock = 1;
> -            vd->lwebsock = g_new0(QIOChannelSocket *, 1);
> -            vd->lwebsock_tag = g_new0(guint, 1);
> -
> -            vd->lwebsock[0] = qio_channel_socket_new();
> -            qio_channel_set_name(QIO_CHANNEL(vd->lwebsock[0]), "vnc-ws-listen");
> -            if (qio_channel_socket_listen_sync(vd->lwebsock[0],
> -                                               wsaddr, errp) < 0) {
> -                goto fail;
> -            }

this is all the more cleanup you do locally:

fail:
    qapi_free_SocketAddress(saddr);
    qapi_free_SocketAddress(wsaddr);
    ws_enabled = false;

so you already have cleanup at a distance when you have partial
allocation before failure (that is, the caller cleans up the
partially-constructed 'vd' object when errp is set).  So you aren't
making it worse.  Thus

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses
  2017-01-05 16:06 ` [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
@ 2017-01-06 16:14   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 16:14 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 2246 bytes --]

On 01/05/2017 10:06 AM, Daniel P. Berrange wrote:
> Remove the limitation that the VNC server can only listen on
> a single resolved IP address. This uses the new DNS resolver
> API to resolve a SocketAddress struct into an array of
> SocketAddress structs containing raw IP addresses. The VNC
> server will then attempt to listen on all resolve IP addresses.

s/resolve/resolved/

> An error will be returned if it was not possible to listen on
> all of the IP addresses.

s/all/any/ ?  That is, we fail only if we don't get at least one working
listener, or do we fail if even one listener fails while the other work?

> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  ui/vnc.c | 52 +++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 43 insertions(+), 9 deletions(-)
> 

> -    (*lsock_tag)[0] = qio_channel_add_watch(
> -        QIO_CHANNEL((*lsock)[0]),
> -        G_IO_IN, vnc_listen_io, vd, NULL);
> +    for (i = 0; i < nrawaddrs; i++) {
> +        QIOChannelSocket *sioc = qio_channel_socket_new();
> +
> +        qio_channel_set_name(QIO_CHANNEL(sioc), name);
> +        if (qio_channel_socket_listen_sync(
> +                sioc, rawaddrs[i], listenerr == NULL ? &listenerr : NULL) < 0) {
> +            continue;
> +        }
> +        (*nlsock)++;
> +        *lsock = g_renew(QIOChannelSocket *, *lsock, *nlsock);
> +        *lsock_tag = g_renew(guint, *lsock_tag, *nlsock);
> +
> +        (*lsock)[*nlsock - 1] = sioc;
> +        (*lsock_tag)[*nlsock - 1] = 0;
> +    }
> +
> +    for (i = 0; i < nrawaddrs; i++) {
> +        qapi_free_SocketAddress(rawaddrs[i]);
> +    }
> +    g_free(rawaddrs);
> +
> +    if (listenerr) {
> +        if (*nlsock == 0) {
> +            error_propagate(errp, listenerr);
> +            return -1;
> +        } else {
> +            error_free(listenerr);
> +        }
> +    }

Answering my question - you fail only if ALL resolved addresses fail. If
at least one succeeds, the overall function succeeds.

With the commit message improved,
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts Daniel P. Berrange
@ 2017-01-06 16:22   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 16:22 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 3028 bytes --]

On 01/05/2017 10:07 AM, Daniel P. Berrange wrote:
> The QemuOpts parser accepts repeated option names, storing
> all the provided values. qemu_opt_get() then just returns
> the last value. There is no way to get the other values
> without using a callback function to iterate over all
> option names. Add a qemu_opt_get_all() method to return
> a string list of all values.
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  include/qemu/option.h |  1 +
>  util/qemu-option.c    | 22 ++++++++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/include/qemu/option.h b/include/qemu/option.h
> index 1f9e3f9..689e0a8 100644
> --- a/include/qemu/option.h
> +++ b/include/qemu/option.h
> @@ -65,6 +65,7 @@ struct QemuOptsList {
>  };
>  
>  const char *qemu_opt_get(QemuOpts *opts, const char *name);
> +size_t qemu_opt_get_all(QemuOpts *opts, const char *name, char ***vals);
>  char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>  /**
>   * qemu_opt_has_help_opt:
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index 3467dc2..0418d71 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -332,6 +332,28 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
>      return opt ? opt->str : NULL;
>  }
>  
> +size_t qemu_opt_get_all(QemuOpts *opts, const char *name, char ***vals)

Documentation would be nice, including that the caller must free two
levels of results.

> +{
> +    QemuOpt *opt;
> +    size_t nvals = 0;
> +
> +    *vals = NULL;
> +
> +    QTAILQ_FOREACH(opt, &opts->head, next) {
> +        if (!g_str_equal(opt->name, name)) {
> +            continue;
> +        }
> +
> +        *vals = g_renew(char *, *vals, nvals + 1);
> +        (*vals)[nvals++] = g_strdup(opt->str);

This one is noticeably O(n^2) if the user supplies LOTS of repeated
options on the command line.  Should we be smarter about the allocation,
since unlike DNS resolution, we don't have quite as much assurance that
the user won't be doing that?  You do have an upper bound that this
won't call g_renew() any more than the number of opts present in the
command-line argument that you could use for O(1) instead of O(n) list
allocations (the O(n^2) is caused by O(n) allocations coupled with O(n)
copying between allocations), but I don't know if we have easy access to
that value, nor if it is wasteful to over-allocate when the more common
case is that most of the opts are not equal to name.

> +    }
> +    if (nvals) {
> +        *vals = g_renew(char *, *vals, nvals + 1);
> +        (*vals)[nvals] = NULL;
> +    }
> +    return nvals;
> +}
> +
>  /* Get a known option (or its default) and remove it from the list
>   * all in one action. Return a malloced string of the option value.
>   * Result must be freed by caller with g_free().
> 

The idea makes sense, though.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses
  2017-01-05 16:07 ` [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
@ 2017-01-06 16:34   ` Eric Blake
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2017-01-06 16:34 UTC (permalink / raw)
  To: Daniel P. Berrange, qemu-devel; +Cc: Gerd Hoffmann

[-- Attachment #1: Type: text/plain, Size: 4256 bytes --]

On 01/05/2017 10:07 AM, Daniel P. Berrange wrote:
> This change allows the listen address and websocket address
> options for -vnc to be repeated. This causes the VNC server
> to listen on multiple addresses. e.g.
> 
>  $ $QEMU -vnc vnc=localhost:1,vnc=unix:/tmp/vnc,\
>               websocket=127.0.0.1:8080,websocket=[::]:8081
> 
> results in listening on
> 
> 127.0.0.1:5901, 127.0.0.1:8080, ::1:5901, :::8081 & /tmp/vnc
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
> ---
>  ui/vnc.c | 191 +++++++++++++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 130 insertions(+), 61 deletions(-)
> 

> +    for (i = 0; i < nsaddrstr; i++) {
> +        int rv;
> +        rv = vnc_display_get_address(saddrstr[i], false, 0, to,
> +                                     has_ipv4, has_ipv6,
> +                                     ipv4, ipv6,
> +                                     &saddr, errp);
> +        if (rv < 0) {
> +            goto cleanup;
> +        }
> +        /* Historical compat - if only a single listen address was
> +         * provided, then the display num can be used to set the
> +         * default websocket port
> +         */
> +        if (nsaddrstr == 1) {
> +            displaynum = rv;
> +        }
> +        *retsaddr = g_renew(SocketAddress *, *retsaddr, *retnsaddr + 1);
> +        (*retsaddr)[(*retnsaddr)++] = saddr;

Again, do we care if the user supplies LOTS of vnc addresses and
witnesses O(n^2) initialization cost?

>      }
> -    if (wsaddrstr) {
> -        if (vnc_display_get_address(wsaddrstr, true, displaynum, to,
> +    for (i = 0; i < nwsaddrstr; i++) {
> +        if (vnc_display_get_address(wsaddrstr[i], true, displaynum, to,
>                                      has_ipv4, has_ipv6,

> +
> +        *retwsaddr = g_renew(SocketAddress *, *retwsaddr, *retnwsaddr + 1);
> +        (*retwsaddr)[(*retnwsaddr)++] = wsaddr;

Same for websocket addresses.

>  static int vnc_display_connect(VncDisplay *vd,
> -                               SocketAddress *saddr,
> -                               SocketAddress *wsaddr,
> +                               SocketAddress **saddr,
> +                               size_t nsaddr,
> +                               SocketAddress **wsaddr,
> +                               size_t nwsaddr,
>                                 Error **errp)
>  {
>      /* connect to viewer */
>      QIOChannelSocket *sioc = NULL;
> -    if (wsaddr) {
> +    if (nwsaddr != 0) {
>          error_setg(errp, "Cannot use websockets in reverse mode");
>          return -1;
>      }
> -    vd->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
> +    if (nsaddr != 1) {
> +        error_setg(errp, "Expected a single address in reverse mo");

s/mo/mode/


>  static int vnc_display_listen(VncDisplay *vd,

> -    if (wsaddr &&
> -        vnc_display_listen_addr(vd, wsaddr,
> -                                "vnc-ws-listen",
> -                                &vd->lwebsock,
> -                                &vd->lwebsock_tag,
> -                                &vd->nlwebsock,
> -                                errp) < 0) {
> -        return -1;
> +    for (i = 0; i < nwsaddr; i++) {
> +        if (vnc_display_listen_addr(vd, wsaddr[i],
> +                                    "vnc-ws-listen",
> +                                    &vd->lwebsock,
> +                                    &vd->lwebsock_tag,
> +                                    &vd->nlwebsock,
> +                                    errp) < 0) {

And while your earlier arguments that resolving a single name into
multiple websocket IP addrs is not going to notice an O(n^2) growth
pattern, now we are calling that growth pattern over N websocket names
where N is user-controlled.  But this time I don't have a good bound on
how many IP addrs nlwebsock will grow to. So maybe we do want to
consider geometric allocation growth (requires tracking and passing an
allocated size alongside the currently-used size).

But overall I think you're enhancement makes sense.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-01-06 16:34 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-05 16:06 [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server Daniel P. Berrange
2017-01-05 16:06 ` [Qemu-devel] [PATCH 1/8] ui: fix regression handling bare 'websocket' option to -vnc Daniel P. Berrange
2017-01-06 13:39   ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 2/8] ui: fix reporting of VNC auth in query-vnc-servers Daniel P. Berrange
2017-01-06 15:06   ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 3/8] ui: refactor VncDisplay to allow multiple listening sockets Daniel P. Berrange
2017-01-06 15:23   ` Eric Blake
2017-01-06 15:28     ` Daniel P. Berrange
2017-01-05 16:06 ` [Qemu-devel] [PATCH 4/8] ui: refactor code for populating SocketAddress from vnc_display_open Daniel P. Berrange
2017-01-06 15:47   ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 5/8] ui: extract code to connect/listen " Daniel P. Berrange
2017-01-06 16:00   ` Eric Blake
2017-01-05 16:06 ` [Qemu-devel] [PATCH 6/8] ui: let VNC server listen on all resolved IP addresses Daniel P. Berrange
2017-01-06 16:14   ` Eric Blake
2017-01-05 16:07 ` [Qemu-devel] [PATCH 7/8] util: add qemu_opt_get_all() to get repeated opts Daniel P. Berrange
2017-01-06 16:22   ` Eric Blake
2017-01-05 16:07 ` [Qemu-devel] [PATCH 8/8] ui: add ability to specify multiple VNC listen addresses Daniel P. Berrange
2017-01-06 16:34   ` Eric Blake
2017-01-05 17:26 ` [Qemu-devel] [PATCH 0/8] Support multiple listening sockets per VNC server no-reply

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 NNTP newsgroup(s).