x11vnc: exit(1) for -connect_or_exit failure, quiet query mode for grab_state, pointer_pos, etc. ipv6 support. STUNNEL_LISTEN for particular interface. -input_eagerly in addition to -allinput. quiet Xinerama message.

pull/1/head
runge 14 years ago
parent 5c53ccbbe9
commit 2a8ba97ec5

@ -1,3 +1,11 @@
2010-04-09 Karl Runge <runge@karlrunge.com>
* classes/ssl: debugging and workarounds for java viewer
* x11vnc/misc: sync ssvnc, improve util scripts.
* x11vnc: exit(1) for -connect_or_exit failure, quiet query
mode for grab_state, etc. ipv6 support. STUNNEL_LISTEN for
particular interface. -input_eagerly in addition to -allinput.
quiet Xinerama message.
2010-03-20 Karl Runge <runge@karlrunge.com> 2010-03-20 Karl Runge <runge@karlrunge.com>
* classes/ssl: Many improvements to Java SSL applet, onetimekey * classes/ssl: Many improvements to Java SSL applet, onetimekey
serverCert param, debugging printout, user dialogs, catch serverCert param, debugging printout, user dialogs, catch

File diff suppressed because it is too large Load Diff

@ -92,6 +92,7 @@ void send_client_info(char *str);
void adjust_grabs(int grab, int quiet); void adjust_grabs(int grab, int quiet);
void check_new_clients(void); void check_new_clients(void);
int accept_client(rfbClientPtr client); int accept_client(rfbClientPtr client);
void check_ipv6_listen(long usec);
int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input,
int len, FILE *output); int len, FILE *output);
int check_access(char *addr); int check_access(char *addr);
@ -168,6 +169,7 @@ char *list_clients(void) {
iter = rfbGetClientIterator(screen); iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) { while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData; ClientData *cd = (ClientData *) cl->clientData;
char *tmp_host, *p;
if (! cd) { if (! cd) {
continue; continue;
@ -177,7 +179,13 @@ char *list_clients(void) {
} }
sprintf(tmp, "0x%x:", cd->uid); sprintf(tmp, "0x%x:", cd->uid);
strcat(list, tmp); strcat(list, tmp);
strcat(list, cl->host); p = tmp_host = strdup(cl->host);
while (*p) {
if (*p == ':') *p = '#';
p++;
}
strcat(list, tmp_host);
free(tmp_host);
strcat(list, ":"); strcat(list, ":");
sprintf(tmp, "%d:", cd->client_port); sprintf(tmp, "%d:", cd->client_port);
strcat(list, tmp); strcat(list, tmp);
@ -197,7 +205,13 @@ char *list_clients(void) {
strcat(list, cd->unixname); strcat(list, cd->unixname);
} }
strcat(list, ":"); strcat(list, ":");
strcat(list, cd->hostname); p = tmp_host = strdup(cd->hostname);
while (*p) {
if (*p == ':') *p = '#';
p++;
}
strcat(list, tmp_host);
free(tmp_host);
strcat(list, ":"); strcat(list, ":");
strcat(list, cd->input); strcat(list, cd->input);
strcat(list, ":"); strcat(list, ":");
@ -292,7 +306,9 @@ static rfbClientPtr *client_match(char *str) {
port = 5500 + port; port = 5500 + port;
} }
} }
if (! dotted_ip(str)) { if (ipv6_ip(str)) {
;
} else if (! dotted_ip(str)) {
char *orig = rstr; char *orig = rstr;
rstr = host2ip(rstr); rstr = host2ip(rstr);
free(orig); free(orig);
@ -891,13 +907,16 @@ void client_gone(rfbClientPtr client) {
client->state == RFB_AUTHENTICATION || client->state == RFB_AUTHENTICATION ||
client->state == RFB_INITIALISATION) && accepted_client) { client->state == RFB_INITIALISATION) && accepted_client) {
rfbLog("connect_once: invalid password or early " rfbLog("connect_once: invalid password or early "
"disconnect.\n"); "disconnect. %d\n", client->state);
rfbLog("connect_once: waiting for next connection.\n"); rfbLog("connect_once: waiting for next connection.\n");
accepted_client--; accepted_client--;
if (accepted_client < 0) { if (accepted_client < 0) {
accepted_client = 0; accepted_client = 0;
} }
CLIENT_UNLOCK; CLIENT_UNLOCK;
if (connect_or_exit) {
clean_up_exit(1);
}
return; return;
} }
if (shared && client_count > 0) { if (shared && client_count > 0) {
@ -913,7 +932,11 @@ void client_gone(rfbClientPtr client) {
kill(gui_pid, SIGTERM); kill(gui_pid, SIGTERM);
} }
CLIENT_UNLOCK; CLIENT_UNLOCK;
clean_up_exit(0); if (connect_or_exit) {
clean_up_exit(1);
} else {
clean_up_exit(0);
}
} }
#ifdef MACOSX #ifdef MACOSX
if (macosx_console && client_count == 0) { if (macosx_console && client_count == 0) {
@ -1042,7 +1065,9 @@ int check_access(char *addr) {
p = strtok(NULL, ", \t\n\r"); p = strtok(NULL, ", \t\n\r");
continue; continue;
} }
if (! dotted_ip(p)) { if (ipv6_ip(p)) {
chk = p;
} else if (! dotted_ip(p)) {
r = host2ip(p); r = host2ip(p);
if (r == NULL || *r == '\0') { if (r == NULL || *r == '\0') {
rfbLog("check_access: bad lookup \"%s\"\n", p); rfbLog("check_access: bad lookup \"%s\"\n", p);
@ -1054,26 +1079,37 @@ int check_access(char *addr) {
} else { } else {
chk = p; chk = p;
} }
if (getenv("X11VNC_DEBUG_ACCESS")) fprintf(stderr, "chk: %s part: %s addr: %s\n", chk, p, addr);
q = strstr(addr, chk); q = strstr(addr, chk);
if (chk[strlen(chk)-1] != '.') { if (ipv6_ip(addr)) {
if (!strcmp(chk, "localhost") && !strcmp(addr, "::1")) {
rfbLog("check_access: client addr %s is local.\n", addr);
allowed = 1;
} else if (!strcmp(chk, "::1") && !strcmp(addr, "::1")) {
rfbLog("check_access: client addr %s is local.\n", addr);
allowed = 1;
} else if (!strcmp(chk, "127.0.0.1") && !strcmp(addr, "::1")) {
/* this if for host2ip("localhost") */
rfbLog("check_access: client addr %s is local.\n", addr);
allowed = 1;
} else if (q == addr) {
rfbLog("check_access: client %s matches pattern %s\n", addr, chk);
allowed = 1;
}
} else if (chk[strlen(chk)-1] != '.') {
if (!strcmp(addr, chk)) { if (!strcmp(addr, chk)) {
if (chk != p) { if (chk != p) {
rfbLog("check_access: client %s " rfbLog("check_access: client %s " "matches host %s=%s\n", addr, chk, p);
"matches host %s=%s\n", addr,
chk, p);
} else { } else {
rfbLog("check_access: client %s " rfbLog("check_access: client %s " "matches host %s\n", addr, chk);
"matches host %s\n", addr, chk);
} }
allowed = 1; allowed = 1;
} else if(!strcmp(chk, "localhost") && } else if(!strcmp(chk, "localhost") && !strcmp(addr, "127.0.0.1")) {
!strcmp(addr, "127.0.0.1")) {
allowed = 1; allowed = 1;
} }
} else if (q == addr) { } else if (q == addr) {
rfbLog("check_access: client %s matches pattern %s\n", rfbLog("check_access: client %s matches pattern %s\n", addr, chk);
addr, chk);
allowed = 1; allowed = 1;
} }
p = strtok(NULL, ", \t\n\r"); p = strtok(NULL, ", \t\n\r");
@ -1691,6 +1727,121 @@ int accept_client(rfbClientPtr client) {
/* return 0; NOTREACHED */ /* return 0; NOTREACHED */
} }
void check_ipv6_listen(long usec) {
#if X11VNC_IPV6
fd_set fds;
struct timeval tv;
int nfds, csock = -1, one = 1;
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof(addr);
rfbClientPtr cl;
int nmax = 0;
char *name;
if (!ipv6_listen || noipv6) {
return;
}
if (ipv6_listen_fd < 0 && ipv6_http_fd < 0) {
return;
}
FD_ZERO(&fds);
if (ipv6_listen_fd >= 0) {
FD_SET(ipv6_listen_fd, &fds);
nmax = ipv6_listen_fd;
}
if (ipv6_http_fd >= 0 && screen->httpSock < 0) {
FD_SET(ipv6_http_fd, &fds);
if (ipv6_http_fd > nmax) {
nmax = ipv6_http_fd;
}
}
tv.tv_sec = 0;
tv.tv_usec = 0;
nfds = select(nmax+1, &fds, NULL, NULL, &tv);
if (nfds <= 0) {
return;
}
if (ipv6_listen_fd >= 0 && FD_ISSET(ipv6_listen_fd, &fds)) {
csock = accept(ipv6_listen_fd, (struct sockaddr *)&addr, &addrlen);
if (csock < 0) {
rfbLogPerror("check_ipv6_listen: accept");
goto err1;
}
if (fcntl(csock, F_SETFL, O_NONBLOCK) < 0) {
rfbLogPerror("check_ipv6_listen: fcntl");
close(csock);
goto err1;
}
if (setsockopt(csock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
rfbLogPerror("check_ipv6_listen: setsockopt");
close(csock);
goto err1;
}
name = ipv6_getipaddr((struct sockaddr *) &addr, addrlen);
ipv6_client_ip_str = name;
cl = rfbNewClient(screen, csock);
ipv6_client_ip_str = NULL;
if (cl == NULL) {
close(csock);
goto err1;
}
if (name) {
if (cl->host) {
free(cl->host);
}
cl->host = name;
rfbLog("ipv6 client: %s\n", name);
}
}
err1:
if (ipv6_http_fd >= 0 && FD_ISSET(ipv6_http_fd, &fds)) {
csock = accept(ipv6_http_fd, (struct sockaddr *)&addr, &addrlen);
if (csock < 0) {
rfbLogPerror("check_ipv6_listen: accept");
return;
}
if (fcntl(csock, F_SETFL, O_NONBLOCK) < 0) {
rfbLogPerror("check_ipv6_listen: fcntl");
close(csock);
return;
}
if (setsockopt(csock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
rfbLogPerror("check_ipv6_listen: setsockopt");
close(csock);
return;
}
rfbLog("check_ipv6_listen: setting httpSock to %d\n", csock);
screen->httpSock = csock;
if (screen->httpListenSock < 0) {
/* this may not always work... */
int save = screen->httpListenSock;
screen->httpListenSock = ipv6_http_fd;
rfbLog("check_ipv6_listen: no httpListenSock, calling rfbHttpCheckFds()\n");
rfbHttpCheckFds(screen);
screen->httpListenSock = save;
}
}
#else
if (usec) {}
#endif
}
/* /*
* For the -connect <file> option: periodically read the file looking for * For the -connect <file> option: periodically read the file looking for
* a connect string. If one is found set client_connect to it. * a connect string. If one is found set client_connect to it.
@ -2093,7 +2244,7 @@ static int pconnect(int psock, char *host, int port, int type, char *http_path,
} }
if (newhost && newport > 0) { if (newhost && newport > 0) {
rfbLog("proxy GET reconnect to: %s:%d\n", newhost, newport); rfbLog("proxy GET reconnect to: %s:%d\n", newhost, newport);
pxy_get_sock = rfbConnectToTcpAddr(newhost, newport); pxy_get_sock = connect_tcp(newhost, newport);
} }
} }
free(req); free(req);
@ -2263,10 +2414,10 @@ static int proxy_connect(char *host, int port) {
psock = -1; psock = -1;
goto pxy_clean; goto pxy_clean;
} }
psock = rfbConnectToTcpAddr("localhost", sport); psock = connect_tcp("localhost", sport);
} else { } else {
psock = rfbConnectToTcpAddr(pxy_h[0], pxy_p[0]); psock = connect_tcp(pxy_h[0], pxy_p[0]);
} }
if (psock < 0) { if (psock < 0) {
@ -2462,7 +2613,7 @@ static int do_reverse_connect(char *str_in) {
host[len] = '\0'; host[len] = '\0';
/* extract port, if any */ /* extract port, if any */
if ((p = strchr(host, ':')) != NULL) { if ((p = strrchr(host, ':')) != NULL) {
rport = atoi(p+1); rport = atoi(p+1);
if (rport < 0) { if (rport < 0) {
rport = -rport; rport = -rport;
@ -2472,12 +2623,17 @@ static int do_reverse_connect(char *str_in) {
*p = '\0'; *p = '\0';
} }
if (ipv6_client_ip_str) {
free(ipv6_client_ip_str);
ipv6_client_ip_str = NULL;
}
if (use_openssl) { if (use_openssl) {
int vncsock; int vncsock;
if (connect_proxy) { if (connect_proxy) {
vncsock = proxy_connect(host, rport); vncsock = proxy_connect(host, rport);
} else { } else {
vncsock = rfbConnectToTcpAddr(host, rport); vncsock = connect_tcp(host, rport);
} }
if (vncsock < 0) { if (vncsock < 0) {
rfbLog("reverse_connect: failed to connect to: %s\n", str); rfbLog("reverse_connect: failed to connect to: %s\n", str);
@ -2488,7 +2644,7 @@ static int do_reverse_connect(char *str_in) {
free(prestring); free(prestring);
} }
/* XXX use header */ /* XXX use header */
#define OPENSSL_REVERSE 4 #define OPENSSL_REVERSE 6
openssl_init(1); openssl_init(1);
if (first_conn_timeout > 0) { if (first_conn_timeout > 0) {
@ -2560,7 +2716,7 @@ static int do_reverse_connect(char *str_in) {
return 0; return 0;
} }
} else if (prestring != NULL) { } else if (prestring != NULL) {
int sock = rfbConnectToTcpAddr(host, rport); int sock = connect_tcp(host, rport);
if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);} if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);}
if (sock >= 0) { if (sock >= 0) {
write(sock, prestring, prestring_len); write(sock, prestring, prestring_len);
@ -2571,6 +2727,12 @@ static int do_reverse_connect(char *str_in) {
} }
} else { } else {
cl = rfbReverseConnection(screen, host, rport); cl = rfbReverseConnection(screen, host, rport);
if (cl == NULL) {
int sock = connect_tcp(host, rport);
if (sock >= 0) {
cl = create_new_client(sock, 1);
}
}
if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);} if (set_alarm) {alarm(0); signal(SIGALRM, SIG_DFL);}
if (cl != NULL && use_threads) { if (cl != NULL && use_threads) {
cl->onHold = FALSE; cl->onHold = FALSE;
@ -2580,6 +2742,12 @@ static int do_reverse_connect(char *str_in) {
free(host); free(host);
if (ipv6_client_ip_str) {
free(ipv6_client_ip_str);
ipv6_client_ip_str = NULL;
}
if (cl == NULL) { if (cl == NULL) {
if (quiet && connect_or_exit) { if (quiet && connect_or_exit) {
rfbLogEnable(1); rfbLogEnable(1);
@ -2699,7 +2867,7 @@ void reverse_connect(char *str) {
rfbLog("killing gui_pid %d\n", gui_pid); rfbLog("killing gui_pid %d\n", gui_pid);
kill(gui_pid, SIGTERM); kill(gui_pid, SIGTERM);
} }
clean_up_exit(0); clean_up_exit(1);
} }
if (xrandr || xrandr_maybe) { if (xrandr || xrandr_maybe) {
check_xrandr_event("reverse_connect1"); check_xrandr_event("reverse_connect1");
@ -2768,7 +2936,7 @@ void reverse_connect(char *str) {
rfbLog("killing gui_pid %d\n", gui_pid); rfbLog("killing gui_pid %d\n", gui_pid);
kill(gui_pid, SIGTERM); kill(gui_pid, SIGTERM);
} }
clean_up_exit(0); clean_up_exit(1);
} }
} }
if (xrandr || xrandr_maybe) { if (xrandr || xrandr_maybe) {
@ -2924,6 +3092,8 @@ void read_x11vnc_remote_prop(int nomsg) {
#endif /* NO_X11 */ #endif /* NO_X11 */
} }
extern int rc_npieces;
void grab_state(int *ptr_grabbed, int *kbd_grabbed) { void grab_state(int *ptr_grabbed, int *kbd_grabbed) {
int rcp, rck; int rcp, rck;
double t0, t1; double t0, t1;
@ -2965,8 +3135,10 @@ void grab_state(int *ptr_grabbed, int *kbd_grabbed) {
if (rck == AlreadyGrabbed || rck == GrabFrozen) { if (rck == AlreadyGrabbed || rck == GrabFrozen) {
*kbd_grabbed = 1; *kbd_grabbed = 1;
} }
rfbLog("grab_state: checked %d,%d in %.6f sec (%.6f %.6f)\n", if (rc_npieces < 10) {
*ptr_grabbed, *kbd_grabbed, t1-t0, tb-ta, tc-tb); rfbLog("grab_state: checked %d,%d in %.6f sec (%.6f %.6f)\n",
*ptr_grabbed, *kbd_grabbed, t1-t0, tb-ta, tc-tb);
}
#endif #endif
} }
@ -3715,6 +3887,15 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
} }
} }
if (ipv6_client_ip_str != NULL) {
rfbLog("renaming client->host from '%s' to '%s'\n",
client->host ? client->host : "", ipv6_client_ip_str);
if (client->host) {
free(client->host);
}
client->host = strdup(ipv6_client_ip_str);
}
if (! check_access(client->host)) { if (! check_access(client->host)) {
rfbLog("denying client: %s does not match %s\n", client->host, rfbLog("denying client: %s does not match %s\n", client->host,
allow_list ? allow_list : "(null)" ); allow_list ? allow_list : "(null)" );
@ -3945,10 +4126,10 @@ void start_client_info_sock(char *host_port_cookie) {
free(host); free(host);
host = strdup("localhost"); host = strdup("localhost");
} }
sock = rfbConnectToTcpAddr(host, port); sock = connect_tcp(host, port);
if (sock < 0) { if (sock < 0) {
usleep(200 * 1000); usleep(200 * 1000);
sock = rfbConnectToTcpAddr(host, port); sock = connect_tcp(host, port);
} }
if (sock >= 0) { if (sock >= 0) {
char *lst = list_clients(); char *lst = list_clients();

@ -68,6 +68,7 @@ extern void send_client_info(char *str);
extern void adjust_grabs(int grab, int quiet); extern void adjust_grabs(int grab, int quiet);
extern void check_new_clients(void); extern void check_new_clients(void);
extern int accept_client(rfbClientPtr client); extern int accept_client(rfbClientPtr client);
extern void check_ipv6_listen(long usec);
extern int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, extern int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input,
int len, FILE *output); int len, FILE *output);
extern int check_access(char *addr); extern int check_access(char *addr);

@ -66,7 +66,7 @@ so, delete this exception statement from your version.
* without using SSH or SSL. * without using SSH or SSL.
* *
* ----------------------------------------------------------------------- * -----------------------------------------------------------------------
* Copyright (C) 2008-2009 Karl J. Runge <runge@karlrunge.com> * Copyright (C) 2008-2010 Karl J. Runge <runge@karlrunge.com>
* All rights reserved. * All rights reserved.
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify

@ -141,6 +141,34 @@ void print_help(int mode) {
" then the x11vnc -gui is used to prompt the user to\n" " then the x11vnc -gui is used to prompt the user to\n"
" enter the port number.\n" " enter the port number.\n"
"\n" "\n"
#if X11VNC_IPV6
"-6 IPv6 listening support. In addition to IPv4, the\n"
" IPv6 address is listened on for incoming connections.\n"
" The same port as IPv4 is used to listen. If you have\n"
" trouble compiling for this mode, set -DX11VNC_IPV6=0\n"
" in CPPFLAGS when configuring.\n"
"\n"
" Currently, the machine may need to have some IPv4\n"
" support, at the least for the loopback interface, for\n"
" everything to work correctly. However for most usage\n"
" modes IPv4 support is not required.\n"
"\n"
" The -6 mode works for both normal connections and\n"
" -ssl encrypted ones. Nearly everything is supported\n"
" for the IPv6 case, but there are a few exceptions.\n"
" See -stunnel for its IPv6 support.\n"
"\n"
"-noipv6 Do not try to use IPv6 for any listening or connecting\n"
" sockets. This includes both the listening service\n"
" port(s) and outgoing connections from -connect,\n"
" -connect_or_exit, or -proxy. Use this if you are having\n"
" problems due to IPv6.\n"
"\n"
"-noipv4 Do not try to use IPv4 for any listening or connecting\n"
" sockets. This is mainly for exploring the behavior of\n"
" x11vnc on an IPv6-only system, but may have other uses.\n"
"\n"
#endif
"-reopen If the X server connection is disconnected, try to\n" "-reopen If the X server connection is disconnected, try to\n"
" reopen the X display (up to one time.) This is of use\n" " reopen the X display (up to one time.) This is of use\n"
" for display managers like GDM (KillInitClients option)\n" " for display managers like GDM (KillInitClients option)\n"
@ -597,6 +625,13 @@ void print_help(int mode) {
" See also the -proxy option below for additional ways\n" " See also the -proxy option below for additional ways\n"
" to plumb reverse connections.\n" " to plumb reverse connections.\n"
"\n" "\n"
" IPv6: as of x11vnc 0.9.10 the -connect option should\n"
" connect to IPv6 hosts properly. If there are problems\n"
" you can disable IPv6 by setting -DX11VNC_IPV6=0\n"
" in CPPFLAGS when configuring. If there problems\n"
" connecting to IPv6 hosts consider a relay like the\n"
" included inet6to4 script or the -proxy option.\n"
"\n"
"-connect_or_exit str As with -connect, except if none of the reverse\n" "-connect_or_exit str As with -connect, except if none of the reverse\n"
" connections succeed, then x11vnc shuts down immediately\n" " connections succeed, then x11vnc shuts down immediately\n"
"\n" "\n"
@ -662,6 +697,13 @@ void print_help(int mode) {
" E.g.: http://host1:port1,socks5://host2:port2 or three\n" " E.g.: http://host1:port1,socks5://host2:port2 or three\n"
" like: first,second,third\n" " like: first,second,third\n"
"\n" "\n"
" IPv6: as of x11vnc 0.9.10 the -proxy option should\n"
" connect to IPv6 hosts properly. If there are problems\n"
" you can disable IPv6 by setting -DX11VNC_IPV6=0\n"
" in CPPFLAGS when configuring. If there problems\n"
" connecting to IPv6 hosts consider a relay like the\n"
" included inet6to4 script.\n"
"\n"
"-vncconnect Monitor the VNC_CONNECT X property set by the standard\n" "-vncconnect Monitor the VNC_CONNECT X property set by the standard\n"
"-novncconnect VNC program vncconnect(1). When the property is\n" "-novncconnect VNC program vncconnect(1). When the property is\n"
" set to \"host\" or \"host:port\" establish a reverse\n" " set to \"host\" or \"host:port\" establish a reverse\n"
@ -691,6 +733,9 @@ void print_help(int mode) {
"\n" "\n"
" -allow applies in -ssl mode, but not in -stunnel mode.\n" " -allow applies in -ssl mode, but not in -stunnel mode.\n"
"\n" "\n"
" IPv6: as of x11vnc 0.9.10 a host can be specified\n"
" in IPv6 numerical format, e.g. 2001:4860:b009::93.\n"
"\n"
"-localhost Basically the same as \"-allow 127.0.0.1\".\n" "-localhost Basically the same as \"-allow 127.0.0.1\".\n"
"\n" "\n"
" Note: if you want to restrict which network interface\n" " Note: if you want to restrict which network interface\n"
@ -710,6 +755,16 @@ void print_help(int mode) {
" or plan to use remote control: -R connect:host), use\n" " or plan to use remote control: -R connect:host), use\n"
" -rfbport 0\n" " -rfbport 0\n"
"\n" "\n"
" IPv6: if IPv6 is supported, this option automatically\n"
" implies the IPv6 loopback address '::1' as well.\n"
"\n"
#if X11VNC_IPV6
"-listen6 str When in IPv6 listen mode \"-6\", only listen on the\n"
" network interface with address \"str\". It currently\n"
" does not work for link scope addresses or non-numeric\n"
" hostname strings.\n"
"\n"
#endif
"-nolookup Do not use gethostbyname() or gethostbyaddr() to look up\n" "-nolookup Do not use gethostbyname() or gethostbyaddr() to look up\n"
" host names or IP numbers. Use this if name resolution\n" " host names or IP numbers. Use this if name resolution\n"
" is incorrectly set up and leads to long pauses as name\n" " is incorrectly set up and leads to long pauses as name\n"
@ -1266,7 +1321,7 @@ void print_help(int mode) {
"\n" "\n"
" This mode only allows one redirected connection.\n" " This mode only allows one redirected connection.\n"
" The -forever option does not apply. Use -inetd or\n" " The -forever option does not apply. Use -inetd or\n"
" -loop for persistant service.\n" " -loop for persistent service.\n"
"\n" "\n"
"-display WAIT:... A special usage mode for the normal -display option.\n" "-display WAIT:... A special usage mode for the normal -display option.\n"
" Useful with -unixpw, but can be used independently\n" " Useful with -unixpw, but can be used independently\n"
@ -1357,6 +1412,10 @@ void print_help(int mode) {
" if the viewer-side supplied value is not completely\n" " if the viewer-side supplied value is not completely\n"
" composed of alphanumeric or '_' or '-' characters.\n" " composed of alphanumeric or '_' or '-' characters.\n"
"\n" "\n"
" To troubleshoot the FINDCREATEDISPLAY mechanism,\n"
" set the following env. var. to an ouput log file,\n"
" e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt\n"
"\n"
" To disable the option setting set the environment\n" " To disable the option setting set the environment\n"
" variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.\n" " variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.\n"
" To set any other options, the user can use the gui\n" " To set any other options, the user can use the gui\n"
@ -2236,15 +2295,25 @@ void print_help(int mode) {
"\n" "\n"
" Set -env STUNNEL_DEBUG=1 for more debugging printout.\n" " Set -env STUNNEL_DEBUG=1 for more debugging printout.\n"
"\n" "\n"
" Set -env STUNNEL_PROG=xxx to the full path of stunnel\n"
" program you want to be used (e.g. /usr/bin/stunnel4).\n"
"\n"
" Set -env STUNNEL_LISTEN=xxx to the address of the\n"
" network interface to listen on (the default is to listen\n"
" on all interfaces), e.g. STUNNEL_LISTEN=192.168.1.100.\n"
"\n"
" A simple way to add IPv6 support is STUNNEL_LISTEN=::\n"
"\n"
" Your VNC viewer will also need to be able to connect\n" " Your VNC viewer will also need to be able to connect\n"
" via SSL. Unfortunately not too many do this. See the\n" " via SSL. Unfortunately not too many do this. See the\n"
" information about SSL viewers under the -ssl option.\n" " information about SSL viewers under the -ssl option.\n"
" The x11vnc project's SSVNC is an option.\n"
"\n" "\n"
" Also, in the x11vnc distribution, patched TightVNC\n" " Also, in the x11vnc distribution, patched TightVNC\n"
" and UltraVNC Java applet jar files are provided in\n" " and UltraVNC Java applet jar files are provided in\n"
" the classes/ssl directory that do SSL connections.\n" " the classes/ssl directory that do SSL connections.\n"
" Enable serving them with the -http, -http_ssl, -https,\n" " Enable serving them with the -http, -http_ssl, or\n"
" or -httpdir (see the option descriptions for more info.)\n" " -httpdir (see the option descriptions for more info.)\n"
"\n" "\n"
" Note that for the Java viewer applet usage the\n" " Note that for the Java viewer applet usage the\n"
" \"?PORT=xxxx\" in the various URLs printed at startup\n" " \"?PORT=xxxx\" in the various URLs printed at startup\n"
@ -3815,6 +3884,9 @@ void print_help(int mode) {
"-allinput Have x11vnc read and process all available client input\n" "-allinput Have x11vnc read and process all available client input\n"
" before proceeding.\n" " before proceeding.\n"
"\n" "\n"
"-input_eagerly Similar to -allinput but use the handleEventsEagerly\n"
" mechanism built into LibVNCServer.\n"
"\n"
"-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that\n" "-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that\n"
" are used to optimize scheduling (e.g. -pointer_mode\n" " are used to optimize scheduling (e.g. -pointer_mode\n"
" 4, -wireframe, -scrollcopyrect) and other things.\n" " 4, -wireframe, -scrollcopyrect) and other things.\n"
@ -4842,6 +4914,13 @@ void print_help(int mode) {
" localhost enable -localhost mode\n" " localhost enable -localhost mode\n"
" nolocalhost disable -localhost mode\n" " nolocalhost disable -localhost mode\n"
" listen:str set -listen to str, empty to disable.\n" " listen:str set -listen to str, empty to disable.\n"
" noipv6 enable -noipv6 mode.\n"
" ipv6 disable -noipv6 mode.\n"
" noipv4 enable -noipv4 mode.\n"
" ipv4 disable -noipv4 mode.\n"
" 6 enable -6 IPv6 listening mode.\n"
" no6 disable -6 IPv6 listening mode.\n"
" lookup disable -nolookup mode.\n"
" nolookup enable -nolookup mode.\n" " nolookup enable -nolookup mode.\n"
" lookup disable -nolookup mode.\n" " lookup disable -nolookup mode.\n"
" input:str set -input to \"str\", empty to disable.\n" " input:str set -input to \"str\", empty to disable.\n"
@ -5005,6 +5084,8 @@ void print_help(int mode) {
" input_skip:n set -input_skip to n.\n" " input_skip:n set -input_skip to n.\n"
" allinput enable use of -allinput mode.\n" " allinput enable use of -allinput mode.\n"
" noallinput disable use of -allinput mode.\n" " noallinput disable use of -allinput mode.\n"
" input_eagerly enable use of -input_eagerly mode.\n"
" noinput_eagerly disable use of -input_eagerly mode.\n"
" ssltimeout:n set -ssltimeout to n.\n" " ssltimeout:n set -ssltimeout to n.\n"
" speeds:str set -speeds to str.\n" " speeds:str set -speeds to str.\n"
" wmdt:str set -wmdt to str.\n" " wmdt:str set -wmdt to str.\n"
@ -5263,52 +5344,54 @@ void print_help(int mode) {
" 8to24_opts 24to32 no24to32 visual scale scale_cursor\n" " 8to24_opts 24to32 no24to32 visual scale scale_cursor\n"
" viewonly noviewonly shared noshared forever noforever\n" " viewonly noviewonly shared noshared forever noforever\n"
" once timeout tightfilexfer notightfilexfer ultrafilexfer\n" " once timeout tightfilexfer notightfilexfer ultrafilexfer\n"
" noultrafilexfer rfbversion deny lock nodeny unlock\n" " noultrafilexfer rfbversion deny lock nodeny unlock avahi\n"
" avahi mdns zeroconf noavahi nomdns nozeroconf connect\n" " mdns zeroconf noavahi nomdns nozeroconf connect proxy\n"
" proxy allowonce allow localhost nolocalhost listen\n" " allowonce allow noipv6 ipv6 noipv4 ipv4 no6 6 localhost\n"
" lookup nolookup accept afteraccept gone shm noshm\n" " nolocalhost listen lookup nolookup accept afteraccept\n"
" flipbyteorder noflipbyteorder onetile noonetile\n" " gone shm noshm flipbyteorder noflipbyteorder onetile\n"
" solid_color solid nosolid blackout xinerama noxinerama\n" " noonetile solid_color solid nosolid blackout xinerama\n"
" xtrap noxtrap xrandr noxrandr xrandr_mode rotate padgeom\n" " noxinerama xtrap noxtrap xrandr noxrandr xrandr_mode\n"
" quiet q noquiet modtweak nomodtweak xkb noxkb capslock\n" " rotate padgeom quiet q noquiet modtweak nomodtweak xkb\n"
" nocapslock skip_lockkeys noskip_lockkeys skip_keycodes\n" " noxkb capslock nocapslock skip_lockkeys noskip_lockkeys\n"
" sloppy_keys nosloppy_keys skip_dups noskip_dups\n" " skip_keycodes sloppy_keys nosloppy_keys skip_dups\n"
" add_keysyms noadd_keysyms clear_mods noclear_mods\n" " noskip_dups add_keysyms noadd_keysyms clear_mods\n"
" clear_keys noclear_keys clear_all clear_locks keystate\n" " noclear_mods clear_keys noclear_keys clear_all\n"
" remap repeat norepeat fb nofb bell nobell sendbell\n" " clear_locks keystate remap repeat norepeat fb nofb bell\n"
" sel nosel primary noprimary setprimary nosetprimary\n" " nobell sendbell sel nosel primary noprimary setprimary\n"
" clipboard noclipboard setclipboard nosetclipboard\n" " nosetprimary clipboard noclipboard setclipboard\n"
" seldir cursorshape nocursorshape cursorpos nocursorpos\n" " nosetclipboard seldir cursorshape nocursorshape\n"
" cursor_drag nocursor_drag cursor show_cursor\n" " cursorpos nocursorpos cursor_drag nocursor_drag cursor\n"
" noshow_cursor nocursor arrow xfixes noxfixes xdamage\n" " show_cursor noshow_cursor nocursor arrow xfixes\n"
" noxdamage xd_area xd_mem alphacut alphafrac alpharemove\n" " noxfixes xdamage noxdamage xd_area xd_mem alphacut\n"
" noalpharemove alphablend noalphablend xwarppointer\n" " alphafrac alpharemove noalpharemove alphablend\n"
" xwarp noxwarppointer noxwarp buttonmap dragging\n" " noalphablend xwarppointer xwarp noxwarppointer\n"
" nodragging ncache_cr noncache_cr ncache_no_moveraise\n" " noxwarp buttonmap dragging nodragging ncache_cr\n"
" noncache_no_moveraise ncache_no_dtchange\n" " noncache_cr ncache_no_moveraise noncache_no_moveraise\n"
" noncache_no_dtchange ncache_no_rootpixmap\n" " ncache_no_dtchange noncache_no_dtchange\n"
" noncache_no_rootpixmap ncache_reset_rootpixmap ncrp\n" " ncache_no_rootpixmap noncache_no_rootpixmap\n"
" ncache_keep_anims noncache_keep_anims ncache_old_wm\n" " ncache_reset_rootpixmap ncrp ncache_keep_anims\n"
" noncache_old_wm ncache_pad ncache noncache ncache_size\n" " noncache_keep_anims ncache_old_wm noncache_old_wm\n"
" debug_ncache nodebug_ncache wireframe_mode wireframe wf\n" " ncache_pad ncache noncache ncache_size debug_ncache\n"
" nowireframe nowf wireframelocal wfl nowireframelocal\n" " nodebug_ncache wireframe_mode wireframe wf nowireframe\n"
" nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area\n" " nowf wireframelocal wfl nowireframelocal nowfl\n"
" wirecopyrect wcr nowirecopyrect nowcr scr_area\n"
" scr_skip scr_inc scr_keys scr_term scr_keyrepeat\n" " scr_skip scr_inc scr_keys scr_term scr_keyrepeat\n"
" scr_parms scrollcopyrect scr noscrollcopyrect\n" " scr_parms scrollcopyrect scr noscrollcopyrect\n"
" noscr fixscreen noxrecord xrecord reset_record\n" " noscr fixscreen noxrecord xrecord reset_record\n"
" pointer_mode pm input_skip allinput noallinput input\n" " pointer_mode pm input_skip allinput noallinput\n"
" grabkbd nograbkbd grabptr nograbptr grabalways\n" " input_eagerly noinput_eagerly input grabkbd nograbkbd\n"
" nograbalways grablocal client_input ssltimeout\n" " grabptr nograbptr grabalways nograbalways grablocal\n"
" speeds wmdt debug_pointer dp nodebug_pointer nodp\n" " client_input ssltimeout speeds wmdt debug_pointer dp\n"
" debug_keyboard dk nodebug_keyboard nodk keycode keysym\n" " nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n"
" ptr fakebuttonevent sleep get_xprop set_xprop wininfo\n" " nodk keycode keysym ptr fakebuttonevent sleep get_xprop\n"
" bcx_xattach deferupdate defer setdefer extra_fbur\n" " set_xprop wininfo bcx_xattach deferupdate defer\n"
" wait_ui wait_bog nowait_bog slow_fb xrefresh wait\n" " setdefer extra_fbur wait_ui wait_bog nowait_bog\n"
" readtimeout nap nonap sb screen_blank fbpm nofbpm dpms\n" " slow_fb xrefresh wait readtimeout nap nonap sb\n"
" nodpms clientdpms noclientdpms forcedpms noforcedpms\n" " screen_blank fbpm nofbpm dpms nodpms clientdpms\n"
" noserverdpms serverdpms noultraext ultraext chatwindow\n" " noclientdpms forcedpms noforcedpms noserverdpms\n"
" nochatwindow chaton chatoff fs gaps grow fuzz snapfb\n" " serverdpms noultraext ultraext chatwindow nochatwindow\n"
" nosnapfb rawfb uinput_accel uinput_thresh uinput_reset\n" " chaton chatoff fs gaps grow fuzz snapfb nosnapfb\n"
" rawfb uinput_accel uinput_thresh uinput_reset\n"
" uinput_always progressive rfbport http nohttp httpport\n" " uinput_always progressive rfbport http nohttp httpport\n"
" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n" " httpdir enablehttpproxy noenablehttpproxy alwaysshared\n"
" noalwaysshared nevershared noalwaysshared dontdisconnect\n" " noalwaysshared nevershared noalwaysshared dontdisconnect\n"
@ -5340,7 +5423,6 @@ void print_help(int mode) {
" pointer_x pointer_y pointer_same pointer_root bpp depth\n" " pointer_x pointer_y pointer_same pointer_root bpp depth\n"
" indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y\n" " indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y\n"
" cdpy_x cdpy_y coff_x coff_y rfbauth passwd viewpasswd\n" " cdpy_x cdpy_y coff_x coff_y rfbauth passwd viewpasswd\n"
"\n"
"-QD variable Just like -query variable, but returns the default\n" "-QD variable Just like -query variable, but returns the default\n"
" value for that parameter (no running x11vnc server\n" " value for that parameter (no running x11vnc server\n"
" is consulted)\n" " is consulted)\n"
@ -6087,7 +6169,7 @@ void print_license(void) {
"\n" "\n"
"x11vnc: a VNC server for X displays. %s\n" "x11vnc: a VNC server for X displays. %s\n"
"\n" "\n"
"Copyright (C) 2002-2009 Karl J. Runge <runge@karlrunge.com>\n" "Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>\n"
"All rights reserved.\n" "All rights reserved.\n"
"\n" "\n"
; ;

@ -44,6 +44,7 @@ char *host2ip(char *host);
char *raw2host(char *raw, int len); char *raw2host(char *raw, int len);
char *raw2ip(char *raw); char *raw2ip(char *raw);
char *ip2host(char *ip); char *ip2host(char *ip);
int ipv6_ip(char *host);
int dotted_ip(char *host); int dotted_ip(char *host);
int get_remote_port(int sock); int get_remote_port(int sock);
int get_local_port(int sock); int get_local_port(int sock);
@ -51,7 +52,13 @@ char *get_remote_host(int sock);
char *get_local_host(int sock); char *get_local_host(int sock);
char *ident_username(rfbClientPtr client); char *ident_username(rfbClientPtr client);
int find_free_port(int start, int end); int find_free_port(int start, int end);
int find_free_port6(int start, int end);
int have_ssh_env(void); int have_ssh_env(void);
char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen);
char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen);
int listen6(int port);
int connect_tcp(char *host, int port);
int listen_tcp(int port, in_addr_t iface, int try6);
static int get_port(int sock, int remote); static int get_port(int sock, int remote);
static char *get_host(int sock, int remote); static char *get_host(int sock, int remote);
@ -126,6 +133,43 @@ char *ip2host(char *ip) {
return str; return str;
} }
int ipv6_ip(char *host_in) {
char *p, *host, a[2];
int ncol = 0, nhex = 0;
if (host_in[0] == '[') {
host = host_in + 1;
} else {
host = host_in;
}
if (strstr(host, "::ffff:") == host) {
return dotted_ip(host + strlen("::ffff:"));
}
a[1] = '\0';
p = host;
while (*p != '\0' && *p != '%' && *p != ']') {
if (*p == ':') {
ncol++;
} else {
nhex++;
}
a[0] = *p;
if (strpbrk(a, ":abcdef0123456789") == a) {
p++;
continue;
}
return 0;
}
if (ncol < 2 || ncol > 8 || nhex == 0) {
return 0;
} else {
return 1;
}
}
int dotted_ip(char *host) { int dotted_ip(char *host) {
char *p = host; char *p = host;
while (*p != '\0') { while (*p != '\0') {
@ -251,7 +295,7 @@ char *ident_username(rfbClientPtr client) {
signal(SIGQUIT, SIG_DFL); signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL); signal(SIGTERM, SIG_DFL);
if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) { if ((sock = connect_tcp(client->host, 113)) < 0) {
exit(1); exit(1);
} else { } else {
close(sock); close(sock);
@ -262,7 +306,7 @@ char *ident_username(rfbClientPtr client) {
#endif #endif
if (block || refused) { if (block || refused) {
; ;
} else if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) { } else if ((sock = connect_tcp(client->host, 113)) < 0) {
rfbLog("ident_username: could not connect to ident: %s:%d\n", rfbLog("ident_username: could not connect to ident: %s:%d\n",
client->host, 113); client->host, 113);
} else { } else {
@ -356,7 +400,25 @@ int find_free_port(int start, int end) {
end = 65530; end = 65530;
} }
for (port = start; port <= end; port++) { for (port = start; port <= end; port++) {
int sock = rfbListenOnTCPPort(port, htonl(INADDR_ANY)); int sock = listen_tcp(port, htonl(INADDR_ANY), 0);
if (sock >= 0) {
close(sock);
return port;
}
}
return 0;
}
int find_free_port6(int start, int end) {
int port;
if (start <= 0) {
start = 1024;
}
if (end <= 0) {
end = 65530;
}
for (port = start; port <= end; port++) {
int sock = listen6(port);
if (sock >= 0) { if (sock >= 0) {
close(sock); close(sock);
return port; return port;
@ -428,3 +490,262 @@ if (0) fprintf(stderr, "%d/%d - '%s' '%s'\n", atoi(rport), atoi(lport), rhost, l
return 0; return 0;
} }
char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) {
#if X11VNC_IPV6
char name[200];
if (noipv6) {
return strdup("unknown");
}
if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) {
return strdup(name);
}
#endif
return strdup("unknown");
}
char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) {
#if X11VNC_IPV6
char name[200];
if (noipv6) {
return strdup("unknown");
}
if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) {
return strdup(name);
}
#endif
return strdup("unknown");
}
int listen6(int port) {
#if X11VNC_IPV6
struct sockaddr_in6 sin;
int fd = -1, one = 1;
if (noipv6) {
return -1;
}
fd = socket(AF_INET6, SOCK_STREAM, 0);
if (fd < 0) {
rfbLogPerror("listen6: socket");
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
rfbLogPerror("listen6: setsockopt1");
close(fd);
return -1;
}
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
rfbLogPerror("listen6: setsockopt2");
close(fd);
return -1;
}
#endif
memset((char *)&sin, 0, sizeof(sin));
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(port);
sin.sin6_addr = in6addr_any;
if (listen_str6) {
if (!strcmp(listen_str6, "localhost")) {
sin.sin6_addr = in6addr_loopback;
} else if (ipv6_ip(listen_str6)) {
int err = inet_pton(AF_INET6, listen_str6, &(sin.sin6_addr));
if (err <= 0) {
rfbLog("inet_pton[%d] failed -listen6 %s\n", err, listen_str6);
close(fd);
return -1;
}
} else {
rfbLog("Unsupported -listen6 string: %s\n", listen_str6);
close(fd);
return -1;
}
} else if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
sin.sin6_addr = in6addr_loopback;
} else if (listen_str) {
if (!strcmp(listen_str, "localhost")) {
sin.sin6_addr = in6addr_loopback;
}
}
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
rfbLogPerror("listen6: bind");
close(fd);
return -1;
}
if (listen(fd, 32) < 0) {
rfbLogPerror("listen6: listen");
close(fd);
return -1;
}
return fd;
#else
if (port) {}
return -1;
#endif
}
int connect_tcp(char *host, int port) {
double t0 = dnow();
int fd = -1;
int fail4 = noipv4;
if (getenv("IPV4_FAILS")) {
fail4 = 2;
}
rfbLog("connect_tcp: trying: %s %d\n", host, port);
if (fail4) {
if (fail4 > 1) {
rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n");
}
} else {
fd = rfbConnectToTcpAddr(host, port);
}
if (fd >= 0) {
return fd;
}
rfbLogPerror("connect_tcp: connection failed");
if (dnow() - t0 < 4.0) {
rfbLog("connect_tcp: re-trying %s %d\n", host, port);
usleep (100 * 1000);
if (!fail4) {
fd = rfbConnectToTcpAddr(host, port);
}
if (fd < 0) {
rfbLogPerror("connect_tcp: connection failed");
}
}
if (fd < 0 && !noipv6) {
#if X11VNC_IPV6 && defined(AI_ADDRCONFIG)
int err;
struct addrinfo *ai;
struct addrinfo hints;
char service[32], *host2, *q;
rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port);
memset(&hints, 0, sizeof(hints));
sprintf(service, "%d", port);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
if(ipv6_ip(host)) {
#ifdef AI_NUMERICHOST
rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host);
hints.ai_flags |= AI_NUMERICHOST;
#else
rfbLog("connect_tcp[ipv6]: no AI_NUMERICHOST for %s\n", host);
#endif
}
#ifdef AI_NUMERICSERV
hints.ai_flags |= AI_NUMERICSERV;
#endif
if (!strcmp(host, "127.0.0.1")) {
host2 = strdup("::1");
} else if (host[0] == '[') {
host2 = strdup(host+1);
} else {
host2 = strdup(host);
}
q = strrchr(host2, ']');
if (q) {
*q = '\0';
}
err = getaddrinfo(host2, service, &hints, &ai);
if (err != 0) {
rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
usleep(100 * 1000);
err = getaddrinfo(host2, service, &hints, &ai);
}
free(host2);
if (err != 0) {
rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
} else {
struct addrinfo *ap = ai;
while (ap != NULL) {
int sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
if (sock == -1) {
rfbLogPerror("connect_tcp[ipv6]: socket");
} else {
char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
if (!s) s = strdup("unknown");
rfbLog("connect_tcp[ipv6]: trying sock=%d using %s\n", sock, s);
if (connect(sock, ap->ai_addr, ap->ai_addrlen) == 0) {
rfbLog("connect_tcp[ipv6]: connect OK\n");
fd = sock;
if (!ipv6_client_ip_str) {
ipv6_client_ip_str = strdup(s);
}
free(s);
break;
} else {
close(sock);
rfbLogPerror("connect_tcp[ipv6]: connect");
}
free(s);
}
ap = ap->ai_next;
}
freeaddrinfo(ai);
}
#endif
}
return fd;
}
int listen_tcp(int port, in_addr_t iface, int try6) {
int fd = -1;
int fail4 = noipv4;
if (getenv("IPV4_FAILS")) {
fail4 = 2;
}
if (fail4) {
if (fail4 > 1) {
rfbLog("TESTING: IPV4_FAILS for listen_tcp: port=%d try6=%d\n", port, try6);
}
} else {
fd = rfbListenOnTCPPort(port, iface);
}
if (fd >= 0) {
return fd;
}
if (fail4 > 1) {
rfbLogPerror("listen_tcp: listen failed");
}
if (fd < 0 && try6 && ipv6_listen && !noipv6) {
#if X11VNC_IPV6
char *save = listen_str6;
if (iface == htonl(INADDR_LOOPBACK)) {
listen_str6 = "localhost";
rfbLog("listen_tcp: retrying on IPv6 in6addr_loopback ...\n");
fd = listen6(port);
} else if (iface == htonl(INADDR_ANY)) {
listen_str6 = NULL;
rfbLog("listen_tcp: retrying on IPv6 in6addr_any ...\n");
fd = listen6(port);
}
listen_str6 = save;
#else
if (try6) {}
#endif
}
return fd;
}

@ -39,6 +39,7 @@ extern char *host2ip(char *host);
extern char *raw2host(char *raw, int len); extern char *raw2host(char *raw, int len);
extern char *raw2ip(char *raw); extern char *raw2ip(char *raw);
extern char *ip2host(char *ip); extern char *ip2host(char *ip);
extern int ipv6_ip(char *host);
extern int dotted_ip(char *host); extern int dotted_ip(char *host);
extern int get_remote_port(int sock); extern int get_remote_port(int sock);
extern int get_local_port(int sock); extern int get_local_port(int sock);
@ -46,6 +47,12 @@ extern char *get_remote_host(int sock);
extern char *get_local_host(int sock); extern char *get_local_host(int sock);
extern char *ident_username(rfbClientPtr client); extern char *ident_username(rfbClientPtr client);
extern int find_free_port(int start, int end); extern int find_free_port(int start, int end);
extern int find_free_port6(int start, int end);
extern int have_ssh_env(void); extern int have_ssh_env(void);
extern char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen);
extern char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen);
extern int listen6(int port);
extern int connect_tcp(char *host, int port);
extern int listen_tcp(int port, in_addr_t iface, int try6);
#endif /* _X11VNC_INET_H */ #endif /* _X11VNC_INET_H */

@ -134,10 +134,21 @@ int no_external_cmds = 1; /* cannot be turned back on. */
char *allowed_external_cmds = NULL; char *allowed_external_cmds = NULL;
int started_as_root = 0; int started_as_root = 0;
int host_lookup = 1; int host_lookup = 1;
#ifndef X11VNC_LISTEN6
int ipv6_listen = 0; /* -6 */
#else
int ipv6_listen = 1;
#endif
int ipv6_listen_fd = -1;
int ipv6_http_fd = -1;
int noipv6 = 0;
int noipv4 = 0;
char *ipv6_client_ip_str = NULL;
char *users_list = NULL; /* -users */ char *users_list = NULL; /* -users */
char **user2group = NULL; char **user2group = NULL;
char *allow_list = NULL; /* for -allow and -localhost */ char *allow_list = NULL; /* for -allow and -localhost */
char *listen_str = NULL; char *listen_str = NULL;
char *listen_str6 = NULL;
char *allow_once = NULL; /* one time -allow */ char *allow_once = NULL; /* one time -allow */
char *accept_cmd = NULL; /* for -accept */ char *accept_cmd = NULL; /* for -accept */
char *afteraccept_cmd = NULL; /* for -afteraccept */ char *afteraccept_cmd = NULL; /* for -afteraccept */
@ -426,6 +437,7 @@ int napfac = 4; /* time = napfac*waitms, cut load with extra waits */
int napmax = 1500; /* longest nap in ms. */ int napmax = 1500; /* longest nap in ms. */
int ui_skip = 10; /* see watchloop. negative means ignore input */ int ui_skip = 10; /* see watchloop. negative means ignore input */
int all_input = 0; int all_input = 0;
int handle_events_eagerly = 0;
#if LIBVNCSERVER_HAVE_FBPM #if LIBVNCSERVER_HAVE_FBPM

@ -115,10 +115,17 @@ extern int no_external_cmds;
extern char *allowed_external_cmds; extern char *allowed_external_cmds;
extern int started_as_root; extern int started_as_root;
extern int host_lookup; extern int host_lookup;
extern int ipv6_listen;
extern int ipv6_listen_fd;
extern int ipv6_http_fd;
extern int noipv6;
extern int noipv4;
extern char *ipv6_client_ip_str;
extern char *users_list; extern char *users_list;
extern char **user2group; extern char **user2group;
extern char *allow_list; extern char *allow_list;
extern char *listen_str; extern char *listen_str;
extern char *listen_str6;
extern char *allow_once; extern char *allow_once;
extern char *accept_cmd; extern char *accept_cmd;
extern char *afteraccept_cmd; extern char *afteraccept_cmd;
@ -331,6 +338,7 @@ extern int napfac;
extern int napmax; extern int napmax;
extern int ui_skip; extern int ui_skip;
extern int all_input; extern int all_input;
extern int handle_events_eagerly;
extern int watch_fbpm; extern int watch_fbpm;
extern int watch_dpms; extern int watch_dpms;

@ -59,6 +59,7 @@ so, delete this exception statement from your version.
#include "uinput.h" #include "uinput.h"
#include "userinput.h" #include "userinput.h"
#include "avahi.h" #include "avahi.h"
#include "sslhelper.h"
int send_remote_cmd(char *cmd, int query, int wait); int send_remote_cmd(char *cmd, int query, int wait);
int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync, int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync,
@ -480,6 +481,15 @@ static void rfb_http_init_sockets(void) {
screen->listenInterface = htonl(INADDR_LOOPBACK); screen->listenInterface = htonl(INADDR_LOOPBACK);
} }
rfbHttpInitSockets(screen); rfbHttpInitSockets(screen);
if (noipv4 || getenv("IPV4_FAILS")) {
if (getenv("IPV4_FAILS")) {
rfbLog("TESTING: IPV4_FAILS for rfb_http_init_sockets()\n");
}
if (screen->httpListenSock > -1) {
close(screen->httpListenSock);
screen->httpListenSock = -1;
}
}
screen->listenInterface = iface; screen->listenInterface = iface;
} }
@ -505,95 +515,169 @@ void http_connections(int on) {
} }
screen->httpInitDone = FALSE; screen->httpInitDone = FALSE;
if (check_httpdir()) { if (check_httpdir()) {
int fd6 = -1;
screen->httpDir = http_dir; screen->httpDir = http_dir;
rfb_http_init_sockets(); rfb_http_init_sockets();
if (screen->httpPort != 0 && screen->httpListenSock < 0) { if (screen->httpPort != 0 && screen->httpListenSock < 0) {
rfbLog("http_connections: failed to listen on http port: %d\n", screen->httpPort); rfbLog("http_connections: failed to listen on http port: %d\n", screen->httpPort);
clean_up_exit(1); if (ipv6_listen) {
fd6 = listen6(screen->httpPort);
}
if (fd6 < 0) {
clean_up_exit(1);
}
rfbLog("http_connections: trying IPv6 only mode.\n");
}
if (ipv6_listen && screen->httpPort > 0) {
if (fd6 < 0) {
fd6 = listen6(screen->httpPort);
}
ipv6_http_fd = fd6;
if (ipv6_http_fd >= 0) {
rfbLog("http_connections: %s listening on IPv6 port=%d sock=%d\n",
screen->httpListenSock < 0 ? "Only" : "Also",
screen->httpPort, ipv6_http_fd);
}
} }
} }
} else { } else {
rfbLog("http_connections: turning off http service.\n"); rfbLog("http_connections: turning off http service.\n");
if (screen->httpListenSock > -1) { if (screen->httpListenSock > -1) {
close(screen->httpListenSock); close(screen->httpListenSock);
screen->httpListenSock = -1;
} }
screen->httpListenSock = -1;
screen->httpDir = NULL; screen->httpDir = NULL;
if (ipv6_http_fd >= 0) {
close(ipv6_http_fd);
ipv6_http_fd = -1;
}
} }
} }
static void reset_httpport(int old, int new) { static void reset_httpport(int old, int new) {
int hp = new; int hp = new;
if (hp < 0) {
if (! screen->httpDir) {
return;
} else if (inetd) {
rfbLog("reset_httpport: cannot set httpport: %d in inetd.\n", hp);
return;
} else if (!screen) {
rfbLog("reset_httpport: no screen.\n");
return;
} else if (hp < 0) {
rfbLog("reset_httpport: invalid httpport: %d\n", hp); rfbLog("reset_httpport: invalid httpport: %d\n", hp);
return;
} else if (hp == old) { } else if (hp == old) {
rfbLog("reset_httpport: unchanged httpport: %d\n", hp); rfbLog("reset_httpport: unchanged httpport: %d\n", hp);
} else if (inetd) { return;
rfbLog("reset_httpport: cannot set httpport: %d" }
" in inetd.\n", hp);
} else if (screen) { if (screen->httpListenSock > -1) {
/* mutex */ close(screen->httpListenSock);
screen->httpPort = hp; screen->httpListenSock = -1;
screen->httpInitDone = FALSE; }
if (screen->httpListenSock > -1) {
close(screen->httpListenSock); screen->httpPort = hp;
screen->httpInitDone = FALSE;
rfbLog("reset_httpport: setting httpport %d -> %d.\n",
old == -1 ? hp : old, hp);
if (noipv4 || getenv("IPV4_FAILS")) {
if (getenv("IPV4_FAILS")) {
rfbLog("TESTING: IPV4_FAILS for reset_httpport()\n");
} }
rfbLog("reset_httpport: setting httpport %d -> %d.\n", } else if (screen->httpPort == 0) {
old == -1 ? hp : old, hp); ;
} else {
rfb_http_init_sockets(); rfb_http_init_sockets();
if (screen->httpPort != 0 && screen->httpListenSock < 0) { }
rfbLog("reset_httpport: failed to listen on http port: %d\n", screen->httpPort);
} if (screen->httpPort != 0 && screen->httpListenSock < 0) {
rfbLog("reset_httpport: failed to listen on http port: %d\n",
screen->httpPort);
}
if (ipv6_http_fd >= 0) {
close(ipv6_http_fd);
ipv6_http_fd = -1;
}
if (ipv6_listen && screen->httpPort > 0) {
ipv6_http_fd = listen6(screen->httpPort);
rfbLog("reset_httpport: ipv6_http_fd: %d port: %d\n",
ipv6_http_fd, screen->httpPort);
} }
} }
static void reset_rfbport(int old, int new) { static void reset_rfbport(int old, int new) {
int rp = new; int rp = new;
if (rp < 0) {
if (inetd) {
rfbLog("reset_rfbport: cannot set rfbport: %d in inetd.\n", rp);
return;
} else if (!screen) {
rfbLog("reset_rfbport: no screen.\n");
return;
} else if (rp < 0) {
rfbLog("reset_rfbport: invalid rfbport: %d\n", rp); rfbLog("reset_rfbport: invalid rfbport: %d\n", rp);
return;
} else if (rp == old) { } else if (rp == old) {
rfbLog("reset_rfbport: unchanged rfbport: %d\n", rp); rfbLog("reset_rfbport: unchanged rfbport: %d\n", rp);
} else if (inetd) { return;
rfbLog("reset_rfbport: cannot set rfbport: %d" }
" in inetd.\n", rp);
} else if (screen) { rfbLog("reset_rfbport: setting rfbport %d -> %d.\n", old == -1 ? rp : old, rp);
rfbClientIteratorPtr iter;
rfbClientPtr cl; screen->port = rp;
int maxfd;
/* mutex */ if (use_openssl) {
if (rp == 0) { openssl_port(1);
screen->autoPort = TRUE; if (openssl_sock < 0 && openssl_sock6 < 0) {
rfbLog("reset_rfbport: warning could not listen on port: %d\n",
screen->port);
} else { } else {
screen->autoPort = FALSE; set_vnc_desktop_name();
} }
screen->port = rp; if (https_port_num >= 0) {
screen->socketState = RFB_SOCKET_INIT; https_port(1);
if (screen->listenSock > -1) {
close(screen->listenSock);
} }
return;
}
rfbLog("reset_rfbport: setting rfbport %d -> %d.\n", if (screen->listenSock >= 0) {
old == -1 ? rp : old, rp); FD_CLR(screen->listenSock, &(screen->allFds));
rfbInitSockets(screen); close(screen->listenSock);
screen->listenSock = -1;
}
maxfd = screen->maxFd; if (noipv4 || getenv("IPV4_FAILS")) {
if (screen->udpSock > 0 && screen->udpSock > maxfd) { if (getenv("IPV4_FAILS")) {
maxfd = screen->udpSock; rfbLog("TESTING: IPV4_FAILS for reset_rfbport()\n");
} }
iter = rfbGetClientIterator(screen); } else {
while( (cl = rfbClientIteratorNext(iter)) ) { screen->listenSock = listen_tcp(screen->port, screen->listenInterface, 0);
if (cl->sock > -1) { if (screen->listenSock >= 0) {
FD_SET(cl->sock, &(screen->allFds)); if (screen->listenSock > screen->maxFd) {
if (cl->sock > maxfd) { screen->maxFd = screen->listenSock;
maxfd = cl->sock;
}
} }
FD_SET(screen->listenSock, &(screen->allFds));
} }
rfbReleaseClientIterator(iter); }
screen->maxFd = maxfd; if (ipv6_listen_fd >= 0) {
close(ipv6_listen_fd);
ipv6_listen_fd = -1;
}
if (ipv6_listen && screen->port > 0) {
ipv6_listen_fd = listen6(screen->port);
rfbLog("reset_rfbport: ipv6_listen_fd: %d port: %d\n",
ipv6_listen_fd, screen->port);
}
if (screen->listenSock < 0 && ipv6_listen_fd < 0) {
rfbLog("reset_rfbport: warning could not listen on port: %d\n", screen->port);
} else {
set_vnc_desktop_name(); set_vnc_desktop_name();
} }
} }
@ -741,6 +825,8 @@ int remote_control_access_ok(void) {
void macosxCG_keycode_inject(int down, int keycode); void macosxCG_keycode_inject(int down, int keycode);
#endif #endif
int rc_npieces = 0;
/* /*
* Huge, ugly switch to handle all remote commands and queries * Huge, ugly switch to handle all remote commands and queries
* -remote/-R and -query/-Q. * -remote/-R and -query/-Q.
@ -876,6 +962,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
free(s); free(s);
rc_npieces = n;
strcpy(buf, ""); strcpy(buf, "");
for (k=0; k < n; k++) { for (k=0; k < n; k++) {
res = process_remote_cmd(pieces[k], 1); res = process_remote_cmd(pieces[k], 1);
@ -898,6 +985,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
free(pieces[k]); free(pieces[k]);
} }
free(pieces); free(pieces);
rc_npieces = 0;
goto qry; goto qry;
} }
p += strlen("qry="); p += strlen("qry=");
@ -1779,6 +1867,74 @@ char *process_remote_cmd(char *cmd, int stringonly) {
free(before); free(before);
goto done; goto done;
} }
if (!strcmp(p, "noipv6")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, noipv6);
goto qry;
}
rfbLog("remote_cmd: enabling -noipv6 mode for future sockets.\n");
noipv6 = 1;
goto done;
}
if (!strcmp(p, "ipv6")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !noipv6);
goto qry;
}
rfbLog("remote_cmd: disabling -noipv6 mode for future sockets.\n");
noipv6 = 0;
goto done;
}
if (!strcmp(p, "noipv4")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, noipv4);
goto qry;
}
rfbLog("remote_cmd: enabling -noipv4 mode for future sockets.\n");
noipv4 = 1;
goto done;
}
if (!strcmp(p, "ipv4")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !noipv4);
goto qry;
}
rfbLog("remote_cmd: disabling -noipv4 mode for future sockets.\n");
noipv4 = 0;
goto done;
}
if (!strcmp(p, "no6")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !ipv6_listen);
goto qry;
}
if (ipv6_listen) {
ipv6_listen = 0;
rfbLog("disabling -6 IPv6 listening mode.\n");
reset_rfbport(-1, screen->port);
reset_httpport(-1, screen->httpPort);
if (https_port_num > 0) {
https_port(1);
}
}
goto done;
}
if (!strcmp(p, "6")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, ipv6_listen);
goto qry;
}
if (!ipv6_listen) {
ipv6_listen = 1;
rfbLog("enabling -6 IPv6 listening mode.\n");
reset_rfbport(-1, screen->port);
reset_httpport(-1, screen->httpPort);
if (https_port_num > 0) {
https_port(1);
}
}
goto done;
}
if (!strcmp(p, "localhost")) { if (!strcmp(p, "localhost")) {
char *before, *old; char *before, *old;
if (query) { if (query) {
@ -1818,9 +1974,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("listening on loopback network only.\n"); rfbLog("listening on loopback network only.\n");
rfbLog("allow list is: '%s'\n", NONUL(allow_list)); rfbLog("allow list is: '%s'\n", NONUL(allow_list));
reset_rfbport(-1, screen->port); reset_rfbport(-1, screen->port);
if (screen->httpListenSock > -1) { reset_httpport(-1, screen->httpPort);
reset_httpport(-1, screen->httpPort);
}
goto done; goto done;
} }
if (!strcmp(p, "nolocalhost")) { if (!strcmp(p, "nolocalhost")) {
@ -1866,9 +2020,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("listening on ALL network interfaces.\n"); rfbLog("listening on ALL network interfaces.\n");
rfbLog("allow list is: '%s'\n", NONUL(allow_list)); rfbLog("allow list is: '%s'\n", NONUL(allow_list));
reset_rfbport(-1, screen->port); reset_rfbport(-1, screen->port);
if (screen->httpListenSock > -1) { reset_httpport(-1, screen->httpPort);
reset_httpport(-1, screen->httpPort);
}
goto done; goto done;
} }
if (strstr(p, "listen") == p) { if (strstr(p, "listen") == p) {
@ -1957,9 +2109,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (ok) { if (ok) {
rfbLog("allow list is: '%s'\n", NONUL(allow_list)); rfbLog("allow list is: '%s'\n", NONUL(allow_list));
reset_rfbport(-1, screen->port); reset_rfbport(-1, screen->port);
if (screen->httpListenSock > -1) { reset_httpport(-1, screen->httpPort);
reset_httpport(-1, screen->httpPort);
}
free(before); free(before);
} else { } else {
rfbLog("invalid listen string: %s\n", listen_str); rfbLog("invalid listen string: %s\n", listen_str);
@ -3933,6 +4083,10 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
all_input = 1; all_input = 1;
rfbLog("enabled allinput\n"); rfbLog("enabled allinput\n");
if (handle_events_eagerly) {
rfbLog("disabled input_eagerly\n");
handle_events_eagerly = 0;
}
goto done; goto done;
} }
if (!strcmp(p, "noallinput")) { if (!strcmp(p, "noallinput")) {
@ -3944,6 +4098,28 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("disabled allinput\n"); rfbLog("disabled allinput\n");
goto done; goto done;
} }
if (!strcmp(p, "input_eagerly")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, handle_events_eagerly);
goto qry;
}
handle_events_eagerly = 1;
rfbLog("enabled input_eagerly\n");
if (all_input) {
rfbLog("disabled allinput\n");
all_input = 0;
}
goto done;
}
if (!strcmp(p, "noinput_eagerly")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !handle_events_eagerly);
goto qry;
}
handle_events_eagerly = 0;
rfbLog("disabled input_eagerly\n");
goto done;
}
if (strstr(p, "input") == p) { if (strstr(p, "input") == p) {
int doit = 1; int doit = 1;
COLON_CHECK("input:") COLON_CHECK("input:")
@ -4941,24 +5117,24 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
if (strstr(p, "uinput_reset") == p) { if (strstr(p, "uinput_reset") == p) {
COLON_CHECK("uinput_reset:") COLON_CHECK("uinput_reset:")
p += strlen("uinput_reset:");
if (query) { if (query) {
snprintf(buf, bufn, "ans=%s%s%d", p, co, snprintf(buf, bufn, "ans=%s%s%d", p, co,
get_uinput_reset()); get_uinput_reset());
goto qry; goto qry;
} }
p += strlen("uinput_reset:");
rfbLog("set_uinput_reset: %s\n", p); rfbLog("set_uinput_reset: %s\n", p);
set_uinput_reset(atoi(p)); set_uinput_reset(atoi(p));
goto done; goto done;
} }
if (strstr(p, "uinput_always") == p) { if (strstr(p, "uinput_always") == p) {
COLON_CHECK("uinput_always:") COLON_CHECK("uinput_always:")
p += strlen("uinput_always:");
if (query) { if (query) {
snprintf(buf, bufn, "ans=%s%s%d", p, co, snprintf(buf, bufn, "ans=%s%s%d", p, co,
get_uinput_always()); get_uinput_always());
goto qry; goto qry;
} }
p += strlen("uinput_always:");
rfbLog("set_uinput_always: %s\n", p); rfbLog("set_uinput_always: %s\n", p);
set_uinput_always(atoi(p)); set_uinput_always(atoi(p));
goto done; goto done;
@ -5002,7 +5178,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "ans=%s:%d", p, (ls > -1)); snprintf(buf, bufn, "ans=%s:%d", p, (ls > -1));
goto qry; goto qry;
} }
if (screen->httpListenSock > -1) { if (screen->httpListenSock > -1 || ipv6_http_fd > -1) {
rfbLog("already listening for http connections.\n"); rfbLog("already listening for http connections.\n");
} else { } else {
rfbLog("turning on listening for http connections.\n"); rfbLog("turning on listening for http connections.\n");
@ -5018,7 +5194,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "ans=%s:%d", p, !(ls > -1)); snprintf(buf, bufn, "ans=%s:%d", p, !(ls > -1));
goto qry; goto qry;
} }
if (screen->httpListenSock < 0) { if (screen->httpListenSock < 0 && ipv6_http_fd < 0) {
rfbLog("already not listening for http connections.\n"); rfbLog("already not listening for http connections.\n");
} else { } else {
rfbLog("turning off listening for http connections.\n"); rfbLog("turning off listening for http connections.\n");
@ -5936,7 +6112,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
grab_state(&ptr_grabbed, &kbd_grabbed); grab_state(&ptr_grabbed, &kbd_grabbed);
snprintf(buf, bufn, "aro=%s:%d,%d", p, ptr_grabbed, kbd_grabbed); snprintf(buf, bufn, "aro=%s:%d,%d", p, ptr_grabbed, kbd_grabbed);
if (dpy) { if (dpy && rc_npieces < 10) {
rfbLog("remote_cmd: ptr,kbd: %s\n", buf); rfbLog("remote_cmd: ptr,kbd: %s\n", buf);
} }
goto qry; goto qry;
@ -5982,7 +6158,9 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} else if (!strcmp(p, "pointer_root")) { /* skip-cmd-list */ } else if (!strcmp(p, "pointer_root")) { /* skip-cmd-list */
snprintf(buf, bufn, "aro=%s:0x%x", p, (unsigned int) r); snprintf(buf, bufn, "aro=%s:0x%x", p, (unsigned int) r);
} }
rfbLog("remote_cmd: %s: %s\n", p, buf); if (rc_npieces < 10) {
rfbLog("remote_cmd: %s: %s\n", p, buf);
}
goto qry; goto qry;
} }
if (!strcmp(p, "bpp")) { if (!strcmp(p, "bpp")) {

@ -1421,7 +1421,7 @@ char *vnc_reflect_guess(char *str, char **raw_fb_addr) {
if (first) { if (first) {
argv[argc++] = "x11vnc_rawfb_vnc"; argv[argc++] = "x11vnc_rawfb_vnc";
if (strstr(hp, "listen") == hp) { if (strstr(hp, "listen") == hp) {
char *q = strchr(hp, ':'); char *q = strrchr(hp, ':');
argv[argc++] = strdup("-listen"); argv[argc++] = strdup("-listen");
if (q) { if (q) {
client->listenPort = atoi(q+1); client->listenPort = atoi(q+1);
@ -3589,12 +3589,54 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
defer_update = screen->deferUpdateTime; defer_update = screen->deferUpdateTime;
} }
rfbInitServer(screen); if (noipv4 || getenv("IPV4_FAILS")) {
rfbBool ap = screen->autoPort;
int port = screen->port;
if (getenv("IPV4_FAILS")) {
rfbLog("TESTING: IPV4_FAILS for rfbInitServer()\n");
}
screen->autoPort = FALSE;
screen->port = 0;
rfbInitServer(screen);
screen->autoPort = ap;
screen->port = port;
} else {
rfbInitServer(screen);
}
if (use_openssl) { if (use_openssl) {
openssl_port(); openssl_port(0);
if (https_port_num >= 0) { if (https_port_num >= 0) {
https_port(); https_port(0);
}
} else {
if (ipv6_listen) {
int fd = -1;
if (screen->port <= 0) {
if (got_rfbport) {
screen->port = got_rfbport_val;
} else {
int ap = 5900;
if (auto_port > 0) {
ap = auto_port;
}
screen->port = find_free_port6(ap, ap+200);
}
}
fd = listen6(screen->port);
if (fd < 0) {
ipv6_listen = 0;
} else {
rfbLog("%slistening on IPv6 port=%d sock=%d\n",
screen->listenSock < 0 ? "Only " : "Also ",
screen->port, fd);
ipv6_listen_fd = fd;
}
} }
} }
@ -3717,7 +3759,8 @@ void do_announce_http(void) {
return; return;
} }
if (screen->httpListenSock > -1 && screen->httpPort) { /* XXX ipv6? */
if ((screen->httpListenSock > -1 || ipv6_http_fd > -1) && screen->httpPort) {
int enc_none = (enc_str && !strcmp(enc_str, "none")); int enc_none = (enc_str && !strcmp(enc_str, "none"));
char *SPORT = " (single port)"; char *SPORT = " (single port)";
if (use_openssl && ! enc_none) { if (use_openssl && ! enc_none) {
@ -3752,6 +3795,7 @@ void do_announce_http(void) {
void do_mention_java_urls(void) { void do_mention_java_urls(void) {
if (! quiet && screen) { if (! quiet && screen) {
/* XXX ipv6? */
if (screen->httpListenSock > -1 && screen->httpPort) { if (screen->httpListenSock > -1 && screen->httpPort) {
rfbLog("\n"); rfbLog("\n");
rfbLog("The URLs printed out below ('Java ... viewer URL') can\n"); rfbLog("The URLs printed out below ('Java ... viewer URL') can\n");

@ -114,7 +114,7 @@ int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport
strcat(path, extra); strcat(path, extra);
} }
exe = (char *) malloc(strlen(path) + 1 + strlen("stunnel") + 1); exe = (char *) malloc(strlen(path) + 1 + strlen("stunnel4") + 1);
p = strtok(path, ":"); p = strtok(path, ":");
@ -123,6 +123,14 @@ int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport
while (p) { while (p) {
struct stat sbuf; struct stat sbuf;
sprintf(exe, "%s/%s", p, "stunnel4");
if (! stunnel_path && stat(exe, &sbuf) == 0) {
if (! S_ISDIR(sbuf.st_mode)) {
stunnel_path = exe;
break;
}
}
sprintf(exe, "%s/%s", p, "stunnel"); sprintf(exe, "%s/%s", p, "stunnel");
if (! stunnel_path && stat(exe, &sbuf) == 0) { if (! stunnel_path && stat(exe, &sbuf) == 0) {
if (! S_ISDIR(sbuf.st_mode)) { if (! S_ISDIR(sbuf.st_mode)) {
@ -137,6 +145,12 @@ int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport
free(path); free(path);
} }
if (getenv("STUNNEL_PROG")) {
free(exe);
exe = strdup(getenv("STUNNEL_PROG"));
stunnel_path = exe;
}
if (! stunnel_path) { if (! stunnel_path) {
free(exe); free(exe);
return 0; return 0;
@ -219,6 +233,15 @@ int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport
FILE *in; FILE *in;
char fd[20]; char fd[20];
int i; int i;
char *st_if = getenv("STUNNEL_LISTEN");
if (st_if == NULL) {
st_if = "";
} else {
st_if = (char *) malloc(strlen(st_if) + 2);
sprintf(st_if, "%s:", getenv("STUNNEL_LISTEN"));
}
for (i=3; i<256; i++) { for (i=3; i<256; i++) {
close(i); close(i);
@ -293,12 +316,12 @@ int start_stunnel(int stunnel_port, int x11vnc_port, int hport, int x11vnc_hport
} }
fprintf(in, ";debug = 7\n\n"); fprintf(in, ";debug = 7\n\n");
fprintf(in, "[x11vnc_stunnel]\n"); fprintf(in, "[x11vnc_stunnel]\n");
fprintf(in, "accept = %d\n", stunnel_port); fprintf(in, "accept = %s%d\n", st_if, stunnel_port);
fprintf(in, "connect = %d\n", x11vnc_port); fprintf(in, "connect = %d\n", x11vnc_port);
if (hport > 0 && x11vnc_hport > 0) { if (hport > 0 && x11vnc_hport > 0) {
fprintf(in, "\n[x11vnc_http]\n"); fprintf(in, "\n[x11vnc_http]\n");
fprintf(in, "accept = %d\n", hport); fprintf(in, "accept = %s%d\n", st_if, hport);
fprintf(in, "connect = %d\n", x11vnc_hport); fprintf(in, "connect = %d\n", x11vnc_hport);
} }

@ -42,10 +42,12 @@ so, delete this exception statement from your version.
#include "unixpw.h" #include "unixpw.h"
#include "user.h" #include "user.h"
#define OPENSSL_INETD 1 #define OPENSSL_INETD 1
#define OPENSSL_VNC 2 #define OPENSSL_VNC 2
#define OPENSSL_HTTPS 3 #define OPENSSL_VNC6 3
#define OPENSSL_REVERSE 4 #define OPENSSL_HTTPS 4
#define OPENSSL_HTTPS6 5
#define OPENSSL_REVERSE 6
#define DO_DH 0 #define DO_DH 0
@ -56,8 +58,10 @@ so, delete this exception statement from your version.
#endif #endif
int openssl_sock = -1; int openssl_sock = -1;
int openssl_sock6 = -1;
int openssl_port_num = 0; int openssl_port_num = 0;
int https_sock = -1; int https_sock = -1;
int https_sock6 = -1;
pid_t openssl_last_helper_pid = 0; pid_t openssl_last_helper_pid = 0;
char *openssl_last_ip = NULL; char *openssl_last_ip = NULL;
@ -658,8 +662,8 @@ char *get_ssl_verify_file(char *str_in) {
int openssl_present(void); int openssl_present(void);
void openssl_init(int isclient); void openssl_init(int isclient);
void openssl_port(void); void openssl_port(int restart);
void https_port(void); void https_port(int restart);
void check_openssl(void); void check_openssl(void);
void check_https(void); void check_https(void);
void ssl_helper_pid(pid_t pid, int sock); void ssl_helper_pid(pid_t pid, int sock);
@ -1989,6 +1993,10 @@ static int ssl_init(int s_in, int s_out, int skip_vnc_tls, double last_https) {
name = get_remote_host(ssock); name = get_remote_host(ssock);
peerport = get_remote_port(ssock); peerport = get_remote_port(ssock);
if (!strcmp(name, "0.0.0.0") && openssl_last_ip != NULL) {
name = strdup(openssl_last_ip);
}
if (db > 1) fprintf(stderr, "ssl_init: 4\n"); if (db > 1) fprintf(stderr, "ssl_init: 4\n");
while (1) { while (1) {
@ -2593,7 +2601,7 @@ static void init_prng(void) {
void check_openssl(void) { void check_openssl(void) {
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
int nfds; int nfds, nmax = openssl_sock;
static time_t last_waitall = 0; static time_t last_waitall = 0;
static double last_check = 0.0; static double last_check = 0.0;
double now; double now;
@ -2607,7 +2615,7 @@ void check_openssl(void) {
ssl_helper_pid(0, -2); /* waitall */ ssl_helper_pid(0, -2); /* waitall */
} }
if (openssl_sock < 0) { if (openssl_sock < 0 && openssl_sock6 < 0) {
return; return;
} }
@ -2618,29 +2626,43 @@ void check_openssl(void) {
last_check = now; last_check = now;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(openssl_sock, &fds); if (openssl_sock >= 0) {
FD_SET(openssl_sock, &fds);
}
if (openssl_sock6 >= 0) {
FD_SET(openssl_sock6, &fds);
if (openssl_sock6 > openssl_sock) {
nmax = openssl_sock6;
}
}
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
nfds = select(openssl_sock+1, &fds, NULL, NULL, &tv); nfds = select(nmax+1, &fds, NULL, NULL, &tv);
if (nfds <= 0) { if (nfds <= 0) {
return; return;
} }
rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n"); if (openssl_sock >= 0 && FD_ISSET(openssl_sock, &fds)) {
accept_openssl(OPENSSL_VNC, -1); rfbLog("SSL: accept_openssl(OPENSSL_VNC)\n");
accept_openssl(OPENSSL_VNC, -1);
}
if (openssl_sock6 >= 0 && FD_ISSET(openssl_sock6, &fds)) {
rfbLog("SSL: accept_openssl(OPENSSL_VNC6)\n");
accept_openssl(OPENSSL_VNC6, -1);
}
} }
void check_https(void) { void check_https(void) {
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
int nfds; int nfds, nmax = https_sock;
static double last_check = 0.0; static double last_check = 0.0;
double now; double now;
if (! use_openssl || https_sock < 0) { if (! use_openssl || (https_sock < 0 && https_sock6 < 0)) {
return; return;
} }
@ -2651,25 +2673,40 @@ void check_https(void) {
last_check = now; last_check = now;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(https_sock, &fds); if (https_sock >= 0) {
FD_SET(https_sock, &fds);
}
if (https_sock6 >= 0) {
FD_SET(https_sock6, &fds);
if (https_sock6 > https_sock) {
nmax = https_sock6;
}
}
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
nfds = select(https_sock+1, &fds, NULL, NULL, &tv); nfds = select(nmax+1, &fds, NULL, NULL, &tv);
if (nfds <= 0) { if (nfds <= 0) {
return; return;
} }
rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
accept_openssl(OPENSSL_HTTPS, -1); if (https_sock >= 0 && FD_ISSET(https_sock, &fds)) {
rfbLog("SSL: accept_openssl(OPENSSL_HTTPS)\n");
accept_openssl(OPENSSL_HTTPS, -1);
}
if (https_sock6 >= 0 && FD_ISSET(https_sock6, &fds)) {
rfbLog("SSL: accept_openssl(OPENSSL_HTTPS6)\n");
accept_openssl(OPENSSL_HTTPS6, -1);
}
} }
void openssl_port(void) { void openssl_port(int restart) {
int sock = -1, shutdown = 0; int sock = -1, shutdown = 0;
static int port = -1; static int port = -1;
static in_addr_t iface = INADDR_ANY; static in_addr_t iface = INADDR_ANY;
int db = 0; int db = 0, fd6 = -1;
if (! screen) { if (! screen) {
rfbLog("openssl_port: no screen!\n"); rfbLog("openssl_port: no screen!\n");
@ -2680,15 +2717,18 @@ void openssl_port(void) {
return; return;
} }
if (screen->listenSock > -1 && screen->port > 0) { if (restart) {
port = screen->port;
} else if (screen->listenSock > -1 && screen->port > 0) {
port = screen->port; port = screen->port;
shutdown = 1; shutdown = 1;
} else if (ipv6_listen && screen->port > 0) {
port = screen->port;
} else if (screen->port == 0) { } else if (screen->port == 0) {
port = screen->port; port = screen->port;
} }
if (screen->listenInterface) {
iface = screen->listenInterface; iface = screen->listenInterface;
}
if (shutdown) { if (shutdown) {
if (db) fprintf(stderr, "shutting down %d/%d\n", if (db) fprintf(stderr, "shutting down %d/%d\n",
@ -2698,21 +2738,56 @@ void openssl_port(void) {
#endif #endif
} }
if (openssl_sock >= 0) {
close(openssl_sock);
openssl_sock = -1;
}
if (openssl_sock6 >= 0) {
close(openssl_sock6);
openssl_sock6 = -1;
}
if (port < 0) { if (port < 0) {
rfbLog("openssl_port: could not obtain listening port %d\n", port); rfbLog("openssl_port: could not obtain listening port %d\n", port);
if (!got_rfbport && !ipv6_listen) {
rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
}
clean_up_exit(1); clean_up_exit(1);
} else if (port == 0) { } else if (port == 0) {
/* no listen case, i.e. -connect */ /* no listen case, i.e. -connect */
sock = -1; sock = -1;
} else { } else {
sock = rfbListenOnTCPPort(port, iface); sock = listen_tcp(port, iface, 0);
if (ipv6_listen) {
fd6 = listen6(port);
} else if (!got_rfbport) {
rfbLog("openssl_port: if this system is IPv6-only, use the -6 option\n");
}
if (sock < 0) { if (sock < 0) {
rfbLog("openssl_port: could not reopen port %d\n", port); if (fd6 < 0) {
clean_up_exit(1); rfbLog("openssl_port: could not reopen port %d\n", port);
if (!restart) {
clean_up_exit(1);
}
} else {
rfbLog("openssl_port: Info: only listening on IPv6\n");
}
} }
} }
rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock); rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock);
if (!quiet) { if (ipv6_listen && port > 0) {
if (fd6 < 0) {
fd6 = listen6(port);
}
if (fd6 < 0) {
ipv6_listen = 0;
} else {
rfbLog("openssl_port: listen on port/sock %d/%d (ipv6)\n",
port, fd6);
openssl_sock6 = fd6;
}
}
if (!quiet && sock >=0) {
announce(port, 1, NULL); announce(port, 1, NULL);
} }
openssl_sock = sock; openssl_sock = sock;
@ -2721,11 +2796,10 @@ void openssl_port(void) {
ssl_initialized = 1; ssl_initialized = 1;
} }
void https_port(void) { void https_port(int restart) {
int sock; int sock, fd6 = -1;
static int port = 0; static int port = 0;
static in_addr_t iface = INADDR_ANY; static in_addr_t iface = INADDR_ANY;
int db = 0;
/* as openssl_port above: open a listening socket for pure https: */ /* as openssl_port above: open a listening socket for pure https: */
if (https_port_num < 0) { if (https_port_num < 0) {
@ -2735,6 +2809,9 @@ void https_port(void) {
rfbLog("https_port: no screen!\n"); rfbLog("https_port: no screen!\n");
clean_up_exit(1); clean_up_exit(1);
} }
if (! screen->httpDir) {
return;
}
if (screen->listenInterface) { if (screen->listenInterface) {
iface = screen->listenInterface; iface = screen->listenInterface;
} }
@ -2742,6 +2819,9 @@ void https_port(void) {
if (https_port_num == 0) { if (https_port_num == 0) {
https_port_num = find_free_port(5801, 5851); https_port_num = find_free_port(5801, 5851);
} }
if (ipv6_listen && https_port_num <= 0) {
https_port_num = find_free_port6(5801, 5851);
}
if (https_port_num <= 0) { if (https_port_num <= 0) {
rfbLog("https_port: could not find port %d\n", https_port_num); rfbLog("https_port: could not find port %d\n", https_port_num);
clean_up_exit(1); clean_up_exit(1);
@ -2750,17 +2830,54 @@ void https_port(void) {
if (port <= 0) { if (port <= 0) {
rfbLog("https_port: could not obtain listening port %d\n", port); rfbLog("https_port: could not obtain listening port %d\n", port);
clean_up_exit(1); if (!restart) {
clean_up_exit(1);
} else {
return;
}
}
if (https_sock >= 0) {
close(https_sock);
https_sock = -1;
} }
sock = rfbListenOnTCPPort(port, iface); if (https_sock6 >= 0) {
close(https_sock6);
https_sock6 = -1;
}
sock = listen_tcp(port, iface, 0);
if (sock < 0) { if (sock < 0) {
rfbLog("https_port: could not open port %d\n", port); rfbLog("https_port: could not open port %d\n", port);
clean_up_exit(1); if (ipv6_listen) {
fd6 = listen6(port);
}
if (fd6 < 0) {
if (!restart) {
clean_up_exit(1);
}
}
rfbLog("https_port: trying IPv6 only mode.\n");
} }
if (db) fprintf(stderr, "https_port: listen on port/sock %d/%d\n", rfbLog("https_port: listen on port/sock %d/%d\n", port, sock);
port, sock);
https_sock = sock; https_sock = sock;
if (ipv6_listen) {
if (fd6 < 0) {
fd6 = listen6(port);
}
if (fd6 < 0) {
;
} else {
rfbLog("https_port: listen on port/sock %d/%d (ipv6)\n",
port, fd6);
https_sock6 = fd6;
}
if (fd6 < 0 && https_sock < 0) {
rfbLog("https_port: could not listen on either IPv4 or IPv6.\n");
if (!restart) {
clean_up_exit(1);
}
}
}
} }
static void lose_ram(void) { static void lose_ram(void) {
@ -3095,6 +3212,7 @@ void accept_openssl(int mode, int presock) {
char cookie[256], rcookie[256], *name = NULL; char cookie[256], rcookie[256], *name = NULL;
int vencrypt_sel = 0; int vencrypt_sel = 0;
int anontls_sel = 0; int anontls_sel = 0;
char *ipv6_name = NULL;
static double last_https = 0.0; static double last_https = 0.0;
static char last_get[256]; static char last_get[256];
static int first = 1; static int first = 1;
@ -3138,6 +3256,25 @@ void accept_openssl(int mode, int presock) {
} }
listen = openssl_sock; listen = openssl_sock;
} else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
#if X11VNC_IPV6
struct sockaddr_in6 a6;
socklen_t a6len = sizeof(a6);
int fd = (mode == OPENSSL_VNC6 ? openssl_sock6 : https_sock6);
sock = accept(fd, (struct sockaddr *)&a6, &a6len);
if (sock < 0) {
rfbLog("SSL: accept_openssl: accept connection failed\n");
rfbLogPerror("accept");
if (ssl_no_fail) {
clean_up_exit(1);
}
return;
}
ipv6_name = ipv6_getipaddr((struct sockaddr *)&a6, a6len);
if (!ipv6_name) ipv6_name = strdup("unknown");
listen = fd;
#endif
} else if (mode == OPENSSL_REVERSE) { } else if (mode == OPENSSL_REVERSE) {
sock = presock; sock = presock;
if (sock < 0) { if (sock < 0) {
@ -3147,6 +3284,10 @@ void accept_openssl(int mode, int presock) {
} }
return; return;
} }
if (getenv("OPENSSL_REVERSE_DEBUG")) fprintf(stderr, "OPENSSL_REVERSE: ipv6_client_ip_str: %s\n", ipv6_client_ip_str);
if (ipv6_client_ip_str != NULL) {
ipv6_name = strdup(ipv6_client_ip_str);
}
listen = -1; listen = -1;
} else if (mode == OPENSSL_HTTPS) { } else if (mode == OPENSSL_HTTPS) {
@ -3169,13 +3310,17 @@ void accept_openssl(int mode, int presock) {
} }
if (mode == OPENSSL_INETD) { if (mode == OPENSSL_INETD) {
openssl_last_ip = get_remote_host(fileno(stdin)); openssl_last_ip = get_remote_host(fileno(stdin));
} else if (mode == OPENSSL_VNC6 || mode == OPENSSL_HTTPS6) {
openssl_last_ip = ipv6_name;
} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
openssl_last_ip = ipv6_name;
} else { } else {
openssl_last_ip = get_remote_host(sock); openssl_last_ip = get_remote_host(sock);
} }
if (!check_ssl_access(openssl_last_ip)) { if (!check_ssl_access(openssl_last_ip)) {
rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip); rfbLog("SSL: accept_openssl: denying client %s\n", openssl_last_ip);
rfbLog("SSL: accept_openssl: does not match -allow (or other reason).\n"); rfbLog("SSL: accept_openssl: does not match -allow or other reason.\n");
close(sock); close(sock);
sock = -1; sock = -1;
if (ssl_no_fail) { if (ssl_no_fail) {
@ -3186,7 +3331,12 @@ void accept_openssl(int mode, int presock) {
/* now make a listening socket for child to connect back to us by: */ /* now make a listening socket for child to connect back to us by: */
cport = find_free_port(20000, 0); cport = find_free_port(20000, 22000);
if (! cport && ipv6_listen) {
rfbLog("SSL: accept_openssl: seeking IPv6 port.\n");
cport = find_free_port6(20000, 22000);
rfbLog("SSL: accept_openssl: IPv6 port: %d\n", cport);
}
if (! cport) { if (! cport) {
rfbLog("SSL: accept_openssl: could not find open port.\n"); rfbLog("SSL: accept_openssl: could not find open port.\n");
close(sock); close(sock);
@ -3197,7 +3347,7 @@ void accept_openssl(int mode, int presock) {
} }
if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport); if (db) fprintf(stderr, "accept_openssl: cport: %d\n", cport);
csock = rfbListenOnTCPPort(cport, htonl(INADDR_LOOPBACK)); csock = listen_tcp(cport, htonl(INADDR_LOOPBACK), 1);
if (csock < 0) { if (csock < 0) {
rfbLog("SSL: accept_openssl: could not listen on port %d.\n", rfbLog("SSL: accept_openssl: could not listen on port %d.\n",
@ -3225,7 +3375,13 @@ void accept_openssl(int mode, int presock) {
rb[0], rb[1], rb[2], rb[3], rb[4], rb[5], rb[0], rb[1], rb[2], rb[3], rb[4], rb[5],
dnow() - x11vnc_start, x11vnc_start, (void *)rb); dnow() - x11vnc_start, x11vnc_start, (void *)rb);
if (mode != OPENSSL_INETD) { if (mode == OPENSSL_VNC6) {
name = strdup(ipv6_name);
peerport = get_remote_port(sock);
} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL) {
name = strdup(ipv6_name);
peerport = get_remote_port(sock);
} else if (mode != OPENSSL_INETD) {
name = get_remote_host(sock); name = get_remote_host(sock);
peerport = get_remote_port(sock); peerport = get_remote_port(sock);
} else { } else {
@ -3338,7 +3494,7 @@ void accept_openssl(int mode, int presock) {
lose_ram(); lose_ram();
/* now connect back to parent socket: */ /* now connect back to parent socket: */
vncsock = rfbConnectToTcpAddr("127.0.0.1", cport); vncsock = connect_tcp("127.0.0.1", cport);
if (vncsock < 0) { if (vncsock < 0) {
rfbLog("SSL: ssl_helper[%d]: could not connect" rfbLog("SSL: ssl_helper[%d]: could not connect"
" back to: %d\n", getpid(), cport); " back to: %d\n", getpid(), cport);
@ -3388,8 +3544,9 @@ void accept_openssl(int mode, int presock) {
} }
if (screen->httpListenSock >= 0 && screen->httpPort > 0) { if (screen->httpListenSock >= 0 && screen->httpPort > 0) {
have_httpd = 1; have_httpd = 1;
} } else if (ipv6_http_fd >= 0) {
if (screen->httpListenSock == -2) { have_httpd = 1;
} else if (screen->httpListenSock == -2) {
have_httpd = 1; have_httpd = 1;
} }
if (mode == OPENSSL_HTTPS && ! have_httpd) { if (mode == OPENSSL_HTTPS && ! have_httpd) {
@ -3614,7 +3771,7 @@ void accept_openssl(int mode, int presock) {
if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport); if (db) fprintf(stderr, "iface: %s:%d\n", iface, hport);
usleep(150*1000); usleep(150*1000);
httpsock = rfbConnectToTcpAddr(iface, hport); httpsock = connect_tcp(iface, hport);
if (httpsock < 0) { if (httpsock < 0) {
/* UGH, after all of that! */ /* UGH, after all of that! */
@ -3962,6 +4119,18 @@ void accept_openssl(int mode, int presock) {
openssl_last_helper_pid = 0; openssl_last_helper_pid = 0;
if (client) { if (client) {
int swt = 0;
if (mode == OPENSSL_VNC6 && openssl_last_ip != NULL) {
swt = 1;
} else if (mode == OPENSSL_REVERSE && ipv6_name != NULL && openssl_last_ip != NULL) {
swt = 1;
}
if (swt) {
if (client->host) {
free(client->host);
}
client->host = strdup(openssl_last_ip);
}
if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client); if (db) fprintf(stderr, "accept_openssl: client %p\n", (void *) client);
if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook); if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) screen->newClientHook);
if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client); if (db) fprintf(stderr, "accept_openssl: new_client %p\n", (void *) new_client);

@ -38,12 +38,16 @@ so, delete this exception statement from your version.
#define OPENSSL_INETD 1 #define OPENSSL_INETD 1
#define OPENSSL_VNC 2 #define OPENSSL_VNC 2
#define OPENSSL_HTTPS 3 #define OPENSSL_VNC6 3
#define OPENSSL_REVERSE 4 #define OPENSSL_HTTPS 4
#define OPENSSL_HTTPS6 5
#define OPENSSL_REVERSE 6
extern int openssl_sock; extern int openssl_sock;
extern int openssl_sock6;
extern int openssl_port_num; extern int openssl_port_num;
extern int https_sock; extern int https_sock;
extern int https_sock6;
extern pid_t openssl_last_helper_pid; extern pid_t openssl_last_helper_pid;
extern char *openssl_last_ip; extern char *openssl_last_ip;
extern char *certret_str; extern char *certret_str;
@ -54,8 +58,8 @@ extern void raw_xfer(int csock, int s_in, int s_out);
extern int openssl_present(void); extern int openssl_present(void);
extern void openssl_init(int); extern void openssl_init(int);
extern void openssl_port(void); extern void openssl_port(int);
extern void https_port(void); extern void https_port(int);
extern void check_openssl(void); extern void check_openssl(void);
extern void check_https(void); extern void check_https(void);
extern void ssl_helper_pid(pid_t pid, int sock); extern void ssl_helper_pid(pid_t pid, int sock);

@ -789,6 +789,7 @@ char find_display[] =
" exit 1\n" " exit 1\n"
"fi\n" "fi\n"
"\n" "\n"
"# Set PATH to pick up utilities we use below.\n"
"PATH=$PATH:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/ucb\n" "PATH=$PATH:/bin:/usr/bin:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/ucb\n"
"export PATH\n" "export PATH\n"
"\n" "\n"
@ -1823,6 +1824,10 @@ char create_display[] =
" chmod 755 $stmp || exit 1\n" " chmod 755 $stmp || exit 1\n"
" echo \"#!/bin/sh\" > $stmp\n" " echo \"#!/bin/sh\" > $stmp\n"
" #echo \"(id; env; env | grep XAUTHORITY | sed -e 's/XAUTHORITY=//' | xargs ls -l) > /tmp/ENV.OUT.$$\" >> $stmp\n" " #echo \"(id; env; env | grep XAUTHORITY | sed -e 's/XAUTHORITY=//' | xargs ls -l) > /tmp/ENV.OUT.$$\" >> $stmp\n"
" if [ \"X$SAVE_PATH\" != \"X\" ]; then\n"
" echo \"PATH=\\\"$SAVE_PATH\\\"\" >> $stmp\n"
" echo \"export PATH\" >> $stmp\n"
" fi\n"
" if [ \"X$noxauth\" = \"X1\" ]; then\n" " if [ \"X$noxauth\" = \"X1\" ]; then\n"
" echo \"unset XAUTHORITY\" >> $stmp\n" " echo \"unset XAUTHORITY\" >> $stmp\n"
" fi\n" " fi\n"
@ -1971,25 +1976,6 @@ char create_display[] =
" fi\n" " fi\n"
" done\n" " done\n"
"\n" "\n"
"# if [ \"X$result\" = \"X1\" ]; then\n"
"# if [ \"X$use_xdmcp_query\" = \"X0\" -a \"X$have_xdpyinfo\" != \"X\" ]; then\n"
"# ok=0\n"
"# for t in 1 2 3 4\n"
"# do\n"
"# $have_xdpyinfo >/dev/null 2>&1\n"
"# if [ $? != 0 ]; then\n"
"# sleep 1\n"
"# else\n"
"# ok=1\n"
"# break;\n"
"# fi\n"
"# done\n"
"# if [ \"X$ok\" = \"X0\" ]; then\n"
"# result=0\n"
"# fi\n"
"# fi\n"
"# fi\n"
"\n"
" if [ \"X$redir_daemon\" != \"X\" -a \"X$result\" = \"X1\" ]; then\n" " if [ \"X$redir_daemon\" != \"X\" -a \"X$result\" = \"X1\" ]; then\n"
" redir_daemon=`echo \"$redir_daemon\" | sed -e 's/[~!$&*()|;?<>\"]//g' -e \"s/'//g\"`\n" " redir_daemon=`echo \"$redir_daemon\" | sed -e 's/[~!$&*()|;?<>\"]//g' -e \"s/'//g\"`\n"
" xprog=$X11VNC_PROG\n" " xprog=$X11VNC_PROG\n"
@ -2276,6 +2262,8 @@ char create_display[] =
" USER=`whoami`\n" " USER=`whoami`\n"
"fi\n" "fi\n"
"\n" "\n"
"# Set PATH to have a better chance of finding things:\n"
"SAVE_PATH=$PATH\n"
"PATH=$PATH:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde4/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin:/usr/local/bin\n" "PATH=$PATH:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde4/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin:/usr/local/bin\n"
"\n" "\n"
"have_root=\"\"\n" "have_root=\"\"\n"

@ -268,6 +268,10 @@ Misc
macmenu macmenu
=GAL LOFF =GAL LOFF
-- --
6
noipv6
noipv4
--
nofb nofb
=D nobell =D nobell
nolookup nolookup
@ -2754,6 +2758,7 @@ proc update_menu_vars {{query ""}} {
set x11vnc_icon_mode 1 set x11vnc_icon_mode 1
#puts stderr "x11vnc_icon_mode: $x11vnc_icon_mode" #puts stderr "x11vnc_icon_mode: $x11vnc_icon_mode"
} }
# XXX ipv6
if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} { if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} {
if {[info exists menu_var($item)]} { if {[info exists menu_var($item)]} {
set old $menu_var($item) set old $menu_var($item)

@ -279,6 +279,10 @@ char gui_code[] = "";
" macmenu\n" " macmenu\n"
" =GAL LOFF\n" " =GAL LOFF\n"
" --\n" " --\n"
" 6\n"
" noipv6\n"
" noipv4\n"
" --\n"
" nofb\n" " nofb\n"
" =D nobell\n" " =D nobell\n"
" nolookup\n" " nolookup\n"
@ -2765,6 +2769,7 @@ char gui_code[] = "";
" set x11vnc_icon_mode 1\n" " set x11vnc_icon_mode 1\n"
" #puts stderr \"x11vnc_icon_mode: $x11vnc_icon_mode\"\n" " #puts stderr \"x11vnc_icon_mode: $x11vnc_icon_mode\"\n"
" }\n" " }\n"
" # XXX ipv6\n"
" if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} {\n" " if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} {\n"
" if {[info exists menu_var($item)]} {\n" " if {[info exists menu_var($item)]} {\n"
" set old $menu_var($item)\n" " set old $menu_var($item)\n"

@ -1180,9 +1180,11 @@ static void handle_one_http_request(void) {
screen->port = 0; screen->port = 0;
http_connections(1); http_connections(1);
rfbInitServer(screen); rfbInitServer(screen);
if (!inetd) { if (!inetd) {
/* XXX ipv6 */
int conn = 0; int conn = 0;
while (1) { while (1) {
if (0) fprintf(stderr, "%d %d %d %d\n", conn, screen->listenSock, screen->httpSock, screen->httpListenSock); if (0) fprintf(stderr, "%d %d %d %d\n", conn, screen->listenSock, screen->httpSock, screen->httpListenSock);
@ -1234,8 +1236,7 @@ static void handle_one_http_request(void) {
rfbLog("handle_one_http_request: finished.\n"); rfbLog("handle_one_http_request: finished.\n");
return; return;
} else { } else {
int sock = rfbConnectToTcpAddr("127.0.0.1", int sock = connect_tcp("127.0.0.1", screen->httpPort);
screen->httpPort);
if (sock < 0) { if (sock < 0) {
exit(1); exit(1);
} }
@ -1703,6 +1704,7 @@ static void vnc_redirect_loop(char *vnc_redirect_test, int *vnc_redirect_cnt) {
} }
} else { } else {
pid_t pid = 0; pid_t pid = 0;
/* XXX ipv6 */
if (screen->httpListenSock >= 0) { if (screen->httpListenSock >= 0) {
#if LIBVNCSERVER_HAVE_FORK #if LIBVNCSERVER_HAVE_FORK
if ((pid = fork()) > 0) { if ((pid = fork()) > 0) {
@ -1817,7 +1819,7 @@ static void vnc_redirect_loop(char *vnc_redirect_test, int *vnc_redirect_cnt) {
static void do_vnc_redirect(int created_disp, char *vnc_redirect_host, int vnc_redirect_port, static void do_vnc_redirect(int created_disp, char *vnc_redirect_host, int vnc_redirect_port,
int vnc_redirect_cnt, char *vnc_redirect_test) { int vnc_redirect_cnt, char *vnc_redirect_test) {
char *q = strchr(use_dpy, ':'); char *q = strrchr(use_dpy, ':');
int vdpy = -1, sock = -1; int vdpy = -1, sock = -1;
int s_in, s_out, i; int s_in, s_out, i;
if (vnc_redirect == 2) { if (vnc_redirect == 2) {
@ -1850,7 +1852,7 @@ static void do_vnc_redirect(int created_disp, char *vnc_redirect_host, int vnc_r
usleep(1000*1000); usleep(1000*1000);
} }
for (i=0; i < 20; i++) { for (i=0; i < 20; i++) {
sock = rfbConnectToTcpAddr(vnc_redirect_host, vdpy); sock = connect_tcp(vnc_redirect_host, vdpy);
if (sock >= 0) { if (sock >= 0) {
break; break;
} }
@ -2993,9 +2995,14 @@ int wait_for_client(int *argc, char** argv, int http) {
if (! screen->port || screen->listenSock < 0) { if (! screen->port || screen->listenSock < 0) {
if (got_rfbport && got_rfbport_val == 0) { if (got_rfbport && got_rfbport_val == 0) {
; ;
} else if (ipv6_listen && ipv6_listen_fd >= 0) {
rfbLog("Info: listening only on IPv6 interface.\n");
} else { } else {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("Error: could not obtain listening port.\n"); rfbLog("Error: could not obtain listening port.\n");
if (!got_rfbport) {
rfbLog("If this system is IPv6-only, use the -6 option.\n");
}
clean_up_exit(1); clean_up_exit(1);
} }
} }

@ -495,7 +495,7 @@ void check_allinput_rate(void) {
if (verb) rfbLog("check_allinput_rate:\n"); if (verb) rfbLog("check_allinput_rate:\n");
if (verb) rfbLog("Client is sending %.1f extra requests per second for the\n", rate); if (verb) rfbLog("Client is sending %.1f extra requests per second for the\n", rate);
if (verb) rfbLog("past %d seconds! (queued: %d)\n", dt, nq); if (verb) rfbLog("past %d seconds! (queued: %d)\n", dt, nq);
if (strstr(getenv("CHECK_RATE"), "allinput") && !all_input) { if (strstr(getenv("CHECK_RATE"), "allinput") && !all_input && !handle_events_eagerly) {
rfbLog("Switching to -allpinput mode.\n"); rfbLog("Switching to -allpinput mode.\n");
all_input = 1; all_input = 1;
} }
@ -590,6 +590,9 @@ int rfbPE(long usec) {
} }
} }
if (ipv6_listen) {
check_ipv6_listen(usec);
}
if (check_rate != 0) { if (check_rate != 0) {
if (check_rate < 0) { if (check_rate < 0) {
if (getenv("CHECK_RATE")) { if (getenv("CHECK_RATE")) {
@ -643,8 +646,7 @@ void rfbCFD(long usec) {
if (all_input) { if (all_input) {
do_allinput(usec); do_allinput(usec);
} else { } else {
/* XXX how for cmdline? */ if (handle_events_eagerly) {
if (all_input) {
screen->handleEventsEagerly = TRUE; screen->handleEventsEagerly = TRUE;
} else { } else {
screen->handleEventsEagerly = FALSE; screen->handleEventsEagerly = FALSE;

@ -1,8 +1,8 @@
.\" This file was automatically generated from x11vnc -help output. .\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "March 2010" "x11vnc " "User Commands" .TH X11VNC "1" "April 2010" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.9.10, lastmod: 2010-03-20 version: 0.9.10, lastmod: 2010-04-08
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
@ -110,6 +110,38 @@ The VNC port to listen on (a libvncserver option), e.g.
then the x11vnc \fB-gui\fR is used to prompt the user to then the x11vnc \fB-gui\fR is used to prompt the user to
enter the port number. enter the port number.
.PP .PP
\fB-6\fR
.IP
IPv6 listening support. In addition to IPv4, the
IPv6 address is listened on for incoming connections.
The same port as IPv4 is used to listen. If you have
trouble compiling for this mode, set \fB-DX11VNC_IPV6=0\fR
in CPPFLAGS when configuring.
.IP
Currently, the machine may need to have some IPv4
support, at the least for the loopback interface, for
everything to work correctly. However for most usage
modes IPv4 support is not required.
.IP
The -6 mode works for both normal connections and
\fB-ssl\fR encrypted ones. Nearly everything is supported
for the IPv6 case, but there are a few exceptions.
See \fB-stunnel\fR for its IPv6 support.
.PP
\fB-noipv6\fR
.IP
Do not try to use IPv6 for any listening or connecting
sockets. This includes both the listening service
port(s) and outgoing connections from \fB-connect,\fR
\fB-connect_or_exit,\fR or \fB-proxy.\fR Use this if you are having
problems due to IPv6.
.PP
\fB-noipv4\fR
.IP
Do not try to use IPv4 for any listening or connecting
sockets. This is mainly for exploring the behavior of
x11vnc on an IPv6-only system, but may have other uses.
.PP
\fB-reopen\fR \fB-reopen\fR
.IP .IP
If the X server connection is disconnected, try to If the X server connection is disconnected, try to
@ -651,6 +683,13 @@ newline and carriage return. "\\c" is expanded to
.IP .IP
See also the \fB-proxy\fR option below for additional ways See also the \fB-proxy\fR option below for additional ways
to plumb reverse connections. to plumb reverse connections.
.IP
IPv6: as of x11vnc 0.9.10 the \fB-connect\fR option should
connect to IPv6 hosts properly. If there are problems
you can disable IPv6 by setting \fB-DX11VNC_IPV6=0\fR
in CPPFLAGS when configuring. If there problems
connecting to IPv6 hosts consider a relay like the
included inet6to4 script or the \fB-proxy\fR option.
.PP .PP
\fB-connect_or_exit\fR \fIstr\fR \fB-connect_or_exit\fR \fIstr\fR
.IP .IP
@ -720,6 +759,13 @@ reach the VNC viewer. Up to 3 may be chained, separate
them by commas in the order they are to be connected to. them by commas in the order they are to be connected to.
E.g.: http://host1:port1,socks5://host2:port2 or three E.g.: http://host1:port1,socks5://host2:port2 or three
like: first,second,third like: first,second,third
.IP
IPv6: as of x11vnc 0.9.10 the \fB-proxy\fR option should
connect to IPv6 hosts properly. If there are problems
you can disable IPv6 by setting \fB-DX11VNC_IPV6=0\fR
in CPPFLAGS when configuring. If there problems
connecting to IPv6 hosts consider a relay like the
included inet6to4 script.
.PP .PP
\fB-vncconnect,\fR \fB-novncconnect\fR \fB-vncconnect,\fR \fB-novncconnect\fR
.IP .IP
@ -757,6 +803,9 @@ re-read each time a new client connects. Lines can be
commented out with the "#" character in the usual way. commented out with the "#" character in the usual way.
.IP .IP
\fB-allow\fR applies in \fB-ssl\fR mode, but not in \fB-stunnel\fR mode. \fB-allow\fR applies in \fB-ssl\fR mode, but not in \fB-stunnel\fR mode.
.IP
IPv6: as of x11vnc 0.9.10 a host can be specified
in IPv6 numerical format, e.g. 2001:4860:b009::93.
.PP .PP
\fB-localhost\fR \fB-localhost\fR
.IP .IP
@ -778,6 +827,16 @@ If you do not want x11vnc to listen on ANY interface
(evidently you are using \fB-connect\fR or \fB-connect_or_exit,\fR (evidently you are using \fB-connect\fR or \fB-connect_or_exit,\fR
or plan to use remote control: \fB-R\fR connect:host), use or plan to use remote control: \fB-R\fR connect:host), use
\fB-rfbport\fR 0 \fB-rfbport\fR 0
.IP
IPv6: if IPv6 is supported, this option automatically
implies the IPv6 loopback address '::1' as well.
.PP
\fB-listen6\fR \fIstr\fR
.IP
When in IPv6 listen mode "-6", only listen on the
network interface with address \fIstr\fR. It currently
does not work for link scope addresses or non-numeric
hostname strings.
.PP .PP
\fB-nolookup\fR \fB-nolookup\fR
.IP .IP
@ -1419,7 +1478,7 @@ can act as a replacement for
.IP .IP
This mode only allows one redirected connection. This mode only allows one redirected connection.
The \fB-forever\fR option does not apply. Use \fB-inetd\fR or The \fB-forever\fR option does not apply. Use \fB-inetd\fR or
\fB-loop\fR for persistant service. \fB-loop\fR for persistent service.
.PP .PP
\fB-display\fR \fIWAIT:...\fR \fB-display\fR \fIWAIT:...\fR
.IP .IP
@ -1514,6 +1573,10 @@ be ignored if the FD_TAG env. var. is already set or
if the viewer-side supplied value is not completely if the viewer-side supplied value is not completely
composed of alphanumeric or '_' or '-' characters. composed of alphanumeric or '_' or '-' characters.
.IP .IP
To troubleshoot the FINDCREATEDISPLAY mechanism,
set the following env. var. to an ouput log file,
e.g \fB-env\fR CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt
.IP
To disable the option setting set the environment To disable the option setting set the environment
variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc. variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.
To set any other options, the user can use the gui To set any other options, the user can use the gui
@ -2459,15 +2522,25 @@ requirement.
.IP .IP
Set \fB-env\fR STUNNEL_DEBUG=1 for more debugging printout. Set \fB-env\fR STUNNEL_DEBUG=1 for more debugging printout.
.IP .IP
Set \fB-env\fR STUNNEL_PROG=xxx to the full path of stunnel
program you want to be used (e.g. /usr/bin/stunnel4).
.IP
Set \fB-env\fR STUNNEL_LISTEN=xxx to the address of the
network interface to listen on (the default is to listen
on all interfaces), e.g. STUNNEL_LISTEN=192.168.1.100.
.IP
A simple way to add IPv6 support is STUNNEL_LISTEN=::
.IP
Your VNC viewer will also need to be able to connect Your VNC viewer will also need to be able to connect
via SSL. Unfortunately not too many do this. See the via SSL. Unfortunately not too many do this. See the
information about SSL viewers under the \fB-ssl\fR option. information about SSL viewers under the \fB-ssl\fR option.
The x11vnc project's SSVNC is an option.
.IP .IP
Also, in the x11vnc distribution, patched TightVNC Also, in the x11vnc distribution, patched TightVNC
and UltraVNC Java applet jar files are provided in and UltraVNC Java applet jar files are provided in
the classes/ssl directory that do SSL connections. the classes/ssl directory that do SSL connections.
Enable serving them with the \fB-http,\fR \fB-http_ssl,\fR \fB-https,\fR Enable serving them with the \fB-http,\fR \fB-http_ssl,\fR or
or \fB-httpdir\fR (see the option descriptions for more info.) \fB-httpdir\fR (see the option descriptions for more info.)
.IP .IP
Note that for the Java viewer applet usage the Note that for the Java viewer applet usage the
"?PORT=xxxx" in the various URLs printed at startup "?PORT=xxxx" in the various URLs printed at startup
@ -4310,6 +4383,11 @@ Default: 10
Have x11vnc read and process all available client input Have x11vnc read and process all available client input
before proceeding. before proceeding.
.PP .PP
\fB-input_eagerly\fR
.IP
Similar to \fB-allinput\fR but use the handleEventsEagerly
mechanism built into LibVNCServer.
.PP
\fB-speeds\fR \fIrd,bw,lat\fR \fB-speeds\fR \fIrd,bw,lat\fR
.IP .IP
x11vnc tries to estimate some speed parameters that x11vnc tries to estimate some speed parameters that
@ -5541,6 +5619,20 @@ nolocalhost disable \fB-localhost\fR mode
.IP .IP
listen:str set \fB-listen\fR to str, empty to disable. listen:str set \fB-listen\fR to str, empty to disable.
.IP .IP
noipv6 enable \fB-noipv6\fR mode.
.IP
ipv6 disable \fB-noipv6\fR mode.
.IP
noipv4 enable \fB-noipv4\fR mode.
.IP
ipv4 disable \fB-noipv4\fR mode.
.IP
6 enable -6 IPv6 listening mode.
.IP
no6 disable -6 IPv6 listening mode.
.IP
lookup disable \fB-nolookup\fR mode.
.IP
nolookup enable \fB-nolookup\fR mode. nolookup enable \fB-nolookup\fR mode.
.IP .IP
lookup disable \fB-nolookup\fR mode. lookup disable \fB-nolookup\fR mode.
@ -5844,6 +5936,10 @@ allinput enable use of \fB-allinput\fR mode.
.IP .IP
noallinput disable use of \fB-allinput\fR mode. noallinput disable use of \fB-allinput\fR mode.
.IP .IP
input_eagerly enable use of \fB-input_eagerly\fR mode.
.IP
noinput_eagerly disable use of \fB-input_eagerly\fR mode.
.IP
ssltimeout:n set \fB-ssltimeout\fR to n. ssltimeout:n set \fB-ssltimeout\fR to n.
.IP .IP
speeds:str set \fB-speeds\fR to str. speeds:str set \fB-speeds\fR to str.
@ -6223,52 +6319,54 @@ nooverlay_yescursor overlay_nocursor 8to24 no8to24
8to24_opts 24to32 no24to32 visual scale scale_cursor 8to24_opts 24to32 no24to32 visual scale scale_cursor
viewonly noviewonly shared noshared forever noforever viewonly noviewonly shared noshared forever noforever
once timeout tightfilexfer notightfilexfer ultrafilexfer once timeout tightfilexfer notightfilexfer ultrafilexfer
noultrafilexfer rfbversion deny lock nodeny unlock noultrafilexfer rfbversion deny lock nodeny unlock avahi
avahi mdns zeroconf noavahi nomdns nozeroconf connect mdns zeroconf noavahi nomdns nozeroconf connect proxy
proxy allowonce allow localhost nolocalhost listen allowonce allow noipv6 ipv6 noipv4 ipv4 no6 6 localhost
lookup nolookup accept afteraccept gone shm noshm nolocalhost listen lookup nolookup accept afteraccept
flipbyteorder noflipbyteorder onetile noonetile gone shm noshm flipbyteorder noflipbyteorder onetile
solid_color solid nosolid blackout xinerama noxinerama noonetile solid_color solid nosolid blackout xinerama
xtrap noxtrap xrandr noxrandr xrandr_mode rotate padgeom noxinerama xtrap noxtrap xrandr noxrandr xrandr_mode
quiet q noquiet modtweak nomodtweak xkb noxkb capslock rotate padgeom quiet q noquiet modtweak nomodtweak xkb
nocapslock skip_lockkeys noskip_lockkeys skip_keycodes noxkb capslock nocapslock skip_lockkeys noskip_lockkeys
sloppy_keys nosloppy_keys skip_dups noskip_dups skip_keycodes sloppy_keys nosloppy_keys skip_dups
add_keysyms noadd_keysyms clear_mods noclear_mods noskip_dups add_keysyms noadd_keysyms clear_mods
clear_keys noclear_keys clear_all clear_locks keystate noclear_mods clear_keys noclear_keys clear_all
remap repeat norepeat fb nofb bell nobell sendbell clear_locks keystate remap repeat norepeat fb nofb bell
sel nosel primary noprimary setprimary nosetprimary nobell sendbell sel nosel primary noprimary setprimary
clipboard noclipboard setclipboard nosetclipboard nosetprimary clipboard noclipboard setclipboard
seldir cursorshape nocursorshape cursorpos nocursorpos nosetclipboard seldir cursorshape nocursorshape
cursor_drag nocursor_drag cursor show_cursor cursorpos nocursorpos cursor_drag nocursor_drag cursor
noshow_cursor nocursor arrow xfixes noxfixes xdamage show_cursor noshow_cursor nocursor arrow xfixes
noxdamage xd_area xd_mem alphacut alphafrac alpharemove noxfixes xdamage noxdamage xd_area xd_mem alphacut
noalpharemove alphablend noalphablend xwarppointer alphafrac alpharemove noalpharemove alphablend
xwarp noxwarppointer noxwarp buttonmap dragging noalphablend xwarppointer xwarp noxwarppointer
nodragging ncache_cr noncache_cr ncache_no_moveraise noxwarp buttonmap dragging nodragging ncache_cr
noncache_no_moveraise ncache_no_dtchange noncache_cr ncache_no_moveraise noncache_no_moveraise
noncache_no_dtchange ncache_no_rootpixmap ncache_no_dtchange noncache_no_dtchange
noncache_no_rootpixmap ncache_reset_rootpixmap ncrp ncache_no_rootpixmap noncache_no_rootpixmap
ncache_keep_anims noncache_keep_anims ncache_old_wm ncache_reset_rootpixmap ncrp ncache_keep_anims
noncache_old_wm ncache_pad ncache noncache ncache_size noncache_keep_anims ncache_old_wm noncache_old_wm
debug_ncache nodebug_ncache wireframe_mode wireframe wf ncache_pad ncache noncache ncache_size debug_ncache
nowireframe nowf wireframelocal wfl nowireframelocal nodebug_ncache wireframe_mode wireframe wf nowireframe
nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area nowf wireframelocal wfl nowireframelocal nowfl
wirecopyrect wcr nowirecopyrect nowcr scr_area
scr_skip scr_inc scr_keys scr_term scr_keyrepeat scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect scr_parms scrollcopyrect scr noscrollcopyrect
noscr fixscreen noxrecord xrecord reset_record noscr fixscreen noxrecord xrecord reset_record
pointer_mode pm input_skip allinput noallinput input pointer_mode pm input_skip allinput noallinput
grabkbd nograbkbd grabptr nograbptr grabalways input_eagerly noinput_eagerly input grabkbd nograbkbd
nograbalways grablocal client_input ssltimeout grabptr nograbptr grabalways nograbalways grablocal
speeds wmdt debug_pointer dp nodebug_pointer nodp client_input ssltimeout speeds wmdt debug_pointer dp
debug_keyboard dk nodebug_keyboard nodk keycode keysym nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
ptr fakebuttonevent sleep get_xprop set_xprop wininfo nodk keycode keysym ptr fakebuttonevent sleep get_xprop
bcx_xattach deferupdate defer setdefer extra_fbur set_xprop wininfo bcx_xattach deferupdate defer
wait_ui wait_bog nowait_bog slow_fb xrefresh wait setdefer extra_fbur wait_ui wait_bog nowait_bog
readtimeout nap nonap sb screen_blank fbpm nofbpm dpms slow_fb xrefresh wait readtimeout nap nonap sb
nodpms clientdpms noclientdpms forcedpms noforcedpms screen_blank fbpm nofbpm dpms nodpms clientdpms
noserverdpms serverdpms noultraext ultraext chatwindow noclientdpms forcedpms noforcedpms noserverdpms
nochatwindow chaton chatoff fs gaps grow fuzz snapfb serverdpms noultraext ultraext chatwindow nochatwindow
nosnapfb rawfb uinput_accel uinput_thresh uinput_reset chaton chatoff fs gaps grow fuzz snapfb nosnapfb
rawfb uinput_accel uinput_thresh uinput_reset
uinput_always progressive rfbport http nohttp httpport uinput_always progressive rfbport http nohttp httpport
httpdir enablehttpproxy noenablehttpproxy alwaysshared httpdir enablehttpproxy noenablehttpproxy alwaysshared
noalwaysshared nevershared noalwaysshared dontdisconnect noalwaysshared nevershared noalwaysshared dontdisconnect

@ -1,7 +1,7 @@
/* /*
* x11vnc: a VNC server for X displays. * x11vnc: a VNC server for X displays.
* *
* Copyright (C) 2002-2009 Karl J. Runge <runge@karlrunge.com> * Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
* All rights reserved. * All rights reserved.
* *
* This file is part of x11vnc. * This file is part of x11vnc.
@ -216,9 +216,9 @@ int tsdo(int port, int lsock, int *conn) {
if (db) rfbLog("tsdo: using existing csock: %d, port: %d\n", csock, port); if (db) rfbLog("tsdo: using existing csock: %d, port: %d\n", csock, port);
} }
rsock = rfbConnectToTcpAddr("127.0.0.1", port); rsock = connect_tcp("127.0.0.1", port);
if (rsock < 0) { if (rsock < 0) {
if (db) rfbLog("tsdo: rfbConnectToTcpAddr(port=%d) failed.\n", port); if (db) rfbLog("tsdo: connect_tcp(port=%d) failed.\n", port);
close(csock); close(csock);
return 2; return 2;
} }
@ -391,7 +391,8 @@ void terminal_services(char *list) {
XSync(dpy, False); XSync(dpy, False);
for (k=1; k <= 5; k++) { for (k=1; k <= 5; k++) {
socks[i] = rfbListenOnTCPPort(listen[i], htonl(INADDR_LOOPBACK)); /* XXX ::1 fallback? */
socks[i] = listen_tcp(listen[i], htonl(INADDR_LOOPBACK), 1);
if (socks[i] >= 0) { if (socks[i] >= 0) {
if (db) fprintf(stderr, " listen succeeded: %d\n", listen[i]); if (db) fprintf(stderr, " listen succeeded: %d\n", listen[i]);
break; break;
@ -601,7 +602,7 @@ if (tstk[j] != 0) fprintf(stderr, "B redir[%d][%d] = %d %s\n", i, j, tstk[j], t
redir[i][j] = 0; redir[i][j] = 0;
continue; continue;
} }
s = rfbConnectToTcpAddr("127.0.0.1", p); s = connect_tcp("127.0.0.1", p);
if (s < 0) { if (s < 0) {
redir[i][j] = 0; redir[i][j] = 0;
if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p); if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p);
@ -646,6 +647,7 @@ void do_tsd(void) {
char *cmd; char *cmd;
int n, sz = 0; int n, sz = 0;
char *disp = DisplayString(dpy); char *disp = DisplayString(dpy);
char *logfile = getenv("TS_REDIR_LOGFILE");
int db = 0; int db = 0;
if (getenv("TS_REDIR_DEBUG")) { if (getenv("TS_REDIR_DEBUG")) {
@ -675,6 +677,12 @@ void do_tsd(void) {
sz += strlen("-env TSD_RESTART=1") + 1; sz += strlen("-env TSD_RESTART=1") + 1;
sz += strlen("</dev/null 1>/dev/null 2>&1") + 1; sz += strlen("</dev/null 1>/dev/null 2>&1") + 1;
sz += strlen(" &") + 1; sz += strlen(" &") + 1;
if (logfile) {
sz += strlen(logfile);
}
if (ipv6_listen) {
sz += strlen("-6") + 1;
}
cmd = (char *) malloc(sz); cmd = (char *) malloc(sz);
@ -684,7 +692,9 @@ void do_tsd(void) {
*(xauth-2) = '_'; /* yow */ *(xauth-2) = '_'; /* yow */
} }
} }
sprintf(cmd, "%s -display %s -tsd '%s' -env TSD_RESTART=1 </dev/null 1>/dev/null 2>&1 &", program_name, disp, prop); sprintf(cmd, "%s -display %s -tsd '%s' -env TSD_RESTART=1 %s </dev/null 1>%s 2>&1 &",
program_name, disp, prop, ipv6_listen ? "-6" : "",
logfile ? logfile : "/dev/null" );
rfbLog("running: %s\n", cmd); rfbLog("running: %s\n", cmd);
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
@ -2511,10 +2521,32 @@ int main(int argc, char* argv[]) {
got_localhost = 1; got_localhost = 1;
continue; continue;
} }
if (!strcmp(arg, "-listen6")) {
listen_str6 = strdup(argv[++i]);
continue;
}
if (!strcmp(arg, "-nolookup")) { if (!strcmp(arg, "-nolookup")) {
host_lookup = 0; host_lookup = 0;
continue; continue;
} }
#if X11VNC_IPV6
if (!strcmp(arg, "-6")) {
ipv6_listen = 1;
continue;
}
if (!strcmp(arg, "-no6")) {
ipv6_listen = 0;
continue;
}
if (!strcmp(arg, "-noipv6")) {
noipv6 = 1;
continue;
}
if (!strcmp(arg, "-noipv4")) {
noipv4 = 1;
continue;
}
#endif
if (!strcmp(arg, "-input")) { if (!strcmp(arg, "-input")) {
CHECK_ARGC CHECK_ARGC
allowed_input_str = strdup(argv[++i]); allowed_input_str = strdup(argv[++i]);
@ -3558,6 +3590,14 @@ int main(int argc, char* argv[]) {
all_input = 0; all_input = 0;
continue; continue;
} }
if (!strcmp(arg, "-input_eagerly")) {
handle_events_eagerly = 1;
continue;
}
if (!strcmp(arg, "-noinput_eagerly")) {
handle_events_eagerly = 0;
continue;
}
if (!strcmp(arg, "-speeds")) { if (!strcmp(arg, "-speeds")) {
CHECK_ARGC CHECK_ARGC
speeds_str = strdup(argv[++i]); speeds_str = strdup(argv[++i]);
@ -4311,6 +4351,11 @@ int main(int argc, char* argv[]) {
close(n); close(n);
} }
} }
if (ipv6_listen) {
if (inetd) {
ipv6_listen = 0;
}
}
if (inetd && quiet && !logfile) { if (inetd && quiet && !logfile) {
int n; int n;
/* /*
@ -5735,9 +5780,14 @@ int main(int argc, char* argv[]) {
if (! screen->port || screen->listenSock < 0) { if (! screen->port || screen->listenSock < 0) {
if (got_rfbport && got_rfbport_val == 0) { if (got_rfbport && got_rfbport_val == 0) {
; ;
} else if (ipv6_listen && ipv6_listen_fd >= 0) {
rfbLog("Info: listening only on IPv6 interface.\n");
} else { } else {
rfbLogEnable(1); rfbLogEnable(1);
rfbLog("Error: could not obtain listening port.\n"); rfbLog("Error: could not obtain listening port.\n");
if (!got_rfbport) {
rfbLog("If this system is IPv6-only, use the -6 option.\n");
}
clean_up_exit(1); clean_up_exit(1);
} }
} }
@ -5776,7 +5826,6 @@ int main(int argc, char* argv[]) {
} }
if (screen && screen->httpListenSock >= 0) { if (screen && screen->httpListenSock >= 0) {
close(screen->httpListenSock); close(screen->httpListenSock);
FD_CLR(screen->httpListenSock,&screen->allFds);
screen->httpListenSock = -1; screen->httpListenSock = -1;
} }
if (openssl_sock >= 0) { if (openssl_sock >= 0) {
@ -5787,6 +5836,22 @@ int main(int argc, char* argv[]) {
close(https_sock); close(https_sock);
https_sock = -1; https_sock = -1;
} }
if (openssl_sock6 >= 0) {
close(openssl_sock6);
openssl_sock6 = -1;
}
if (https_sock6 >= 0) {
close(https_sock6);
https_sock6 = -1;
}
if (ipv6_listen_fd >= 0) {
close(ipv6_listen_fd);
ipv6_listen_fd = -1;
}
if (ipv6_http_fd >= 0) {
close(ipv6_http_fd);
ipv6_http_fd = -1;
}
} }
/* fork into the background now */ /* fork into the background now */
if ((p = fork()) > 0) { if ((p = fork()) > 0) {

@ -316,6 +316,14 @@ extern int h_errno;
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#ifndef X11VNC_IPV6
#if defined(AF_INET6) || defined(PF_INET6)
#define X11VNC_IPV6 1
#else
#define X11VNC_IPV6 0
#endif
#endif
#if LIBVNCSERVER_HAVE_PWD_H #if LIBVNCSERVER_HAVE_PWD_H
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>

@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.10 lastmod: 2010-03-20"; char lastmod[] = "0.9.10 lastmod: 2010-04-08";
/* X display info */ /* X display info */

@ -50,6 +50,7 @@ so, delete this exception statement from your version.
#include "pm.h" #include "pm.h"
#include "pointer.h" #include "pointer.h"
#include "remote.h" #include "remote.h"
#include "inet.h"
/* XXX CHECK BEFORE RELEASE */ /* XXX CHECK BEFORE RELEASE */
int grab_buster = 0; int grab_buster = 0;
@ -1962,7 +1963,8 @@ static void try_local_chat_window(void) {
for (i = 0; i < 90; i++) { for (i = 0; i < 90; i++) {
/* find an open port */ /* find an open port */
port = 7300 + i; port = 7300 + i;
lsock = rfbListenOnTCPPort(port, htonl(INADDR_LOOPBACK)); /* XXX ::1 fallback */
lsock = listen_tcp(port, htonl(INADDR_LOOPBACK), 0);
if (lsock >= 0) { if (lsock >= 0) {
break; break;
} }

@ -331,9 +331,11 @@ void check_xinerama_clip(void) {
static void initialize_xinerama (void) { static void initialize_xinerama (void) {
#if !LIBVNCSERVER_HAVE_LIBXINERAMA #if !LIBVNCSERVER_HAVE_LIBXINERAMA
rfbLog("Xinerama: Library libXinerama is not available to determine\n"); if (!raw_fb_str) {
rfbLog("Xinerama: the head geometries, consider using -blackout\n"); rfbLog("Xinerama: Library libXinerama is not available to determine\n");
rfbLog("Xinerama: if the screen is non-rectangular.\n"); rfbLog("Xinerama: the head geometries, consider using -blackout\n");
rfbLog("Xinerama: if the screen is non-rectangular.\n");
}
#else #else
XineramaScreenInfo *sc, *xineramas; XineramaScreenInfo *sc, *xineramas;
sraRegionPtr black_region, tmp_region; sraRegionPtr black_region, tmp_region;

Loading…
Cancel
Save