Commit efcdab50 authored by Christian Beier's avatar Christian Beier

Merge branch 'server-ipv6'

parents ee459342 2d50fc84
...@@ -524,6 +524,7 @@ int main(int argc,char** argv) { ...@@ -524,6 +524,7 @@ int main(int argc,char** argv) {
cl->HandleTextChat=text_chat; cl->HandleTextChat=text_chat;
cl->GotXCutText = got_selection; cl->GotXCutText = got_selection;
cl->listenPort = LISTEN_PORT_OFFSET; cl->listenPort = LISTEN_PORT_OFFSET;
cl->listen6Port = LISTEN_PORT_OFFSET;
if(!rfbInitClient(cl,&argc,argv)) if(!rfbInitClient(cl,&argc,argv))
{ {
cl = NULL; /* rfbInitClient has already freed the client struct */ cl = NULL; /* rfbInitClient has already freed the client struct */
......
/* /*
* Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. 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
...@@ -50,7 +51,7 @@ listenForIncomingConnections(rfbClient* client) ...@@ -50,7 +51,7 @@ listenForIncomingConnections(rfbClient* client)
rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n"); rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
return; return;
#else #else
int listenSocket; int listenSocket, listen6Socket = -1;
fd_set fds; fd_set fds;
client->listenSpecified = TRUE; client->listenSpecified = TRUE;
...@@ -65,8 +66,24 @@ listenForIncomingConnections(rfbClient* client) ...@@ -65,8 +66,24 @@ listenForIncomingConnections(rfbClient* client)
rfbClientLog("%s -listen: Command line errors are not reported until " rfbClientLog("%s -listen: Command line errors are not reported until "
"a connection comes in.\n", client->programName); "a connection comes in.\n", client->programName);
while (TRUE) { #ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
/* only do IPv6 listen of listen6Port is set */
if (client->listen6Port > 0)
{
listen6Socket = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
if (listen6Socket < 0)
return;
rfbClientLog("%s -listen: Listening on IPV6 port %d\n",
client->programName,client->listenPort);
rfbClientLog("%s -listen: Command line errors are not reported until "
"a connection comes in.\n", client->programName);
}
#endif
while (TRUE) {
int r;
/* reap any zombies */ /* reap any zombies */
int status, pid; int status, pid;
while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
...@@ -75,12 +92,19 @@ listenForIncomingConnections(rfbClient* client) ...@@ -75,12 +92,19 @@ listenForIncomingConnections(rfbClient* client)
FD_ZERO(&fds); FD_ZERO(&fds);
if(listenSocket >= 0)
FD_SET(listenSocket, &fds); FD_SET(listenSocket, &fds);
if(listen6Socket >= 0)
FD_SET(listen6Socket, &fds);
r = select(max(listenSocket, listen6Socket)+1, &fds, NULL, NULL, NULL);
select(listenSocket+1, &fds, NULL, NULL, NULL); if (r > 0) {
if (FD_ISSET(listenSocket, &fds))
client->sock = AcceptTcpConnection(client->listenSock);
else if (FD_ISSET(listen6Socket, &fds))
client->sock = AcceptTcpConnection(client->listen6Sock);
if (FD_ISSET(listenSocket, &fds)) {
client->sock = AcceptTcpConnection(listenSocket);
if (client->sock < 0) if (client->sock < 0)
return; return;
if (!SetNonBlocking(client->sock)) if (!SetNonBlocking(client->sock))
...@@ -97,6 +121,7 @@ listenForIncomingConnections(rfbClient* client) ...@@ -97,6 +121,7 @@ listenForIncomingConnections(rfbClient* client)
case 0: case 0:
/* child - return to caller */ /* child - return to caller */
close(listenSocket); close(listenSocket);
close(listen6Socket);
return; return;
default: default:
...@@ -144,24 +169,54 @@ listenForIncomingConnectionsNoFork(rfbClient* client, int timeout) ...@@ -144,24 +169,54 @@ listenForIncomingConnectionsNoFork(rfbClient* client, int timeout)
"a connection comes in.\n", client->programName); "a connection comes in.\n", client->programName);
} }
#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
/* only do IPv6 listen of listen6Port is set */
if (client->listen6Port > 0 && client->listen6Sock < 0)
{
client->listen6Sock = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
if (client->listen6Sock < 0)
return -1;
rfbClientLog("%s -listennofork: Listening on IPV6 port %d\n",
client->programName,client->listenPort);
rfbClientLog("%s -listennofork: Command line errors are not reported until "
"a connection comes in.\n", client->programName);
}
#endif
FD_ZERO(&fds); FD_ZERO(&fds);
if(client->listenSock >= 0)
FD_SET(client->listenSock, &fds); FD_SET(client->listenSock, &fds);
if(client->listen6Sock >= 0)
FD_SET(client->listen6Sock, &fds);
if (timeout < 0) if (timeout < 0)
r = select(client->listenSock+1, &fds, NULL, NULL, NULL); r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, NULL);
else else
r = select(client->listenSock+1, &fds, NULL, NULL, &to); r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, &to);
if (r > 0) if (r > 0)
{ {
if (FD_ISSET(client->listenSock, &fds))
client->sock = AcceptTcpConnection(client->listenSock); client->sock = AcceptTcpConnection(client->listenSock);
else if (FD_ISSET(client->listen6Sock, &fds))
client->sock = AcceptTcpConnection(client->listen6Sock);
if (client->sock < 0) if (client->sock < 0)
return -1; return -1;
if (!SetNonBlocking(client->sock)) if (!SetNonBlocking(client->sock))
return -1; return -1;
if(client->listenSock >= 0) {
close(client->listenSock); close(client->listenSock);
client->listenSock = -1;
}
if(client->listen6Sock >= 0) {
close(client->listen6Sock);
client->listen6Sock = -1;
}
return r; return r;
} }
......
/* /*
* Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. 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
...@@ -494,8 +495,9 @@ int ...@@ -494,8 +495,9 @@ int
ListenAtTcpPortAndAddress(int port, const char *address) ListenAtTcpPortAndAddress(int port, const char *address)
{ {
int sock; int sock;
struct sockaddr_in addr;
int one = 1; int one = 1;
#ifndef LIBVNCSERVER_IPv6
struct sockaddr_in addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(port); addr.sin_port = htons(port);
...@@ -527,6 +529,66 @@ ListenAtTcpPortAndAddress(int port, const char *address) ...@@ -527,6 +529,66 @@ ListenAtTcpPortAndAddress(int port, const char *address)
return -1; return -1;
} }
#else
int rv;
struct addrinfo hints, *servinfo, *p;
char port_str[8];
snprintf(port_str, 8, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if address == NULL */
if (!initSockets())
return -1;
if ((rv = getaddrinfo(address, port_str, &hints, &servinfo)) != 0) {
rfbClientErr("ListenAtTcpPortAndAddress: error in getaddrinfo: %s\n", gai_strerror(rv));
return -1;
}
/* loop through all the results and bind to the first we can */
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
continue;
}
#ifdef IPV6_V6ONLY
/* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */
if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt IPV6_V6ONLY: %s\n", strerror(errno));
close(sock);
freeaddrinfo(servinfo);
return -1;
}
#endif
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt SO_REUSEADDR: %s\n", strerror(errno));
close(sock);
freeaddrinfo(servinfo);
return -1;
}
if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
close(sock);
continue;
}
break;
}
if (p == NULL) {
rfbClientErr("ListenAtTcpPortAndAddress: error in bind: %s\n", strerror(errno));
return -1;
}
/* all done with this structure now */
freeaddrinfo(servinfo);
#endif
if (listen(sock, 5) < 0) { if (listen(sock, 5) < 0) {
rfbClientErr("ListenAtTcpPort: listen\n"); rfbClientErr("ListenAtTcpPort: listen\n");
close(sock); close(sock);
......
...@@ -197,6 +197,8 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, ...@@ -197,6 +197,8 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client->sock = -1; client->sock = -1;
client->listenSock = -1; client->listenSock = -1;
client->listenAddress = NULL; client->listenAddress = NULL;
client->listen6Sock = -1;
client->listen6Address = NULL;
client->clientAuthSchemes = NULL; client->clientAuthSchemes = NULL;
return client; return client;
} }
......
...@@ -22,6 +22,9 @@ rfbUsage(void) ...@@ -22,6 +22,9 @@ rfbUsage(void)
rfbProtocolExtension* extension; rfbProtocolExtension* extension;
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n"); fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
#ifdef LIBVNCSERVER_IPv6
fprintf(stderr, "-rfbportv6 port TCP6 port for RFB protocol\n");
#endif
fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n"); fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n" fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
" (use 'storepasswd' to create a password file)\n"); " (use 'storepasswd' to create a password file)\n");
...@@ -42,10 +45,17 @@ rfbUsage(void) ...@@ -42,10 +45,17 @@ rfbUsage(void)
"instead)\n"); "instead)\n");
fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n"); fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n");
fprintf(stderr, "-httpport portnum use portnum for http connection\n"); fprintf(stderr, "-httpport portnum use portnum for http connection\n");
#ifdef LIBVNCSERVER_IPv6
fprintf(stderr, "-httpportv6 portnum use portnum for IPv6 http connection\n");
#endif
fprintf(stderr, "-enablehttpproxy enable http proxy support\n"); fprintf(stderr, "-enablehttpproxy enable http proxy support\n");
fprintf(stderr, "-progressive height enable progressive updating for slow links\n"); fprintf(stderr, "-progressive height enable progressive updating for slow links\n");
fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n"); fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n");
fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n"); fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n");
#ifdef LIBVNCSERVER_IPv6
fprintf(stderr, "-listenv6 ipv6addr listen for IPv6 connections only on network interface with\n");
fprintf(stderr, " addr ipv6addr. '-listen localhost' and hostname work too.\n");
#endif
for(extension=rfbGetExtensionIterator();extension;extension=extension->next) for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
if(extension->usage) if(extension->usage)
...@@ -80,6 +90,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) ...@@ -80,6 +90,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
return FALSE; return FALSE;
} }
rfbScreen->port = atoi(argv[++i]); rfbScreen->port = atoi(argv[++i]);
#ifdef LIBVNCSERVER_IPv6
} else if (strcmp(argv[i], "-rfbportv6") == 0) { /* -rfbportv6 port */
if (i + 1 >= *argc) {
rfbUsage();
return FALSE;
}
rfbScreen->ipv6port = atoi(argv[++i]);
#endif
} else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */ } else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
if (i + 1 >= *argc) { if (i + 1 >= *argc) {
rfbUsage(); rfbUsage();
...@@ -147,6 +165,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) ...@@ -147,6 +165,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
return FALSE; return FALSE;
} }
rfbScreen->httpPort = atoi(argv[++i]); rfbScreen->httpPort = atoi(argv[++i]);
#ifdef LIBVNCSERVER_IPv6
} else if (strcmp(argv[i], "-httpportv6") == 0) { /* -httpportv6 portnum */
if (i + 1 >= *argc) {
rfbUsage();
return FALSE;
}
rfbScreen->http6Port = atoi(argv[++i]);
#endif
} else if (strcmp(argv[i], "-enablehttpproxy") == 0) { } else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
rfbScreen->httpEnableProxyConnect = TRUE; rfbScreen->httpEnableProxyConnect = TRUE;
} else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */ } else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */
...@@ -163,6 +189,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) ...@@ -163,6 +189,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) { if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {
return FALSE; return FALSE;
} }
#ifdef LIBVNCSERVER_IPv6
} else if (strcmp(argv[i], "-listenv6") == 0) { /* -listenv6 ipv6addr */
if (i + 1 >= *argc) {
rfbUsage();
return FALSE;
}
rfbScreen->listen6Interface = argv[++i];
#endif
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS #ifdef LIBVNCSERVER_WITH_WEBSOCKETS
} else if (strcmp(argv[i], "-sslkeyfile") == 0) { /* -sslkeyfile sslkeyfile */ } else if (strcmp(argv[i], "-sslkeyfile") == 0) { /* -sslkeyfile sslkeyfile */
if (i + 1 >= *argc) { if (i + 1 >= *argc) {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
*/ */
/* /*
* Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
* Copyright (C) 2002 RealVNC Ltd. * Copyright (C) 2002 RealVNC Ltd.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
* *
...@@ -102,17 +103,27 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) ...@@ -102,17 +103,27 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
rfbScreen->httpPort = rfbScreen->port-100; rfbScreen->httpPort = rfbScreen->port-100;
} }
rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort);
if ((rfbScreen->httpListenSock = if ((rfbScreen->httpListenSock =
rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) { rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) {
rfbLogPerror("ListenOnTCPPort"); rfbLogPerror("ListenOnTCPPort");
return; return;
} }
rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort);
#ifdef LIBVNCSERVER_IPv6
if (rfbScreen->http6Port == 0) {
rfbScreen->http6Port = rfbScreen->ipv6port-100;
}
/*AddEnabledDevice(httpListenSock);*/ if ((rfbScreen->httpListen6Sock
= rfbListenOnTCP6Port(rfbScreen->http6Port, rfbScreen->listen6Interface)) < 0) {
/* ListenOnTCP6Port has its own detailed error printout */
return;
}
rfbLog("Listening for HTTP connections on TCP6 port %d\n", rfbScreen->http6Port);
rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->http6Port);
#endif
} }
void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {
...@@ -121,6 +132,18 @@ void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { ...@@ -121,6 +132,18 @@ void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {
FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds); FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds);
rfbScreen->httpSock=-1; rfbScreen->httpSock=-1;
} }
if(rfbScreen->httpListenSock>-1) {
close(rfbScreen->httpListenSock);
FD_CLR(rfbScreen->httpListenSock,&rfbScreen->allFds);
rfbScreen->httpListenSock=-1;
}
if(rfbScreen->httpListen6Sock>-1) {
close(rfbScreen->httpListen6Sock);
FD_CLR(rfbScreen->httpListen6Sock,&rfbScreen->allFds);
rfbScreen->httpListen6Sock=-1;
}
} }
/* /*
...@@ -134,7 +157,11 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -134,7 +157,11 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
int nfds; int nfds;
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
#ifdef LIBVNCSERVER_IPv6
struct sockaddr_storage addr;
#else
struct sockaddr_in addr; struct sockaddr_in addr;
#endif
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
if (!rfbScreen->httpDir) if (!rfbScreen->httpDir)
...@@ -145,12 +172,15 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -145,12 +172,15 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(rfbScreen->httpListenSock, &fds); FD_SET(rfbScreen->httpListenSock, &fds);
if (rfbScreen->httpListen6Sock >= 0) {
FD_SET(rfbScreen->httpListen6Sock, &fds);
}
if (rfbScreen->httpSock >= 0) { if (rfbScreen->httpSock >= 0) {
FD_SET(rfbScreen->httpSock, &fds); FD_SET(rfbScreen->httpSock, &fds);
} }
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); nfds = select(max(rfbScreen->httpListen6Sock, max(rfbScreen->httpSock,rfbScreen->httpListenSock)) + 1, &fds, NULL, NULL, &tv);
if (nfds == 0) { if (nfds == 0) {
return; return;
} }
...@@ -167,19 +197,36 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -167,19 +197,36 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
httpProcessInput(rfbScreen); httpProcessInput(rfbScreen);
} }
if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { if (FD_ISSET(rfbScreen->httpListenSock, &fds) || FD_ISSET(rfbScreen->httpListen6Sock, &fds)) {
if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);
if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, if(FD_ISSET(rfbScreen->httpListenSock, &fds)) {
(struct sockaddr *)&addr, &addrlen)) < 0) { if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) {
rfbLogPerror("httpCheckFds: accept");
return;
}
}
else if(FD_ISSET(rfbScreen->httpListen6Sock, &fds)) {
if ((rfbScreen->httpSock = accept(rfbScreen->httpListen6Sock, (struct sockaddr *)&addr, &addrlen)) < 0) {
rfbLogPerror("httpCheckFds: accept"); rfbLogPerror("httpCheckFds: accept");
return; return;
} }
}
#ifdef USE_LIBWRAP #ifdef USE_LIBWRAP
if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), char host[1024];
#ifdef LIBVNCSERVER_IPv6
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("httpCheckFds: error in getnameinfo");
host[0] = '\0';
}
#else
memcpy(host, inet_ntoa(addr.sin_addr), sizeof(host));
#endif
if(!hosts_ctl("vnc",STRING_UNKNOWN, host,
STRING_UNKNOWN)) { STRING_UNKNOWN)) {
rfbLog("Rejected HTTP connection from client %s\n", rfbLog("Rejected HTTP connection from client %s\n",
inet_ntoa(addr.sin_addr)); host);
close(rfbScreen->httpSock); close(rfbScreen->httpSock);
rfbScreen->httpSock=-1; rfbScreen->httpSock=-1;
return; return;
...@@ -212,7 +259,11 @@ static rfbClientRec cl; ...@@ -212,7 +259,11 @@ static rfbClientRec cl;
static void static void
httpProcessInput(rfbScreenInfoPtr rfbScreen) httpProcessInput(rfbScreenInfoPtr rfbScreen)
{ {
#ifdef LIBVNCSERVER_IPv6
struct sockaddr_storage addr;
#else
struct sockaddr_in addr; struct sockaddr_in addr;
#endif
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
char fullFname[512]; char fullFname[512];
char params[1024]; char params[1024];
...@@ -335,8 +386,16 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen) ...@@ -335,8 +386,16 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen); getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
#ifdef LIBVNCSERVER_IPv6
char host[1024];
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("httpProcessInput: error in getnameinfo");
}
rfbLog("httpd: get '%s' for %s\n", fname+1, host);
#else
rfbLog("httpd: get '%s' for %s\n", fname+1, rfbLog("httpd: get '%s' for %s\n", fname+1,
inet_ntoa(addr.sin_addr)); inet_ntoa(addr.sin_addr));
#endif
/* Extract parameters from the URL string if necessary */ /* Extract parameters from the URL string if necessary */
...@@ -562,7 +621,8 @@ parseParams(const char *request, char *result, int max_bytes) ...@@ -562,7 +621,8 @@ parseParams(const char *request, char *result, int max_bytes)
/* /*
* Check if the string consists only of alphanumeric characters, '+' * Check if the string consists only of alphanumeric characters, '+'
* signs, underscores, and dots. Replace all '+' signs with spaces. * signs, underscores, dots, colons and square brackets.
* Replace all '+' signs with spaces.
*/ */
static rfbBool static rfbBool
...@@ -571,7 +631,8 @@ validateString(char *str) ...@@ -571,7 +631,8 @@ validateString(char *str)
char *ptr; char *ptr;
for (ptr = str; *ptr != '\0'; ptr++) { for (ptr = str; *ptr != '\0'; ptr++) {
if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.'
&& *ptr != ':' && *ptr != '[' && *ptr != ']' ) {
if (*ptr == '+') { if (*ptr == '+') {
*ptr = ' '; *ptr = ' ';
} else { } else {
......
...@@ -569,19 +569,35 @@ listenerRun(void *data) ...@@ -569,19 +569,35 @@ listenerRun(void *data)
{ {
rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;
int client_fd; int client_fd;
struct sockaddr_in peer; struct sockaddr_storage peer;
rfbClientPtr cl; rfbClientPtr cl = NULL;
socklen_t len; socklen_t len;
fd_set listen_fds; /* temp file descriptor list for select() */
len = sizeof(peer);
/* TODO: this thread wont die by restarting the server */ /* TODO: this thread wont die by restarting the server */
/* TODO: HTTP is not handled */ /* TODO: HTTP is not handled */
while ((client_fd = accept(screen->listenSock, while (1) {
(struct sockaddr*)&peer, &len)) >= 0) { client_fd = -1;
cl = rfbNewClient(screen,client_fd); FD_ZERO(&listen_fds);
len = sizeof(peer); if(screen->listenSock >= 0)
FD_SET(screen->listenSock, &listen_fds);
if(screen->listen6Sock >= 0)
FD_SET(screen->listen6Sock, &listen_fds);
if (select(screen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
rfbLogPerror("listenerRun: error in select");
return NULL;
}
/* there is something on the listening sockets, handle new connections */
len = sizeof (peer);
if (FD_ISSET(screen->listenSock, &listen_fds))
client_fd = accept(screen->listenSock, (struct sockaddr*)&peer, &len);
else if (FD_ISSET(screen->listen6Sock, &listen_fds))
client_fd = accept(screen->listen6Sock, (struct sockaddr*)&peer, &len);
if(client_fd >= 0)
cl = rfbNewClient(screen,client_fd);
if (cl && !cl->onHold ) if (cl && !cl->onHold )
rfbStartOnHoldClient(cl); rfbStartOnHoldClient(cl);
} }
...@@ -809,6 +825,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -809,6 +825,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->clientHead=NULL; screen->clientHead=NULL;
screen->pointerClient=NULL; screen->pointerClient=NULL;
screen->port=5900; screen->port=5900;
screen->ipv6port=5900;
screen->socketState=RFB_SOCKET_INIT; screen->socketState=RFB_SOCKET_INIT;
screen->inetdInitDone = FALSE; screen->inetdInitDone = FALSE;
...@@ -821,12 +838,15 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -821,12 +838,15 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->maxFd=0; screen->maxFd=0;
screen->listenSock=-1; screen->listenSock=-1;
screen->listen6Sock=-1;
screen->httpInitDone=FALSE; screen->httpInitDone=FALSE;
screen->httpEnableProxyConnect=FALSE; screen->httpEnableProxyConnect=FALSE;
screen->httpPort=0; screen->httpPort=0;
screen->http6Port=0;
screen->httpDir=NULL; screen->httpDir=NULL;
screen->httpListenSock=-1; screen->httpListenSock=-1;
screen->httpListen6Sock=-1;
screen->httpSock=-1; screen->httpSock=-1;
screen->desktopName = "LibVNCServer"; screen->desktopName = "LibVNCServer";
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#endif #endif
...@@ -270,8 +271,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, ...@@ -270,8 +271,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
rfbProtocolVersionMsg pv; rfbProtocolVersionMsg pv;
rfbClientIteratorPtr iterator; rfbClientIteratorPtr iterator;
rfbClientPtr cl,cl_; rfbClientPtr cl,cl_;
#ifdef LIBVNCSERVER_IPv6
struct sockaddr_storage addr;
#else
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in); #endif
socklen_t addrlen = sizeof(addr);
rfbProtocolExtension* extension; rfbProtocolExtension* extension;
cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1); cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
...@@ -294,7 +299,17 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, ...@@ -294,7 +299,17 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
int one=1; int one=1;
getpeername(sock, (struct sockaddr *)&addr, &addrlen); getpeername(sock, (struct sockaddr *)&addr, &addrlen);
#ifdef LIBVNCSERVER_IPv6
char host[1024];
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("rfbNewClient: error in getnameinfo");
cl->host = strdup("");
}
else
cl->host = strdup(host);
#else
cl->host = strdup(inet_ntoa(addr.sin_addr)); cl->host = strdup(inet_ntoa(addr.sin_addr));
#endif
rfbLog(" other clients:\n"); rfbLog(" other clients:\n");
iterator = rfbGetClientIterator(rfbScreen); iterator = rfbGetClientIterator(rfbScreen);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
/* /*
* Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>. * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
...@@ -137,6 +138,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) ...@@ -137,6 +138,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
if(rfbScreen->autoPort) { if(rfbScreen->autoPort) {
int i; int i;
FD_ZERO(&(rfbScreen->allFds));
rfbLog("Autoprobing TCP port \n"); rfbLog("Autoprobing TCP port \n");
for (i = 5900; i < 6000; i++) { for (i = 5900; i < 6000; i++) {
if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) { if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) {
...@@ -150,22 +153,52 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) ...@@ -150,22 +153,52 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
return; return;
} }
rfbLog("Autoprobing selected port %d\n", rfbScreen->port); rfbLog("Autoprobing selected TCP port %d\n", rfbScreen->port);
FD_ZERO(&(rfbScreen->allFds));
FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
rfbScreen->maxFd = rfbScreen->listenSock; rfbScreen->maxFd = rfbScreen->listenSock;
#ifdef LIBVNCSERVER_IPv6
rfbLog("Autoprobing TCP6 port \n");
for (i = 5900; i < 6000; i++) {
if ((rfbScreen->listen6Sock = rfbListenOnTCP6Port(i, rfbScreen->listen6Interface)) >= 0) {
rfbScreen->ipv6port = i;
break;
}
}
if (i >= 6000) {
rfbLogPerror("Failure autoprobing");
return;
}
rfbLog("Autoprobing selected TCP6 port %d\n", rfbScreen->ipv6port);
FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds));
rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd);
#endif
} }
else if(rfbScreen->port>0) { else if(rfbScreen->port>0) {
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port); FD_ZERO(&(rfbScreen->allFds));
if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) { if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {
rfbLogPerror("ListenOnTCPPort"); rfbLogPerror("ListenOnTCPPort");
return; return;
} }
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);
FD_ZERO(&(rfbScreen->allFds));
FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
rfbScreen->maxFd = rfbScreen->listenSock; rfbScreen->maxFd = rfbScreen->listenSock;
#ifdef LIBVNCSERVER_IPv6
if ((rfbScreen->listen6Sock = rfbListenOnTCP6Port(rfbScreen->ipv6port, rfbScreen->listen6Interface)) < 0) {
/* ListenOnTCP6Port has its own detailed error printout */
return;
}
rfbLog("Listening for VNC connections on TCP6 port %d\n", rfbScreen->ipv6port);
FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds));
rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd);
#endif
} }
if (rfbScreen->udpPort != 0) { if (rfbScreen->udpPort != 0) {
...@@ -175,6 +208,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) ...@@ -175,6 +208,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)
rfbLogPerror("ListenOnUDPPort"); rfbLogPerror("ListenOnUDPPort");
return; return;
} }
rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);
FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds)); FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd); rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
} }
...@@ -199,6 +234,12 @@ void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen) ...@@ -199,6 +234,12 @@ void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)
rfbScreen->listenSock=-1; rfbScreen->listenSock=-1;
} }
if(rfbScreen->listen6Sock>-1) {
closesocket(rfbScreen->listen6Sock);
FD_CLR(rfbScreen->listen6Sock,&rfbScreen->allFds);
rfbScreen->listen6Sock=-1;
}
if(rfbScreen->udpSock>-1) { if(rfbScreen->udpSock>-1) {
closesocket(rfbScreen->udpSock); closesocket(rfbScreen->udpSock);
FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds); FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds);
...@@ -270,6 +311,16 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) ...@@ -270,6 +311,16 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
return result; return result;
} }
if (rfbScreen->listen6Sock != -1 && FD_ISSET(rfbScreen->listen6Sock, &fds)) {
if (!rfbProcessNewConnection(rfbScreen))
return -1;
FD_CLR(rfbScreen->listen6Sock, &fds);
if (--nfds == 0)
return result;
}
if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
if(!rfbScreen->udpClient) if(!rfbScreen->udpClient)
rfbNewUDPClient(rfbScreen); rfbNewUDPClient(rfbScreen);
...@@ -330,10 +381,33 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) ...@@ -330,10 +381,33 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)
{ {
const int one = 1; const int one = 1;
int sock = -1; int sock = -1;
#ifdef LIBVNCSERVER_IPv6
struct sockaddr_storage addr;
#else
struct sockaddr_in addr; struct sockaddr_in addr;
#endif
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
fd_set listen_fds;
int chosen_listen_sock = -1;
/* Do another select() call to find out which listen socket
has an incoming connection pending. We know that at least
one of them has, so this should not block for too long! */
FD_ZERO(&listen_fds);
if(rfbScreen->listenSock >= 0)
FD_SET(rfbScreen->listenSock, &listen_fds);
if(rfbScreen->listen6Sock >= 0)
FD_SET(rfbScreen->listen6Sock, &listen_fds);
if (select(rfbScreen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
rfbLogPerror("rfbProcessNewConnection: error in select");
return FALSE;
}
if (FD_ISSET(rfbScreen->listenSock, &listen_fds))
chosen_listen_sock = rfbScreen->listenSock;
if (FD_ISSET(rfbScreen->listen6Sock, &listen_fds))
chosen_listen_sock = rfbScreen->listen6Sock;
if ((sock = accept(rfbScreen->listenSock, if ((sock = accept(chosen_listen_sock,
(struct sockaddr *)&addr, &addrlen)) < 0) { (struct sockaddr *)&addr, &addrlen)) < 0) {
rfbLogPerror("rfbCheckFds: accept"); rfbLogPerror("rfbCheckFds: accept");
return FALSE; return FALSE;
...@@ -361,7 +435,15 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) ...@@ -361,7 +435,15 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)
} }
#endif #endif
#ifdef LIBVNCSERVER_IPv6
char host[1024];
if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
rfbLogPerror("rfbProcessNewConnection: error in getnameinfo");
}
rfbLog("Got connection from client %s\n", host);
#else
rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
#endif
rfbNewClient(rfbScreen,sock); rfbNewClient(rfbScreen,sock);
...@@ -774,12 +856,128 @@ rfbListenOnTCPPort(int port, ...@@ -774,12 +856,128 @@ rfbListenOnTCPPort(int port,
return sock; return sock;
} }
int
rfbListenOnTCP6Port(int port,
const char* iface)
{
#ifndef LIBVNCSERVER_IPv6
rfbLogPerror("This LibVNCServer does not have IPv6 support");
return -1;
#else
int sock;
int one = 1;
int rv;
struct addrinfo hints, *servinfo, *p;
char port_str[8];
snprintf(port_str, 8, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if iface == NULL */
if ((rv = getaddrinfo(iface, port_str, &hints, &servinfo)) != 0) {
rfbErr("rfbListenOnTCP6Port error in getaddrinfo: %s\n", gai_strerror(rv));
return -1;
}
/* loop through all the results and bind to the first we can */
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
continue;
}
#ifdef IPV6_V6ONLY
/* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
rfbLogPerror("rfbListenOnTCP6Port error in setsockopt IPV6_V6ONLY");
closesocket(sock);
freeaddrinfo(servinfo);
return -1;
}
#endif
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
rfbLogPerror("rfbListenOnTCP6Port: error in setsockopt SO_REUSEADDR");
closesocket(sock);
freeaddrinfo(servinfo);
return -1;
}
if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
closesocket(sock);
continue;
}
break;
}
if (p == NULL) {
rfbLogPerror("rfbListenOnTCP6Port: error in bind IPv6 socket");
freeaddrinfo(servinfo);
return -1;
}
/* all done with this structure now */
freeaddrinfo(servinfo);
if (listen(sock, 32) < 0) {
rfbLogPerror("rfbListenOnTCP6Port: error in listen on IPv6 socket");
closesocket(sock);
return -1;
}
return sock;
#endif
}
int int
rfbConnectToTcpAddr(char *host, rfbConnectToTcpAddr(char *host,
int port) int port)
{ {
struct hostent *hp;
int sock; int sock;
#ifdef LIBVNCSERVER_IPv6
struct addrinfo hints, *servinfo, *p;
int rv;
char port_str[8];
snprintf(port_str, 8, "%d", port);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) {
rfbErr("rfbConnectToTcpAddr: error in getaddrinfo: %s\n", gai_strerror(rv));
return -1;
}
/* loop through all the results and connect to the first we can */
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
continue;
if (connect(sock, p->ai_addr, p->ai_addrlen) < 0) {
closesocket(sock);
continue;
}
break;
}
/* all failed */
if (p == NULL) {
rfbLogPerror("rfbConnectToTcoAddr: failed to connect\n");
sock = -1; /* set return value */
}
/* all done with this structure now */
freeaddrinfo(servinfo);
#else
struct hostent *hp;
struct sockaddr_in addr; struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
...@@ -803,7 +1001,7 @@ rfbConnectToTcpAddr(char *host, ...@@ -803,7 +1001,7 @@ rfbConnectToTcpAddr(char *host,
closesocket(sock); closesocket(sock);
return -1; return -1;
} }
#endif
return sock; return sock;
} }
......
...@@ -377,6 +377,14 @@ typedef struct _rfbScreenInfo ...@@ -377,6 +377,14 @@ typedef struct _rfbScreenInfo
char *sslkeyfile; char *sslkeyfile;
char *sslcertfile; char *sslcertfile;
#endif #endif
int ipv6port; /**< The port to listen on when using IPv6. */
char* listen6Interface;
/* We have an additional IPv6 listen socket since there are systems that
don't support dual binding sockets under *any* circumstances, for
instance OpenBSD */
SOCKET listen6Sock;
int http6Port;
SOCKET httpListen6Sock;
} rfbScreenInfo, *rfbScreenInfoPtr; } rfbScreenInfo, *rfbScreenInfoPtr;
...@@ -738,6 +746,7 @@ extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); ...@@ -738,6 +746,7 @@ extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
extern int rfbConnectToTcpAddr(char* host, int port); extern int rfbConnectToTcpAddr(char* host, int port);
extern int rfbListenOnTCPPort(int port, in_addr_t iface); extern int rfbListenOnTCPPort(int port, in_addr_t iface);
extern int rfbListenOnTCP6Port(int port, const char* iface);
extern int rfbListenOnUDPPort(int port, in_addr_t iface); extern int rfbListenOnUDPPort(int port, in_addr_t iface);
extern int rfbStringToAddr(char* string,in_addr_t* addr); extern int rfbStringToAddr(char* string,in_addr_t* addr);
extern rfbBool rfbSetNonBlocking(int sock); extern rfbBool rfbSetNonBlocking(int sock);
......
...@@ -347,7 +347,10 @@ typedef struct _rfbClient { ...@@ -347,7 +347,10 @@ typedef struct _rfbClient {
FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate; FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate;
char *listenAddress; char *listenAddress;
/* IPv6 listen socket, address and port*/
int listen6Sock;
char* listen6Address;
int listen6Port;
} rfbClient; } rfbClient;
/* cursor.c */ /* cursor.c */
......
...@@ -22,7 +22,15 @@ If the above Java applet does not work, you can also try the new JavaScript-only ...@@ -22,7 +22,15 @@ If the above Java applet does not work, you can also try the new JavaScript-only
<script language="JavaScript"> <script language="JavaScript">
<!-- <!--
function start_novnc(){ function start_novnc(){
open("novnc/vnc_auto.html?host=" + document.location.hostname + "&port=$PORT&true_color=1"); var host = document.location.hostname;
// If there are at least two colons in there, it is likely an IPv6 address. Check for square brackets and add them if missing.
if(host.search(/^.*:.*:.*$/) != -1) {
if(host.charAt(0) != "[")
host = "[" + host;
if(host.charAt(host.length-1) != "]")
host = host + "]";
}
open("novnc/vnc_auto.html?host=" + host + "&port=$PORT&true_color=1");
} }
--> -->
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment