Commit e7dfd0a9 authored by Christian Beier's avatar Christian Beier

IPv6 support for LibVNCServer, part two: Let the http server listen on IPv6, too.

As done with the RFB sockets, this uses a separate-socket approach as well.
parent 0e74b5db
...@@ -45,6 +45,9 @@ rfbUsage(void) ...@@ -45,6 +45,9 @@ 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");
...@@ -162,6 +165,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) ...@@ -162,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 */
......
...@@ -102,17 +102,27 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) ...@@ -102,17 +102,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 +131,18 @@ void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { ...@@ -121,6 +131,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 +156,11 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -134,7 +156,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 +171,15 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -145,12 +171,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 +196,36 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -167,19 +196,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 +258,11 @@ static rfbClientRec cl; ...@@ -212,7 +258,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 +385,16 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen) ...@@ -335,8 +385,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 +620,8 @@ parseParams(const char *request, char *result, int max_bytes) ...@@ -562,7 +620,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 +630,8 @@ validateString(char *str) ...@@ -571,7 +630,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 {
......
...@@ -843,8 +843,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -843,8 +843,10 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
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";
......
...@@ -383,6 +383,8 @@ typedef struct _rfbScreenInfo ...@@ -383,6 +383,8 @@ typedef struct _rfbScreenInfo
don't support dual binding sockets under *any* circumstances, for don't support dual binding sockets under *any* circumstances, for
instance OpenBSD */ instance OpenBSD */
SOCKET listen6Sock; SOCKET listen6Sock;
int http6Port;
SOCKET httpListen6Sock;
} rfbScreenInfo, *rfbScreenInfoPtr; } rfbScreenInfo, *rfbScreenInfoPtr;
......
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