summaryrefslogtreecommitdiffstats
path: root/libvncclient/sockets.c
diff options
context:
space:
mode:
authorChristian Beier <dontmind@freeshell.org>2012-03-10 21:31:44 +0100
committerChristian Beier <dontmind@freeshell.org>2012-03-10 21:31:44 +0100
commit75bfb1f5d396b2908a9615cd02bebfc952baa045 (patch)
tree9f775fdd6b00f83cdaf7f0fc45601b825fd6521d /libvncclient/sockets.c
parentedc75fa4f4f0dbadf7cb21a7511626dd35a3c330 (diff)
downloadlibvncserver-75bfb1f5d396b2908a9615cd02bebfc952baa045.zip
libvncserver-75bfb1f5d396b2908a9615cd02bebfc952baa045.tar.gz
IPv6 support for LibVNCServer, part three: make reverse connections IPv6-capable.
Besided making libvncserver reverseVNC IPv6-aware, this introduces some changes on the client side as well to make clients listen on IPv6 sockets, too. Like the server side, this also uses a separate-socket approach.
Diffstat (limited to 'libvncclient/sockets.c')
-rw-r--r--libvncclient/sockets.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c
index be9924a..01ec3a2 100644
--- a/libvncclient/sockets.c
+++ b/libvncclient/sockets.c
@@ -494,8 +494,9 @@ int
ListenAtTcpPortAndAddress(int port, const char *address)
{
int sock;
- struct sockaddr_in addr;
int one = 1;
+#ifndef LIBVNCSERVER_IPv6
+ struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
@@ -527,6 +528,66 @@ ListenAtTcpPortAndAddress(int port, const char *address)
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) {
rfbClientErr("ListenAtTcpPort: listen\n");
close(sock);
OpenPOWER on IntegriCloud