Commit df887684 authored by Gerd Hoffmann's avatar Gerd Hoffmann
Browse files

monitor: add query-vnc-servers command



Add new query vnc qmp command, for the lack of better ideas just name it
"query-vnc-servers".  Changes over query-vnc:

 * It returns a list of vnc servers, so multiple vnc server instances
   are covered.
 * Each vnc server returns a list of server sockets.  Followup patch
   will use that to also report websockets.  In case we add support for
   multiple server sockets server sockets (to better support ipv4+ipv6
   dualstack) we can add them to the list too.

Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
parent 2d29a436
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -750,6 +750,63 @@
           '*family': 'NetworkAddressFamily',
           '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }

##
# @VncPriAuth:
#
# vnc primary authentication method.
#
# Since: 2.3
##
{ 'enum': 'VncPrimaryAuth',
  'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
            'tls', 'vencrypt', 'sasl' ] }

##
# @VncVencryptSubAuth:
#
# vnc sub authentication method with vencrypt.
#
# Since: 2.3
##
{ 'enum': 'VncVencryptSubAuth',
  'data': [ 'plain',
            'tls-none',  'x509-none',
            'tls-vnc',   'x509-vnc',
            'tls-plain', 'x509-plain',
            'tls-sasl',  'x509-sasl' ] }

##
# @VncInfo2:
#
# Information about a vnc server
#
# @id: vnc server name.
#
# @server: A list of @VncBasincInfo describing all listening sockets.
#          The list can be empty (in case the vnc server is disabled).
#          It also may have multiple entries: normal + websocket,
#          possibly also ipv4 + ipv6 in the future.
#
# @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
#
# @vencrypt: #optional The vencrypt sub authentication type used by the server,
#            only specified in case auth == vencrypt.
#
# @display: #optional The display device the vnc server is linked to.
#
# Since: 2.3
##
{ 'type': 'VncInfo2',
  'data': { 'id'        : 'str',
            'server'    : ['VncBasicInfo'],
            'clients'   : ['VncClientInfo'],
            'auth'      : 'VncPrimaryAuth',
            '*vencrypt' : 'VncVencryptSubAuth',
            '*display'  : 'str' } }

##
# @query-vnc:
#
@@ -761,6 +818,17 @@
##
{ 'command': 'query-vnc', 'returns': 'VncInfo' }

##
# @query-vnc-servers:
#
# Returns a list of vnc servers.  The list can be empty.
#
# Returns: a list of @VncInfo2
#
# Since: 2.3
##
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'] }

##
# @SpiceBasicInfo
#
+5 −0
Original line number Diff line number Diff line
@@ -2867,6 +2867,11 @@ EQMP
        .args_type  = "",
        .mhandler.cmd_new = qmp_marshal_input_query_vnc,
    },
    {
        .name       = "query-vnc-servers",
        .args_type  = "",
        .mhandler.cmd_new = qmp_marshal_input_query_vnc_servers,
    },

SQMP
query-spice
+133 −0
Original line number Diff line number Diff line
@@ -456,6 +456,139 @@ out_error:
    return NULL;
}

static VncBasicInfoList *qmp_query_server_entry(int socket,
                                                VncBasicInfoList *prev)
{
    VncBasicInfoList *list;
    VncBasicInfo *info;
    struct sockaddr_storage sa;
    socklen_t salen = sizeof(sa);
    char host[NI_MAXHOST];
    char serv[NI_MAXSERV];

    if (getsockname(socket, (struct sockaddr *)&sa, &salen) < 0 ||
        getnameinfo((struct sockaddr *)&sa, salen,
                    host, sizeof(host), serv, sizeof(serv),
                    NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
        return prev;
    }

    info = g_new0(VncBasicInfo, 1);
    info->host = g_strdup(host);
    info->service = g_strdup(serv);
    info->family = inet_netfamily(sa.ss_family);

    list = g_new0(VncBasicInfoList, 1);
    list->value = info;
    list->next = prev;
    return list;
}

static void qmp_query_auth(VncDisplay *vd, VncInfo2 *info)
{
    switch (vd->auth) {
    case VNC_AUTH_VNC:
        info->auth = VNC_PRIMARY_AUTH_VNC;
        break;
    case VNC_AUTH_RA2:
        info->auth = VNC_PRIMARY_AUTH_RA2;
        break;
    case VNC_AUTH_RA2NE:
        info->auth = VNC_PRIMARY_AUTH_RA2NE;
        break;
    case VNC_AUTH_TIGHT:
        info->auth = VNC_PRIMARY_AUTH_TIGHT;
        break;
    case VNC_AUTH_ULTRA:
        info->auth = VNC_PRIMARY_AUTH_ULTRA;
        break;
    case VNC_AUTH_TLS:
        info->auth = VNC_PRIMARY_AUTH_TLS;
        break;
    case VNC_AUTH_VENCRYPT:
        info->auth = VNC_PRIMARY_AUTH_VENCRYPT;
#ifdef CONFIG_VNC_TLS
        info->has_vencrypt = true;
        switch (vd->subauth) {
        case VNC_AUTH_VENCRYPT_PLAIN:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN;
            break;
        case VNC_AUTH_VENCRYPT_TLSNONE:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE;
            break;
        case VNC_AUTH_VENCRYPT_TLSVNC:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC;
            break;
        case VNC_AUTH_VENCRYPT_TLSPLAIN:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN;
            break;
        case VNC_AUTH_VENCRYPT_X509NONE:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE;
            break;
        case VNC_AUTH_VENCRYPT_X509VNC:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC;
            break;
        case VNC_AUTH_VENCRYPT_X509PLAIN:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN;
            break;
        case VNC_AUTH_VENCRYPT_TLSSASL:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL;
            break;
        case VNC_AUTH_VENCRYPT_X509SASL:
            info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL;
            break;
        default:
            info->has_vencrypt = false;
            break;
        }
#endif
        break;
    case VNC_AUTH_SASL:
        info->auth = VNC_PRIMARY_AUTH_SASL;
        break;
    case VNC_AUTH_NONE:
    default:
        info->auth = VNC_PRIMARY_AUTH_NONE;
        break;
    }
}

VncInfo2List *qmp_query_vnc_servers(Error **errp)
{
    VncInfo2List *item, *prev = NULL;
    VncInfo2 *info;
    VncDisplay *vd;
    DeviceState *dev;

    QTAILQ_FOREACH(vd, &vnc_displays, next) {
        info = g_new0(VncInfo2, 1);
        info->id = g_strdup(vd->id);
        info->clients = qmp_query_client_list(vd);
        qmp_query_auth(vd, info);
        if (vd->dcl.con) {
            dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con),
                                                  "device", NULL));
            info->has_display = true;
            info->display = g_strdup(dev->id);
        }
        if (vd->lsock != -1) {
            info->server = qmp_query_server_entry(vd->lsock,
                                                  info->server);
        }
#ifdef CONFIG_VNC_WS
        if (vd->lwebsock != -1) {
            /* TODO */
        }
#endif

        item = g_new0(VncInfo2List, 1);
        item->value = info;
        item->next = prev;
        prev = item;
    }
    return prev;
}

/* TODO
   1) Get the queue working for IO.
   2) there is some weirdness when using the -S option (the screen is grey