0,0 → 1,298 |
Description: IPv6 support. |
|
--- a/sockets.c |
+++ b/sockets.c |
@@ -99,42 +99,66 @@ WriteExact(int sock, char *buf, int n) |
*/ |
|
int |
-ConnectToTcpAddr(unsigned int host, int port) |
+ConnectToTcpAddr(const char *hostname, int port) |
{ |
- int sock; |
- struct sockaddr_in addr; |
+ int sock = -1; |
int one = 1; |
|
- addr.sin_family = AF_INET; |
- addr.sin_port = htons(port); |
- addr.sin_addr.s_addr = host; |
- |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(struct addrinfo)); |
+ hints.ai_socktype = SOCK_STREAM; |
+ hints.ai_flags = AI_NUMERICSERV; |
+ |
+ char portstr[3*sizeof(int)+1]; |
if(useSSHTunnel) |
{ |
- char *remote, *gateway; |
+ const char *remote, *gateway; |
if(useSSHGateway) |
{ |
gateway=useSSHGateway; |
- remote=inet_ntoa(addr.sin_addr); |
+ remote=hostname; |
}else{ |
- gateway=inet_ntoa(addr.sin_addr); |
- remote="127.0.0.1"; |
+ gateway=hostname; |
+ remote="localhost"; |
} |
- addr.sin_port=htons(tunnel(gateway, remote, port)); |
- inet_aton("127.0.0.1",& addr.sin_addr); |
+ sprintf(portstr, "%i", tunnel(gateway, remote, port)); |
+ hostname = 0; /* Request loopback address from getaddrinfo() */ |
+ } else { |
+ sprintf(portstr, "%i", port); |
} |
- |
- sock = socket(AF_INET, SOCK_STREAM, 0); |
- if (sock < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ConnectToTcpAddr: socket"); |
- return -1; |
+ |
+ struct addrinfo *res; |
+ int eai = getaddrinfo(hostname, portstr, &hints, &res); |
+ if (eai) { |
+ if (eai == EAI_SYSTEM) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ConnectToTcpAddr: getaddrinfo"); |
+ } else { |
+ fprintf(stderr, "%s: ConnectToTcpAddr: getaddrinfo: %s\n", programName, gai_strerror(eai)); |
+ return -1; |
+ } |
} |
+ struct addrinfo *ai; |
+ for (ai = res; ai; ai = ai->ai_next) { |
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
+ if (sock < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ConnectToTcpAddr: socket"); |
+ continue; |
+ } |
|
- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ConnectToTcpAddr: connect"); |
- close(sock); |
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ConnectToTcpAddr: connect"); |
+ close(sock); |
+ sock = -1; |
+ } else { |
+ break; |
+ } |
+ } |
+ freeaddrinfo(res); |
+ if (sock < 0) { |
+ fprintf(stderr,"%s: Could not connect to any address\n", programName); |
return -1; |
} |
|
@@ -157,41 +181,64 @@ ConnectToTcpAddr(unsigned int host, int |
int |
ListenAtTcpPort(int port) |
{ |
- int sock; |
- struct sockaddr_in addr; |
- int one = 1; |
- |
- addr.sin_family = AF_INET; |
- addr.sin_port = htons(port); |
- addr.sin_addr.s_addr = INADDR_ANY; |
- |
- sock = socket(AF_INET, SOCK_STREAM, 0); |
- if (sock < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ListenAtTcpPort: socket"); |
- return -1; |
- } |
+ int sock = -1; |
+ int one = 1, zero = 0; |
+ |
+ struct sockaddr_storage addr; |
+ socklen_t addrlen; |
|
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
- (const char *)&one, sizeof(one)) < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ListenAtTcpPort: setsockopt"); |
- close(sock); |
- return -1; |
- } |
+ for (addr.ss_family = AF_INET6; sock < 0 && addr.ss_family; |
+ addr.ss_family = (addr.ss_family == AF_INET6 ? AF_INET : 0)) { |
|
- if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ListenAtTcpPort: bind"); |
- close(sock); |
- return -1; |
- } |
- |
- if (listen(sock, 5) < 0) { |
- fprintf(stderr,"%s",programName); |
- perror(": ListenAtTcpPort: listen"); |
- close(sock); |
- return -1; |
+ sock = socket(addr.ss_family, SOCK_STREAM, 0); |
+ if (sock < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ListenAtTcpPort: socket"); |
+ continue; |
+ } |
+ |
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
+ (const char *)&one, sizeof(one)) < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ListenAtTcpPort: setsockopt"); |
+ close(sock); sock = -1; |
+ continue; |
+ } |
+ |
+ if (addr.ss_family == AF_INET6) { |
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)&addr; |
+ addr6->sin6_port = htons(port); |
+ memcpy(addr6->sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any)); |
+ addrlen = sizeof(struct sockaddr_in6); |
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
+ &zero, sizeof(zero)) < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": Warning: ListenAtTcpPort: setsockopt"); |
+ } |
+ } else { |
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; |
+ addr4->sin_port = htons(port); |
+ addr4->sin_addr.s_addr = INADDR_ANY; |
+ addrlen = sizeof(struct sockaddr_in); |
+ } |
+ |
+ if (bind(sock, (struct sockaddr *)&addr, addrlen) < 0 |
+ && (addr.ss_family != AF_INET6 |
+ || setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
+ &one, sizeof(one)) < 0 |
+ || bind(sock, (struct sockaddr *)&addr, addrlen) < 0)) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ListenAtTcpPort: bind"); |
+ close(sock); sock = -1; |
+ continue; |
+ } |
+ |
+ if (listen(sock, 5) < 0) { |
+ fprintf(stderr,"%s",programName); |
+ perror(": ListenAtTcpPort: listen"); |
+ close(sock); sock = -1; |
+ continue; |
+ } |
} |
|
return sock; |
@@ -208,22 +255,39 @@ int getFreePort(void) |
for(x=0;x<100;x++) |
{ |
int port = 5500 + last % 100; |
+ char portstr[3*sizeof(int)+1]; |
+ sprintf(portstr, "%i", port); |
last+=4711; |
- |
- addr.sin_family = AF_INET; |
- addr.sin_port = htons(port); |
- addr.sin_addr.s_addr = INADDR_ANY; |
- |
- sock = socket(AF_INET, SOCK_STREAM, 0); |
- if (sock < 0 || |
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
- (const char *)&one, sizeof(one)) < 0 || |
- bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) |
- { |
- close(sock); |
- }else{ |
- close(sock); |
- return port; |
+ |
+ struct addrinfo *res = 0; |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(struct addrinfo)); |
+ hints.ai_socktype = SOCK_STREAM; |
+ |
+ int eai = getaddrinfo(0, portstr, &hints, &res); |
+ if (eai) { |
+ fprintf(stderr, "%s: getaddrinfo() failed when finding a free port: %s\n", |
+ programName, gai_strerror(eai)); |
+ return -1; |
+ } |
+ for (struct addrinfo *ai = res; ai; ai = ai->ai_next) { |
+ sock = socket(ai->ai_family, SOCK_STREAM, 0); |
+ if (sock < 0 || |
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
+ &one, sizeof(one)) < 0 || |
+ (ai->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
+ &one, sizeof(one)) < 0) || |
+ bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
+ close(sock); |
+ sock = -1; |
+ freeaddrinfo(res); |
+ break; |
+ } else { |
+ close(sock); |
+ } |
+ } |
+ if (sock > 0) { |
+ return port; |
} |
} |
return -1; |
@@ -238,7 +302,7 @@ int |
AcceptTcpConnection(int listenSock) |
{ |
int sock; |
- struct sockaddr_in addr; |
+ struct sockaddr_storage addr; |
int addrlen = sizeof(addr); |
int one = 1; |
|
--- a/rfbproto.c |
+++ b/rfbproto.c |
@@ -60,15 +60,8 @@ static char buffer[BUFFER_SIZE]; |
Bool |
ConnectToRFBServer(const char *hostname, int port) |
{ |
- unsigned int host; |
|
- if (!StringToIPAddr(hostname, &host)) { |
- fprintf(stderr,"%s: couldn't convert '%s' to host address\n", |
- programName,hostname); |
- return False; |
- } |
- |
- rfbsock = ConnectToTcpAddr(host, port); |
+ rfbsock = ConnectToTcpAddr(hostname, port); |
|
if (rfbsock < 0) { |
fprintf(stderr,"%s: unable to connect to VNC server\n", |
--- a/x2vnc.h |
+++ b/x2vnc.h |
@@ -140,7 +140,7 @@ extern Bool ReadExact(int sock, char *bu |
extern Bool WriteExact(int sock, char *buf, int n); |
extern int ListenAtTcpPort(int port); |
extern int getFreePort(); |
-extern int ConnectToTcpAddr(unsigned int host, int port); |
+extern int ConnectToTcpAddr(const char *host, int port); |
extern int AcceptTcpConnection(int listenSock); |
extern int StringToIPAddr(const char *str, unsigned int *addr); |
extern Bool SameMachine(int sock); |
--- a/args.c |
+++ b/args.c |
@@ -251,7 +251,8 @@ void processArgs(int argc, char **argv) |
|
argumentSpecified = True; |
|
- if (sscanf(argv[i], "%[^:]:%d", hostname, &port) != 2) usage(); |
+ if (sscanf(argv[i], "[%255[0-9a-f:]]:%d", hostname, &port) != 2 |
+ && sscanf(argv[i], "%255[^:]:%d", hostname, &port) != 2) usage(); |
|
if (port < 100) |
port += SERVERPORT; |