Commit 3aa3eea310318553c853c07f78690a540f7ed94c
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. | ... | ... |
vnc.c
... | ... | @@ -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); | ... | ... |