diff options
Diffstat (limited to 'libvncclient/sockets.c')
-rw-r--r-- | libvncclient/sockets.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c index be9924a..1a8df56 100644 --- a/libvncclient/sockets.c +++ b/libvncclient/sockets.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2011-2012 Christian Beier <[email protected]> * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -494,8 +495,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 +529,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); |