Blob Blame History Raw
From 37beb4aa5dd10764a492d76822f2d7ec04b33fd0 Mon Sep 17 00:00:00 2001
From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Fri, 6 Mar 2009 20:27:05 +0000
Subject: [PATCH] Enhance 'info vnc' monitor output ("Daniel P. Berrange")

The current 'info vnc' monitor output just displays the VNC server address
as provided by the -vnc command line flag. This isn't particularly useful
since it doesn't tell you what VNC is actually listening on. eg, if you
use '-vnc :1' it is useful to know whether this translated to '0.0.0.0:5901'
or chose IPv6 ':::5901'.  It is also useful to know the address of the
client that is currently connected. It is also useful to know the active
authentication (if any).

This patch tweaks the monitor output to look like:

   (qemu) info vnc
    Server:
         address: 0.0.0.0:5902
            auth: vencrypt+x509
    Client: none

And when 2 clients are connected

   (qemu) info vnc
    Server:
         address: 0.0.0.0:5902
            auth: vencrypt+x509
    Client:
         address: 10.33.6.67:38621
    Client:
         address: 10.33.6.63:38620

More data will be added to this later in the patch series...

The 'addr_to_string' helper method in this patch is overly generic
for the needs of this patch alone. This is because it will be re-used
by the later SASL patches in this series, where the flexibility is
important.

(cherry picked from commit 1ff7df1a848044f58d0f3540f1447db4bb1d2d20)

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Fedora-patch: 02-vnc-monitor-info.patch
---
 vnc.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 128 insertions(+), 11 deletions(-)

diff --git a/vnc.c b/vnc.c
index 9fa0f82..7853635 100644
--- a/vnc.c
+++ b/vnc.c
@@ -166,19 +166,136 @@ struct VncState
 static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
 
+static char *addr_to_string(const char *format,
+			    struct sockaddr_storage *sa,
+			    socklen_t salen) {
+    char *addr;
+    char host[NI_MAXHOST];
+    char serv[NI_MAXSERV];
+    int err;
+
+    if ((err = getnameinfo((struct sockaddr *)sa, salen,
+			   host, sizeof(host),
+			   serv, sizeof(serv),
+			   NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
+	VNC_DEBUG("Cannot resolve address %d: %s\n",
+		  err, gai_strerror(err));
+	return NULL;
+    }
+
+    if (asprintf(&addr, format, host, serv) < 0)
+	return NULL;
+
+    return addr;
+}
+
+static char *vnc_socket_local_addr(const char *format, int fd) {
+    struct sockaddr_storage sa;
+    socklen_t salen;
+
+    salen = sizeof(sa);
+    if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0)
+	return NULL;
+
+    return addr_to_string(format, &sa, salen);
+}
+
+static char *vnc_socket_remote_addr(const char *format, int fd) {
+    struct sockaddr_storage sa;
+    socklen_t salen;
+
+    salen = sizeof(sa);
+    if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0)
+	return NULL;
+
+    return addr_to_string(format, &sa, salen);
+}
+
+static const char *vnc_auth_name(VncDisplay *vd) {
+    switch (vd->auth) {
+    case VNC_AUTH_INVALID:
+	return "invalid";
+    case VNC_AUTH_NONE:
+	return "none";
+    case VNC_AUTH_VNC:
+	return "vnc";
+    case VNC_AUTH_RA2:
+	return "ra2";
+    case VNC_AUTH_RA2NE:
+	return "ra2ne";
+    case VNC_AUTH_TIGHT:
+	return "tight";
+    case VNC_AUTH_ULTRA:
+	return "ultra";
+    case VNC_AUTH_TLS:
+	return "tls";
+    case VNC_AUTH_VENCRYPT:
+#ifdef CONFIG_VNC_TLS
+	switch (vd->subauth) {
+	case VNC_AUTH_VENCRYPT_PLAIN:
+	    return "vencrypt+plain";
+	case VNC_AUTH_VENCRYPT_TLSNONE:
+	    return "vencrypt+tls+none";
+	case VNC_AUTH_VENCRYPT_TLSVNC:
+	    return "vencrypt+tls+vnc";
+	case VNC_AUTH_VENCRYPT_TLSPLAIN:
+	    return "vencrypt+tls+plain";
+	case VNC_AUTH_VENCRYPT_X509NONE:
+	    return "vencrypt+x509+none";
+	case VNC_AUTH_VENCRYPT_X509VNC:
+	    return "vencrypt+x509+vnc";
+	case VNC_AUTH_VENCRYPT_X509PLAIN:
+	    return "vencrypt+x509+plain";
+	default:
+	    return "vencrypt";
+	}
+#else
+	return "vencrypt";
+#endif
+    }
+    return "unknown";
+}
+
+#define VNC_SOCKET_FORMAT_PRETTY "local %s:%s"
+
+static void do_info_vnc_client(VncState *client)
+{
+    char *clientAddr =
+	vnc_socket_remote_addr("     address: %s:%s\n",
+			       client->csock);
+    if (!clientAddr)
+	return;
+
+    term_puts("Client:\n");
+    term_puts(clientAddr);
+    free(clientAddr);
+}
+
 void do_info_vnc(void)
 {
-    if (vnc_display == NULL || vnc_display->display == NULL)
-	term_printf("VNC server disabled\n");
-    else {
-	term_printf("VNC server active on: ");
-	term_print_filename(vnc_display->display);
-	term_printf("\n");
-
-	if (vnc_display->clients == NULL)
-	    term_printf("No client connected\n");
-	else
-	    term_printf("Client connected\n");
+    if (vnc_display == NULL || vnc_display->display == NULL) {
+	term_printf("Server: disabled\n");
+    } else {
+	char *serverAddr = vnc_socket_local_addr("     address: %s:%s\n",
+						 vnc_display->lsock);
+
+	if (!serverAddr)
+	    return;
+
+	term_puts("Server:\n");
+	term_puts(serverAddr);
+	free(serverAddr);
+	term_printf("        auth: %s\n", vnc_auth_name(vnc_display));
+
+	if (vnc_display->clients) {
+	    VncState *client = vnc_display->clients;
+	    while (client) {
+		do_info_vnc_client(client);
+		client = client->next;
+	    }
+	} else {
+	    term_printf("Client: none\n");
+	}
     }
 }
 
-- 
1.6.2.5