diff options
| author | Christian Beier <dontmind@freeshell.org> | 2012-04-02 16:30:53 +0200 | 
|---|---|---|
| committer | Christian Beier <dontmind@freeshell.org> | 2012-04-02 16:30:53 +0200 | 
| commit | efcdab50cc10ad121653bfff0da441495af461d3 (patch) | |
| tree | 4a758a7c8caaf070ac14efa80411d00aac1ab3b7 /libvncserver | |
| parent | ee4593425f63821280162d4e66a091479038a652 (diff) | |
| parent | 2d50fc84f7ba869767ce052aa2aa9b11a104e0de (diff) | |
| download | libtdevnc-efcdab50cc10ad121653bfff0da441495af461d3.tar.gz libtdevnc-efcdab50cc10ad121653bfff0da441495af461d3.zip  | |
Merge branch 'server-ipv6'
Diffstat (limited to 'libvncserver')
| -rw-r--r-- | libvncserver/cargs.c | 34 | ||||
| -rw-r--r-- | libvncserver/httpd.c | 91 | ||||
| -rw-r--r-- | libvncserver/main.c | 40 | ||||
| -rw-r--r-- | libvncserver/rfbserver.c | 17 | ||||
| -rw-r--r-- | libvncserver/sockets.c | 214 | 
5 files changed, 362 insertions, 34 deletions
diff --git a/libvncserver/cargs.c b/libvncserver/cargs.c index 2e973e8..b9eb02b 100644 --- a/libvncserver/cargs.c +++ b/libvncserver/cargs.c @@ -22,6 +22,9 @@ rfbUsage(void)      rfbProtocolExtension* extension;      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, "-rfbauth passwd-file   use authentication on RFB protocol\n"                      "                       (use 'storepasswd' to create a password file)\n"); @@ -42,10 +45,17 @@ rfbUsage(void)                                                                  "instead)\n");      fprintf(stderr, "-httpdir dir-path      enable http server using dir-path home\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, "-progressive height    enable progressive updating for slow links\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"); +#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)  	if(extension->usage) @@ -80,6 +90,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])  		return FALSE;  	    }  	    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 */              if (i + 1 >= *argc) {  		rfbUsage(); @@ -147,6 +165,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])  		return FALSE;  	    }              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) {              rfbScreen->httpEnableProxyConnect = TRUE;          } else if (strcmp(argv[i], "-progressive") == 0) {  /* -httpport portnum */ @@ -163,6 +189,14 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])              if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {                  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          } else if (strcmp(argv[i], "-sslkeyfile") == 0) {  /* -sslkeyfile sslkeyfile */              if (i + 1 >= *argc) { diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c index 3025aae..ed91e46 100644 --- a/libvncserver/httpd.c +++ b/libvncserver/httpd.c @@ -3,6 +3,7 @@   */  /* + *  Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>   *  Copyright (C) 2002 RealVNC Ltd.   *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.   * @@ -102,17 +103,27 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)  	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 =        rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) {  	rfbLogPerror("ListenOnTCPPort");  	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) { @@ -121,6 +132,18 @@ void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) {  	FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds);  	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)      int nfds;      fd_set fds;      struct timeval tv; +#ifdef LIBVNCSERVER_IPv6 +    struct sockaddr_storage addr; +#else      struct sockaddr_in addr; +#endif      socklen_t addrlen = sizeof(addr);      if (!rfbScreen->httpDir) @@ -145,12 +172,15 @@ rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)      FD_ZERO(&fds);      FD_SET(rfbScreen->httpListenSock, &fds); +    if (rfbScreen->httpListen6Sock >= 0) { +	FD_SET(rfbScreen->httpListen6Sock, &fds); +    }      if (rfbScreen->httpSock >= 0) {  	FD_SET(rfbScreen->httpSock, &fds);      }      tv.tv_sec = 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) {  	return;      } @@ -167,19 +197,36 @@ rfbHttpCheckFds(rfbScreenInfoPtr 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 = accept(rfbScreen->httpListenSock, -			       (struct sockaddr *)&addr, &addrlen)) < 0) { -	    rfbLogPerror("httpCheckFds: accept"); -	    return; +	if(FD_ISSET(rfbScreen->httpListenSock, &fds)) { +	    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"); +	      return; +	    } +	} +  #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)) {  	  rfbLog("Rejected HTTP connection from client %s\n", -		 inet_ntoa(addr.sin_addr)); +		 host);  	  close(rfbScreen->httpSock);  	  rfbScreen->httpSock=-1;  	  return; @@ -212,7 +259,11 @@ static rfbClientRec cl;  static void  httpProcessInput(rfbScreenInfoPtr rfbScreen)  { +#ifdef LIBVNCSERVER_IPv6 +    struct sockaddr_storage addr; +#else      struct sockaddr_in addr; +#endif      socklen_t addrlen = sizeof(addr);      char fullFname[512];      char params[1024]; @@ -335,8 +386,16 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)      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,  	   inet_ntoa(addr.sin_addr)); +#endif      /* Extract parameters from the URL string if necessary */ @@ -562,7 +621,8 @@ parseParams(const char *request, char *result, int max_bytes)  /*   * 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 @@ -571,7 +631,8 @@ validateString(char *str)      char *ptr;      for (ptr = str; *ptr != '\0'; ptr++) { -	if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { +	if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.' +	    && *ptr != ':' && *ptr != '[' && *ptr != ']' ) {  	    if (*ptr == '+') {  		*ptr = ' ';  	    } else { diff --git a/libvncserver/main.c b/libvncserver/main.c index 0edf994..4cb18ac 100644 --- a/libvncserver/main.c +++ b/libvncserver/main.c @@ -569,21 +569,37 @@ listenerRun(void *data)  {      rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;      int client_fd; -    struct sockaddr_in peer; -    rfbClientPtr cl; +    struct sockaddr_storage peer; +    rfbClientPtr cl = NULL;      socklen_t len; - -    len = sizeof(peer); +    fd_set listen_fds;  /* temp file descriptor list for select() */      /* TODO: this thread wont die by restarting the server */      /* TODO: HTTP is not handled */ -    while ((client_fd = accept(screen->listenSock,  -                               (struct sockaddr*)&peer, &len)) >= 0) { -        cl = rfbNewClient(screen,client_fd); -        len = sizeof(peer); - +    while (1) { +        client_fd = -1; +        FD_ZERO(&listen_fds); +	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 ) -		rfbStartOnHoldClient(cl); +	  rfbStartOnHoldClient(cl);      }      return(NULL);  } @@ -809,6 +825,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,     screen->clientHead=NULL;     screen->pointerClient=NULL;     screen->port=5900; +   screen->ipv6port=5900;     screen->socketState=RFB_SOCKET_INIT;     screen->inetdInitDone = FALSE; @@ -821,12 +838,15 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,     screen->maxFd=0;     screen->listenSock=-1; +   screen->listen6Sock=-1;     screen->httpInitDone=FALSE;     screen->httpEnableProxyConnect=FALSE;     screen->httpPort=0; +   screen->http6Port=0;     screen->httpDir=NULL;     screen->httpListenSock=-1; +   screen->httpListen6Sock=-1;     screen->httpSock=-1;     screen->desktopName = "LibVNCServer"; diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index 9be255f..23c4d77 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -50,6 +50,7 @@  #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H  #include <netinet/in.h>  #include <netinet/tcp.h> +#include <netdb.h>  #include <arpa/inet.h>  #endif  #endif @@ -270,8 +271,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,      rfbProtocolVersionMsg pv;      rfbClientIteratorPtr iterator;      rfbClientPtr cl,cl_; +#ifdef LIBVNCSERVER_IPv6 +    struct sockaddr_storage addr; +#else      struct sockaddr_in addr; -    socklen_t addrlen = sizeof(struct sockaddr_in); +#endif +    socklen_t addrlen = sizeof(addr);      rfbProtocolExtension* extension;      cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1); @@ -294,7 +299,17 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,        int one=1;        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)); +#endif        rfbLog("  other clients:\n");        iterator = rfbGetClientIterator(rfbScreen); diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 415f712..84c9c98 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -19,6 +19,7 @@   */  /* + *  Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>   *  Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin   *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.   *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.   @@ -137,6 +138,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)      if(rfbScreen->autoPort) {          int i; +        FD_ZERO(&(rfbScreen->allFds)); +          rfbLog("Autoprobing TCP port \n");          for (i = 5900; i < 6000; i++) {              if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) { @@ -150,22 +153,52 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)  	    return;          } -        rfbLog("Autoprobing selected port %d\n", rfbScreen->port); -        FD_ZERO(&(rfbScreen->allFds)); +        rfbLog("Autoprobing selected TCP port %d\n", rfbScreen->port);          FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));          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) { -      rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port); +      FD_ZERO(&(rfbScreen->allFds));        if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {  	rfbLogPerror("ListenOnTCPPort");  	return;        } - -      FD_ZERO(&(rfbScreen->allFds)); +      rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);   +          FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));        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) { @@ -175,6 +208,8 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen)  	    rfbLogPerror("ListenOnUDPPort");  	    return;  	} +	rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);   +  	FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));  	rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);      } @@ -199,6 +234,12 @@ void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)  	rfbScreen->listenSock=-1;      } +    if(rfbScreen->listen6Sock>-1) { +	closesocket(rfbScreen->listen6Sock); +	FD_CLR(rfbScreen->listen6Sock,&rfbScreen->allFds); +	rfbScreen->listen6Sock=-1; +    } +      if(rfbScreen->udpSock>-1) {  	closesocket(rfbScreen->udpSock);  	FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds); @@ -270,6 +311,16 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)  		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->udpClient)  		rfbNewUDPClient(rfbScreen); @@ -330,10 +381,33 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)  {      const int one = 1;      int sock = -1; +#ifdef LIBVNCSERVER_IPv6 +    struct sockaddr_storage addr; +#else      struct sockaddr_in addr; +#endif      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) {        rfbLogPerror("rfbCheckFds: accept");        return FALSE; @@ -361,7 +435,15 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)      }  #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)); +#endif      rfbNewClient(rfbScreen,sock); @@ -774,12 +856,128 @@ rfbListenOnTCPPort(int port,      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  rfbConnectToTcpAddr(char *host,                      int port)  { -    struct hostent *hp;      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;      memset(&addr, 0, sizeof(addr)); @@ -803,7 +1001,7 @@ rfbConnectToTcpAddr(char *host,  	closesocket(sock);  	return -1;      } - +#endif      return sock;  }  | 
