Commit 3aa3eea310318553c853c07f78690a540f7ed94c

Authored by balrog
1 parent 3d575329

Add VNC reverse connections, by Eddie Kohler.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3951 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 54 additions and 21 deletions
qemu-doc.texi
... ... @@ -421,21 +421,21 @@ syntax for the @var{display} is
421 421  
422 422 @table @code
423 423  
424   -@item @var{interface}:@var{d}
  424 +@item @var{host}:@var{d}
425 425  
426   -TCP connections will only be allowed from @var{interface} on display @var{d}.
427   -By convention the TCP port is 5900+@var{d}. Optionally, @var{interface} can
428   -be omitted in which case the server will bind to all interfaces.
  426 +TCP connections will only be allowed from @var{host} on display @var{d}.
  427 +By convention the TCP port is 5900+@var{d}. Optionally, @var{host} can
  428 +be omitted in which case the server will accept connections from any host.
429 429  
430   -@item @var{unix}:@var{path}
  430 +@item @code{unix}:@var{path}
431 431  
432 432 Connections will be allowed over UNIX domain sockets where @var{path} is the
433 433 location of a unix socket to listen for connections on.
434 434  
435 435 @item none
436 436  
437   -VNC is initialized by not started. The monitor @code{change} command can be used
438   -to later start the VNC server.
  437 +VNC is initialized but not started. The monitor @code{change} command
  438 +can be used to later start the VNC server.
439 439  
440 440 @end table
441 441  
... ... @@ -444,6 +444,13 @@ separated by commas. Valid options are
444 444  
445 445 @table @code
446 446  
  447 +@item reverse
  448 +
  449 +Connect to a listening VNC client via a ``reverse'' connection. The
  450 +client is specified by the @var{display}. For reverse network
  451 +connections (@var{host}:@var{d},@code{reverse}), the @var{d} argument
  452 +is a TCP port number, not a display number.
  453 +
447 454 @item password
448 455  
449 456 Require that password based authentication is used for client connections.
... ...
... ... @@ -1898,6 +1898,22 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
1898 1898 return 0;
1899 1899 }
1900 1900  
  1901 +static void vnc_connect(VncState *vs)
  1902 +{
  1903 + VNC_DEBUG("New client on socket %d\n", vs->csock);
  1904 + socket_set_nonblock(vs->csock);
  1905 + qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
  1906 + vnc_write(vs, "RFB 003.008\n", 12);
  1907 + vnc_flush(vs);
  1908 + vnc_read_when(vs, protocol_version, 12);
  1909 + memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
  1910 + memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
  1911 + vs->has_resize = 0;
  1912 + vs->has_hextile = 0;
  1913 + vs->ds->dpy_copy = NULL;
  1914 + vnc_update_client(vs);
  1915 +}
  1916 +
1901 1917 static void vnc_listen_read(void *opaque)
1902 1918 {
1903 1919 VncState *vs = opaque;
... ... @@ -1909,18 +1925,7 @@ static void vnc_listen_read(void *opaque)
1909 1925  
1910 1926 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1911 1927 if (vs->csock != -1) {
1912   - VNC_DEBUG("New client on socket %d\n", vs->csock);
1913   - socket_set_nonblock(vs->csock);
1914   - qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1915   - vnc_write(vs, "RFB 003.008\n", 12);
1916   - vnc_flush(vs);
1917   - vnc_read_when(vs, protocol_version, 12);
1918   - memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
1919   - memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
1920   - vs->has_resize = 0;
1921   - vs->has_hextile = 0;
1922   - vs->ds->dpy_copy = NULL;
1923   - vnc_update_client(vs);
  1928 + vnc_connect(vs);
1924 1929 }
1925 1930 }
1926 1931  
... ... @@ -2087,6 +2092,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
2087 2092 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2088 2093 const char *options;
2089 2094 int password = 0;
  2095 + int reverse = 0;
2090 2096 #if CONFIG_VNC_TLS
2091 2097 int tls = 0, x509 = 0;
2092 2098 #endif
... ... @@ -2103,6 +2109,8 @@ int vnc_display_open(DisplayState *ds, const char *display)
2103 2109 options++;
2104 2110 if (strncmp(options, "password", 8) == 0) {
2105 2111 password = 1; /* Require password auth */
  2112 + } else if (strncmp(options, "reverse", 7) == 0) {
  2113 + reverse = 1;
2106 2114 #if CONFIG_VNC_TLS
2107 2115 } else if (strncmp(options, "tls", 3) == 0) {
2108 2116 tls = 1; /* Require TLS */
... ... @@ -2196,7 +2204,9 @@ int vnc_display_open(DisplayState *ds, const char *display)
2196 2204 memset(uaddr.sun_path, 0, 108);
2197 2205 snprintf(uaddr.sun_path, 108, "%s", p);
2198 2206  
2199   - unlink(uaddr.sun_path);
  2207 + if (!reverse) {
  2208 + unlink(uaddr.sun_path);
  2209 + }
2200 2210 } else
2201 2211 #endif
2202 2212 {
... ... @@ -2210,7 +2220,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
2210 2220 return -1;
2211 2221 }
2212 2222  
2213   - iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
  2223 + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + (reverse ? 0 : 5900));
2214 2224  
2215 2225 vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
2216 2226 if (vs->lsock == -1) {
... ... @@ -2233,6 +2243,22 @@ int vnc_display_open(DisplayState *ds, const char *display)
2233 2243 }
2234 2244 }
2235 2245  
  2246 + if (reverse) {
  2247 + if (connect(vs->lsock, addr, addrlen) == -1) {
  2248 + fprintf(stderr, "Connection to VNC client failed\n");
  2249 + close(vs->lsock);
  2250 + vs->lsock = -1;
  2251 + free(vs->display);
  2252 + vs->display = NULL;
  2253 + return -1;
  2254 + } else {
  2255 + vs->csock = vs->lsock;
  2256 + vs->lsock = -1;
  2257 + vnc_connect(vs);
  2258 + return 0;
  2259 + }
  2260 + }
  2261 +
2236 2262 if (bind(vs->lsock, addr, addrlen) == -1) {
2237 2263 fprintf(stderr, "bind() failed\n");
2238 2264 close(vs->lsock);
... ...