From 68e7696a27b31034876f594f242a229ff2b74fa4 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 29 Jun 2010 20:51:08 +0800 Subject: [PATCH] libvncclient: add ipv6 support [jes: pulled the "host" declarations into the conditionally compiled blocks where that variable is used. Also fixed non-IPv6 connections.] Signed-off-by: Vic Lee Signed-off-by: Johannes Schindelin --- configure.ac | 9 ++++++ libvncclient/rfbproto.c | 38 ++++++++++++++++--------- libvncclient/sockets.c | 62 +++++++++++++++++++++++++++++++++++++++++ rfb/rfbclient.h | 1 + 4 files changed, 97 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 6516523..b7cfcc1 100644 --- a/configure.ac +++ b/configure.ac @@ -697,6 +697,15 @@ if test "x$with_gnutls" != "xno"; then fi fi +# IPv6 +AH_TEMPLATE(IPv6, [Enable IPv6 support]) +AC_ARG_WITH(ipv6, +[ --without-ipv6 disable IPv6 support],,) +if test "x$with_ipv6" != "xno"; then + AC_CHECK_FUNC(getaddrinfo, AC_DEFINE(IPv6,1), + AC_CHECK_LIB(socket, getaddrinfo, AC_DEFINE(IPv6,1))) +fi + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h]) diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index 33307d2..83ba3a5 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -363,8 +363,6 @@ IsUnixSocket(const char *name) rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port) { - unsigned int host; - if (client->serverPort==-1) { /* serverHost is a file recorded by vncrec. */ const char* magic="vncLog0.0"; @@ -399,12 +397,20 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port) else #endif { - /* serverHost is a hostname */ - if (!StringToIPAddr(hostname, &host)) { - rfbClientLog("Couldn't convert '%s' to host address\n", hostname); - return FALSE; +#ifdef LIBVNCSERVER_IPv6 + client->sock = ConnectClientToTcpAddr6(hostname, port); + if (client->sock == -1) +#endif + { + unsigned int host; + + /* serverHost is a hostname */ + if (!StringToIPAddr(hostname, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", hostname); + return FALSE; + } + client->sock = ConnectClientToTcpAddr(host, port); } - client->sock = ConnectClientToTcpAddr(host, port); } if (client->sock < 0) { @@ -421,17 +427,23 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port) rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort) { - unsigned int host; rfbProtocolVersionMsg pv; int major,minor; char tmphost[250]; - if (!StringToIPAddr(repeaterHost, &host)) { - rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost); - return FALSE; - } +#ifdef LIBVNCSERVER_IPv6 + client->sock = ConnectClientToTcpAddr6(repeaterHost, repeaterPort); + if (client->sock == -1) +#endif + { + unsigned int host; + if (!StringToIPAddr(repeaterHost, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost); + return FALSE; + } - client->sock = ConnectClientToTcpAddr(host, repeaterPort); + client->sock = ConnectClientToTcpAddr(host, repeaterPort); + } if (client->sock < 0) { rfbClientLog("Unable to connect to VNC repeater\n"); diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index 598dd39..ff4fe48 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -336,6 +336,68 @@ ConnectClientToTcpAddr(unsigned int host, int port) return sock; } +int +ConnectClientToTcpAddr6(const char *hostname, int port) +{ +#ifdef LIBVNCSERVER_IPv6 + int sock; + int n; + struct addrinfo hints, *res, *ressave; + char port_s[10]; + int one = 1; + + if (!initSockets()) + return -1; + + snprintf(port_s, 10, "%d", port); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if ((n = getaddrinfo(hostname, port_s, &hints, &res))) + { + rfbClientErr("ConnectClientToTcpAddr6: getaddrinfo (%s)\n", gai_strerror(n)); + return -1; + } + + ressave = res; + sock = -1; + while (res) + { + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock >= 0) + { + if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) + break; + close(sock); + sock = -1; + } + res = res->ai_next; + } + freeaddrinfo(ressave); + + if (sock == -1) + { + rfbClientErr("ConnectClientToTcpAddr6: connect\n"); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("ConnectToTcpAddr: setsockopt\n"); + close(sock); + return -1; + } + + return sock; + +#else + + rfbClientErr("ConnectClientToTcpAddr6: IPv6 disabled\n"); + return -1; + +#endif +} + int ConnectClientToUnixSock(const char *sockFile) { diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h index bc4ec14..b38f335 100644 --- a/rfb/rfbclient.h +++ b/rfb/rfbclient.h @@ -384,6 +384,7 @@ extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n); extern int FindFreeTcpPort(void); extern int ListenAtTcpPort(int port); extern int ConnectClientToTcpAddr(unsigned int host, int port); +extern int ConnectClientToTcpAddr6(const char *hostname, int port); extern int ConnectClientToUnixSock(const char *sockFile); extern int AcceptTcpConnection(int listenSock); extern rfbBool SetNonBlocking(int sock);