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