diff options
author | Christian Beier <dontmind@freeshell.org> | 2012-03-10 21:31:44 +0100 |
---|---|---|
committer | Christian Beier <dontmind@freeshell.org> | 2012-03-10 21:31:44 +0100 |
commit | 75bfb1f5d396b2908a9615cd02bebfc952baa045 (patch) | |
tree | 9f775fdd6b00f83cdaf7f0fc45601b825fd6521d /libvncclient/sockets.c | |
parent | edc75fa4f4f0dbadf7cb21a7511626dd35a3c330 (diff) | |
download | libvncserver-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.c | 63 |
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); |