]> Git Repo - qemu.git/blobdiff - ui/spice-core.c
Error out when tls-channel option is used without TLS
[qemu.git] / ui / spice-core.c
index 6d3dab6960f93ebd7167e269e81eed07735b4ce6..c1091e1602a8a96332f7bba4ee82755292a0a60a 100644 (file)
@@ -27,6 +27,7 @@
 #include "qemu-queue.h"
 #include "qemu-x509.h"
 #include "qemu_socket.h"
+#include "qmp-commands.h"
 #include "qint.h"
 #include "qbool.h"
 #include "qstring.h"
@@ -138,8 +139,6 @@ static void watch_remove(SpiceWatch *watch)
     g_free(watch);
 }
 
-#if SPICE_INTERFACE_CORE_MINOR >= 3
-
 typedef struct ChannelList ChannelList;
 struct ChannelList {
     SpiceChannelEventInfo *info;
@@ -194,22 +193,6 @@ static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
     qdict_put(dict, "tls", qbool_from_int(tls));
 }
 
-static QList *channel_list_get(void)
-{
-    ChannelList *item;
-    QList *list;
-    QDict *dict;
-
-    list = qlist_new();
-    QTAILQ_FOREACH(item, &channel_list, link) {
-        dict = qdict_new();
-        add_addr_info(dict, &item->info->paddr, item->info->plen);
-        add_channel_info(dict, item->info);
-        qlist_append(list, dict);
-    }
-    return list;
-}
-
 static void channel_event(int event, SpiceChannelEventInfo *info)
 {
     static const int qevent[] = {
@@ -235,10 +218,23 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
     }
 
     client = qdict_new();
-    add_addr_info(client, &info->paddr, info->plen);
-
     server = qdict_new();
-    add_addr_info(server, &info->laddr, info->llen);
+
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+    if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+        add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
+                      info->plen_ext);
+        add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
+                      info->llen_ext);
+    } else {
+        error_report("spice: %s, extended address is expected",
+                     __func__);
+#endif
+        add_addr_info(client, &info->paddr, info->plen);
+        add_addr_info(server, &info->laddr, info->llen);
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+    }
+#endif
 
     if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
         qdict_put(server, "auth", qstring_from_str(auth));
@@ -259,15 +255,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
     }
 }
 
-#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
-static QList *channel_list_get(void)
-{
-    return NULL;
-}
-
-#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
-
 static SpiceCoreInterface core_interface = {
     .base.type          = SPICE_INTERFACE_CORE,
     .base.description   = "qemu core services",
@@ -283,9 +270,7 @@ static SpiceCoreInterface core_interface = {
     .watch_update_mask  = watch_update_mask,
     .watch_remove       = watch_remove,
 
-#if SPICE_INTERFACE_CORE_MINOR >= 3
     .channel_event      = channel_event,
-#endif
 };
 
 #ifdef SPICE_INTERFACE_MIGRATION
@@ -348,7 +333,7 @@ static int parse_name(const char *string, const char *optname,
     if (value != -1) {
         return value;
     }
-    fprintf(stderr, "spice: invalid %s: %s\n", optname, string);
+    error_report("spice: invalid %s: %s", optname, string);
     exit(1);
 }
 
@@ -383,98 +368,104 @@ static const char *wan_compression_names[] = {
 
 /* functions for the rest of qemu */
 
-static void info_spice_iter(QObject *obj, void *opaque)
+static SpiceChannelList *qmp_query_spice_channels(void)
 {
-    QDict *client;
-    Monitor *mon = opaque;
-
-    client = qobject_to_qdict(obj);
-    monitor_printf(mon, "Channel:\n");
-    monitor_printf(mon, "     address: %s:%s%s\n",
-                   qdict_get_str(client, "host"),
-                   qdict_get_str(client, "port"),
-                   qdict_get_bool(client, "tls") ? " [tls]" : "");
-    monitor_printf(mon, "     session: %" PRId64 "\n",
-                   qdict_get_int(client, "connection-id"));
-    monitor_printf(mon, "     channel: %d:%d\n",
-                   (int)qdict_get_int(client, "channel-type"),
-                   (int)qdict_get_int(client, "channel-id"));
-}
+    SpiceChannelList *cur_item = NULL, *head = NULL;
+    ChannelList *item;
 
-void do_info_spice_print(Monitor *mon, const QObject *data)
-{
-    QDict *server;
-    QList *channels;
-    const char *host;
-    int port;
-
-    server = qobject_to_qdict(data);
-    if (qdict_get_bool(server, "enabled") == 0) {
-        monitor_printf(mon, "Server: disabled\n");
-        return;
-    }
+    QTAILQ_FOREACH(item, &channel_list, link) {
+        SpiceChannelList *chan;
+        char host[NI_MAXHOST], port[NI_MAXSERV];
+        struct sockaddr *paddr;
+        socklen_t plen;
+
+        chan = g_malloc0(sizeof(*chan));
+        chan->value = g_malloc0(sizeof(*chan->value));
+
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+        if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+            paddr = (struct sockaddr *)&item->info->paddr_ext;
+            plen = item->info->plen_ext;
+        } else {
+#endif
+            paddr = &item->info->paddr;
+            plen = item->info->plen;
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+        }
+#endif
 
-    monitor_printf(mon, "Server:\n");
-    host = qdict_get_str(server, "host");
-    port = qdict_get_try_int(server, "port", -1);
-    if (port != -1) {
-        monitor_printf(mon, "     address: %s:%d\n", host, port);
-    }
-    port = qdict_get_try_int(server, "tls-port", -1);
-    if (port != -1) {
-        monitor_printf(mon, "     address: %s:%d [tls]\n", host, port);
+        getnameinfo(paddr, plen,
+                    host, sizeof(host), port, sizeof(port),
+                    NI_NUMERICHOST | NI_NUMERICSERV);
+        chan->value->host = g_strdup(host);
+        chan->value->port = g_strdup(port);
+        chan->value->family = g_strdup(inet_strfamily(paddr->sa_family));
+
+        chan->value->connection_id = item->info->connection_id;
+        chan->value->channel_type = item->info->type;
+        chan->value->channel_id = item->info->id;
+        chan->value->tls = item->info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
+
+       /* XXX: waiting for the qapi to support GSList */
+        if (!cur_item) {
+            head = cur_item = chan;
+        } else {
+            cur_item->next = chan;
+            cur_item = chan;
+        }
     }
-    monitor_printf(mon, "        auth: %s\n", qdict_get_str(server, "auth"));
-    monitor_printf(mon, "    compiled: %s\n",
-                   qdict_get_str(server, "compiled-version"));
 
-    channels = qdict_get_qlist(server, "channels");
-    if (qlist_empty(channels)) {
-        monitor_printf(mon, "Channels: none\n");
-    } else {
-        qlist_iter(channels, info_spice_iter, mon);
-    }
+    return head;
 }
 
-void do_info_spice(Monitor *mon, QObject **ret_data)
+SpiceInfo *qmp_query_spice(Error **errp)
 {
     QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
-    QDict *server;
-    QList *clist;
-    const char *addr;
     int port, tls_port;
+    const char *addr;
+    SpiceInfo *info;
     char version_string[20]; /* 12 = |255.255.255\0| is the max */
 
+    info = g_malloc0(sizeof(*info));
+
     if (!spice_server || !opts) {
-        *ret_data = qobject_from_jsonf("{ 'enabled': false }");
-        return;
+        info->enabled = false;
+        return info;
     }
 
+    info->enabled = true;
+
     addr = qemu_opt_get(opts, "addr");
     port = qemu_opt_get_number(opts, "port", 0);
     tls_port = qemu_opt_get_number(opts, "tls-port", 0);
-    clist = channel_list_get();
 
-    server = qdict_new();
-    qdict_put(server, "enabled", qbool_from_int(true));
-    qdict_put(server, "auth", qstring_from_str(auth));
-    qdict_put(server, "host", qstring_from_str(addr ? addr : "0.0.0.0"));
+    info->has_auth = true;
+    info->auth = g_strdup(auth);
+
+    info->has_host = true;
+    info->host = g_strdup(addr ? addr : "0.0.0.0");
+
+    info->has_compiled_version = true;
     snprintf(version_string, sizeof(version_string), "%d.%d.%d",
              (SPICE_SERVER_VERSION & 0xff0000) >> 16,
              (SPICE_SERVER_VERSION & 0xff00) >> 8,
              SPICE_SERVER_VERSION & 0xff);
-    qdict_put(server, "compiled-version", qstring_from_str(version_string));
+    info->compiled_version = g_strdup(version_string);
+
     if (port) {
-        qdict_put(server, "port", qint_from_int(port));
+        info->has_port = true;
+        info->port = port;
     }
     if (tls_port) {
-        qdict_put(server, "tls-port", qint_from_int(tls_port));
-    }
-    if (clist) {
-        qdict_put(server, "channels", clist);
+        info->has_tls_port = true;
+        info->tls_port = tls_port;
     }
 
-    *ret_data = QOBJECT(server);
+    /* for compatibility with the original command */
+    info->has_channels = true;
+    info->channels = qmp_query_spice_channels();
+
+    return info;
 }
 
 static void migration_state_notifier(Notifier *notifier, void *data)
@@ -486,14 +477,12 @@ static void migration_state_notifier(Notifier *notifier, void *data)
         spice_server_migrate_start(spice_server);
 #endif
     } else if (migration_has_finished(s)) {
-#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
 #ifndef SPICE_INTERFACE_MIGRATION
         spice_server_migrate_switch(spice_server);
 #else
         spice_server_migrate_end(spice_server, true);
     } else if (migration_has_failed(s)) {
         spice_server_migrate_end(spice_server, false);
-#endif
 #endif
     }
 }
@@ -522,6 +511,12 @@ static int add_channel(const char *name, const char *value, void *opaque)
     int rc;
 
     if (strcmp(name, "tls-channel") == 0) {
+        int *tls_port = opaque;
+        if (!*tls_port) {
+            error_report("spice: tried to setup tls-channel"
+                         " without specifying a TLS port");
+            exit(1);
+        }
         security = SPICE_CHANNEL_SECURITY_SSL;
     }
     if (strcmp(name, "plaintext-channel") == 0) {
@@ -536,7 +531,7 @@ static int add_channel(const char *name, const char *value, void *opaque)
         rc = spice_server_set_channel_security(spice_server, value, security);
     }
     if (rc != 0) {
-        fprintf(stderr, "spice: failed to set channel security for %s\n", value);
+        error_report("spice: failed to set channel security for %s", value);
         exit(1);
     }
     return 0;
@@ -564,15 +559,15 @@ void qemu_spice_init(void)
     port = qemu_opt_get_number(opts, "port", 0);
     tls_port = qemu_opt_get_number(opts, "tls-port", 0);
     if (!port && !tls_port) {
-        fprintf(stderr, "neither port nor tls-port specified for spice.");
+        error_report("neither port nor tls-port specified for spice");
         exit(1);
     }
     if (port < 0 || port > 65535) {
-        fprintf(stderr, "spice port is out of range");
+        error_report("spice port is out of range");
         exit(1);
     }
     if (tls_port < 0 || tls_port > 65535) {
-        fprintf(stderr, "spice tls-port is out of range");
+        error_report("spice tls-port is out of range");
         exit(1);
     }
     password = qemu_opt_get(opts, "password");
@@ -642,11 +637,11 @@ void qemu_spice_init(void)
 #if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */
         if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 ||
             spice_server_set_sasl(spice_server, 1) == -1) {
-            fprintf(stderr, "spice: failed to enable sasl\n");
+            error_report("spice: failed to enable sasl");
             exit(1);
         }
 #else
-        fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n");
+        error_report("spice: sasl is not available (spice >= 0.9 required)");
         exit(1);
 #endif
     }
@@ -655,11 +650,9 @@ void qemu_spice_init(void)
         spice_server_set_noauth(spice_server);
     }
 
-#if SPICE_SERVER_VERSION >= 0x000801
     if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) {
         spice_server_set_agent_copypaste(spice_server, false);
     }
-#endif
 
     compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
     str = qemu_opt_get(opts, "image-compression");
@@ -693,10 +686,10 @@ void qemu_spice_init(void)
     spice_server_set_playback_compression
         (spice_server, qemu_opt_get_bool(opts, "playback-compression", 1));
 
-    qemu_opt_foreach(opts, add_channel, NULL, 0);
+    qemu_opt_foreach(opts, add_channel, &tls_port, 0);
 
     if (0 != spice_server_init(spice_server, &core_interface)) {
-        fprintf(stderr, "failed to initialize spice server");
+        error_report("failed to initialize spice server");
         exit(1);
     };
     using_spice = 1;
@@ -721,7 +714,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
 {
     if (!spice_server) {
         if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
-            fprintf(stderr, "Oops: spice configured but not active\n");
+            error_report("Oops: spice configured but not active");
             exit(1);
         }
         /*
@@ -770,14 +763,28 @@ int qemu_spice_set_pw_expire(time_t expires)
     return qemu_spice_set_ticket(false, false);
 }
 
+int qemu_spice_display_add_client(int csock, int skipauth, int tls)
+{
+#if SPICE_SERVER_VERSION >= 0x000a01
+    if (tls) {
+        return spice_server_add_ssl_client(spice_server, csock, skipauth);
+    } else {
+        return spice_server_add_client(spice_server, csock, skipauth);
+    }
+#else
+    return -1;
+#endif
+}
+
 static void spice_register_config(void)
 {
     qemu_add_opts(&qemu_spice_opts);
 }
 machine_init(spice_register_config);
 
-static void spice_initialize(void)
+static void spice_register_types(void)
 {
     qemu_spice_init();
 }
-device_init(spice_initialize);
+
+type_init(spice_register_types)
This page took 0.037445 seconds and 4 git commands to generate.