Blob Blame History Raw
Index: qemu-kvm-0.10/qemu/vnc.c
===================================================================
--- qemu-kvm-0.10.orig/qemu/vnc.c
+++ qemu-kvm-0.10/qemu/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");
+	}
     }
 }