summaryrefslogtreecommitdiffstats
path: root/x11vnc/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/inet.c')
-rw-r--r--x11vnc/inet.c936
1 files changed, 0 insertions, 936 deletions
diff --git a/x11vnc/inet.c b/x11vnc/inet.c
deleted file mode 100644
index 23a911e..0000000
--- a/x11vnc/inet.c
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
- All rights reserved.
-
-This file is part of x11vnc.
-
-x11vnc is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-x11vnc is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with x11vnc; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
-or see <http://www.gnu.org/licenses/>.
-
-In addition, as a special exception, Karl J. Runge
-gives permission to link the code of its release of x11vnc with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables. You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL". If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so. If you do not wish to do
-so, delete this exception statement from your version.
-*/
-
-/* -- inet.c -- */
-
-#include "x11vnc.h"
-#include "unixpw.h"
-#include "sslhelper.h"
-
-/*
- * Simple utility to map host name to dotted IP address. Ignores aliases.
- * Up to caller to free returned string.
- */
-char *host2ip(char *host);
-char *raw2host(char *raw, int len);
-char *raw2ip(char *raw);
-char *ip2host(char *ip);
-int ipv6_ip(char *host);
-int dotted_ip(char *host, int partial);
-int get_remote_port(int sock);
-int get_local_port(int sock);
-char *get_remote_host(int sock);
-char *get_local_host(int sock);
-char *ident_username(rfbClientPtr client);
-int find_free_port(int start, int end);
-int find_free_port6(int start, int end);
-int have_ssh_env(void);
-char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen);
-char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen);
-int listen6(int port);
-int listen_unix(char *file);
-int accept_unix(int s);
-int connect_tcp(char *host, int port);
-int listen_tcp(int port, in_addr_t iface, int try6);
-
-static int get_port(int sock, int remote);
-static char *get_host(int sock, int remote);
-
-char *host2ip(char *host) {
- struct hostent *hp;
- struct sockaddr_in addr;
- char *str;
-
- if (! host_lookup) {
- return NULL;
- }
-
- hp = gethostbyname(host);
- if (!hp) {
- return NULL;
- }
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
- str = strdup(inet_ntoa(addr.sin_addr));
- return str;
-}
-
-char *raw2host(char *raw, int len) {
- char *str;
-#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
- struct hostent *hp;
-
- if (! host_lookup) {
- return strdup("unknown");
- }
-
- hp = gethostbyaddr(raw, len, AF_INET);
- if (!hp) {
- return strdup(inet_ntoa(*((struct in_addr *)raw)));
- }
- str = strdup(hp->h_name);
-#else
- str = strdup("unknown");
-#endif
- return str;
-}
-
-char *raw2ip(char *raw) {
- return strdup(inet_ntoa(*((struct in_addr *)raw)));
-}
-
-char *ip2host(char *ip) {
- char *str;
-#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
- struct hostent *hp;
- in_addr_t iaddr;
-
- if (! host_lookup) {
- return strdup("unknown");
- }
-
- iaddr = inet_addr(ip);
- if (iaddr == htonl(INADDR_NONE)) {
- return strdup("unknown");
- }
-
- hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET);
- if (!hp) {
- return strdup("unknown");
- }
- str = strdup(hp->h_name);
-#else
- str = strdup("unknown");
-#endif
- return str;
-}
-
-int ipv6_ip(char *host_in) {
- char *p, *host, a[2];
- int ncol = 0, nhex = 0;
-
- if (host_in[0] == '[') {
- host = host_in + 1;
- } else {
- host = host_in;
- }
-
- if (strstr(host, "::ffff:") == host || strstr(host, "::FFFF:") == host) {
- return dotted_ip(host + strlen("::ffff:"), 0);
- }
-
- a[1] = '\0';
-
- p = host;
- while (*p != '\0' && *p != '%' && *p != ']') {
- if (*p == ':') {
- ncol++;
- } else {
- nhex++;
- }
- a[0] = *p;
- if (strpbrk(a, ":abcdef0123456789") == a) {
- p++;
- continue;
- }
- return 0;
- }
- if (ncol < 2 || ncol > 8 || nhex == 0) {
- return 0;
- } else {
- return 1;
- }
-}
-
-int dotted_ip(char *host, int partial) {
- int len, dots = 0;
- char *p = host;
-
- if (!host) {
- return 0;
- }
-
- if (!isdigit((unsigned char) host[0])) {
- return 0;
- }
-
- len = strlen(host);
- if (!partial && !isdigit((unsigned char) host[len-1])) {
- return 0;
- }
-
- while (*p != '\0') {
- if (*p == '.') dots++;
- if (*p == '.' || isdigit((unsigned char) (*p))) {
- p++;
- continue;
- }
- return 0;
- }
- if (!partial && dots != 3) {
- return 0;
- }
- return 1;
-}
-
-static int get_port(int sock, int remote) {
- struct sockaddr_in saddr;
- unsigned int saddr_len;
- int saddr_port;
-
- saddr_len = sizeof(saddr);
- memset(&saddr, 0, sizeof(saddr));
- saddr_port = -1;
- if (remote) {
- if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_port = ntohs(saddr.sin_port);
- }
- } else {
- if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_port = ntohs(saddr.sin_port);
- }
- }
- return saddr_port;
-}
-
-int get_remote_port(int sock) {
- return get_port(sock, 1);
-}
-
-int get_local_port(int sock) {
- return get_port(sock, 0);
-}
-
-static char *get_host(int sock, int remote) {
- struct sockaddr_in saddr;
- unsigned int saddr_len;
- int saddr_port;
- char *saddr_ip_str = NULL;
-
- saddr_len = sizeof(saddr);
- memset(&saddr, 0, sizeof(saddr));
- saddr_port = -1;
-#if LIBVNCSERVER_HAVE_NETINET_IN_H
- if (remote) {
- if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_ip_str = inet_ntoa(saddr.sin_addr);
- }
- } else {
- if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_ip_str = inet_ntoa(saddr.sin_addr);
- }
- }
-#endif
- if (! saddr_ip_str) {
- saddr_ip_str = "unknown";
- }
- return strdup(saddr_ip_str);
-}
-
-char *get_remote_host(int sock) {
- return get_host(sock, 1);
-}
-
-char *get_local_host(int sock) {
- return get_host(sock, 0);
-}
-
-char *ident_username(rfbClientPtr client) {
- ClientData *cd = (ClientData *) client->clientData;
- char *str, *newhost, *user = NULL, *newuser = NULL;
- int len;
-
- if (cd) {
- user = cd->username;
- }
- if (!user || *user == '\0') {
- int n, sock, ok = 0;
- int block = 0;
- int refused = 0;
-
- /*
- * need to check to see if the operation will block for
- * a long time: a firewall may just ignore our packets.
- */
-#if LIBVNCSERVER_HAVE_FORK
- { pid_t pid, pidw;
- int rc;
- if ((pid = fork()) > 0) {
- usleep(100 * 1000); /* 0.1 sec for quick success or refusal */
- pidw = waitpid(pid, &rc, WNOHANG);
- if (pidw <= 0) {
- usleep(1500 * 1000); /* 1.5 sec */
- pidw = waitpid(pid, &rc, WNOHANG);
- if (pidw <= 0) {
- int rc2;
- rfbLog("ident_username: set block=1 (hung)\n");
- block = 1;
- kill(pid, SIGTERM);
- usleep(100 * 1000);
- waitpid(pid, &rc2, WNOHANG);
- }
- }
- if (pidw > 0 && !block) {
- if (WIFEXITED(rc) && WEXITSTATUS(rc) == 1) {
- rfbLog("ident_username: set refused=1 (exit)\n");
- refused = 1;
- }
- }
- } else if (pid == -1) {
- ;
- } else {
- /* child */
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-
- if ((sock = connect_tcp(client->host, 113)) < 0) {
- exit(1);
- } else {
- close(sock);
- exit(0);
- }
- }
- }
-#endif
- if (block || refused) {
- ;
- } else if ((sock = connect_tcp(client->host, 113)) < 0) {
- rfbLog("ident_username: could not connect to ident: %s:%d\n",
- client->host, 113);
- } else {
- char msg[128];
- int ret;
- fd_set rfds;
- struct timeval tv;
- int rport = get_remote_port(client->sock);
- int lport = get_local_port(client->sock);
-
- sprintf(msg, "%d, %d\r\n", rport, lport);
- n = write(sock, msg, strlen(msg));
-
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
- tv.tv_sec = 3;
- tv.tv_usec = 0;
- ret = select(sock+1, &rfds, NULL, NULL, &tv);
-
- if (ret > 0) {
- int i;
- char *q, *p;
- for (i=0; i < (int) sizeof(msg); i++) {
- msg[i] = '\0';
- }
- usleep(250*1000);
- n = read(sock, msg, 127);
- close(sock);
- if (n <= 0) goto badreply;
-
- /* 32782 , 6000 : USERID : UNIX :runge */
- q = strstr(msg, "USERID");
- if (!q) goto badreply;
- q = strstr(q, ":");
- if (!q) goto badreply;
- q++;
- q = strstr(q, ":");
- if (!q) goto badreply;
- q++;
- q = lblanks(q);
- p = q;
- while (*p) {
- if (*p == '\r' || *p == '\n') {
- *p = '\0';
- }
- p++;
- }
- ok = 1;
- if (strlen(q) > 24) {
- *(q+24) = '\0';
- }
- newuser = strdup(q);
-
- badreply:
- n = 0; /* avoid syntax error */
- } else {
- close(sock);
- }
- }
- if (! ok || !newuser) {
- newuser = strdup("unknown-user");
- }
- if (cd) {
- if (cd->username) {
- free(cd->username);
- }
- cd->username = newuser;
- }
- user = newuser;
- }
- if (!strcmp(user, "unknown-user") && cd && cd->unixname[0] != '\0') {
- user = cd->unixname;
- }
- if (unixpw && openssl_last_ip && strstr("UNIX:", user) != user) {
- newhost = ip2host(openssl_last_ip);
- } else {
- newhost = ip2host(client->host);
- }
- len = strlen(user) + 1 + strlen(newhost) + 1;
- str = (char *) malloc(len);
- sprintf(str, "%s@%s", user, newhost);
- free(newhost);
- return str;
-}
-
-int find_free_port(int start, int end) {
- int port;
- if (start <= 0) {
- start = 1024;
- }
- if (end <= 0) {
- end = 65530;
- }
- for (port = start; port <= end; port++) {
- int sock = listen_tcp(port, htonl(INADDR_ANY), 0);
- if (sock >= 0) {
- close(sock);
- return port;
- }
- }
- return 0;
-}
-
-int find_free_port6(int start, int end) {
- int port;
- if (start <= 0) {
- start = 1024;
- }
- if (end <= 0) {
- end = 65530;
- }
- for (port = start; port <= end; port++) {
- int sock = listen6(port);
- if (sock >= 0) {
- close(sock);
- return port;
- }
- }
- return 0;
-}
-
-int have_ssh_env(void) {
- char *str, *p = getenv("SSH_CONNECTION");
- char *rhost, *rport, *lhost, *lport;
-
- if (! p) {
- char *q = getenv("SSH_CLIENT");
- if (! q) {
- return 0;
- }
- if (strstr(q, "127.0.0.1") != NULL) {
- return 0;
- }
- return 1;
- }
-
- if (strstr(p, "127.0.0.1") != NULL) {
- return 0;
- }
-
- str = strdup(p);
-
- p = strtok(str, " ");
- rhost = p;
-
- p = strtok(NULL, " ");
- if (! p) goto fail;
-
- rport = p;
-
- p = strtok(NULL, " ");
- if (! p) goto fail;
-
- lhost = p;
-
- p = strtok(NULL, " ");
- if (! p) goto fail;
-
- lport = p;
-
-if (0) fprintf(stderr, "%d/%d - '%s' '%s'\n", atoi(rport), atoi(lport), rhost, lhost);
-
- if (atoi(rport) <= 16 || atoi(rport) > 65535) {
- goto fail;
- }
- if (atoi(lport) <= 16 || atoi(lport) > 65535) {
- goto fail;
- }
-
- if (!strcmp(rhost, lhost)) {
- goto fail;
- }
-
- free(str);
-
- return 1;
-
- fail:
-
- free(str);
-
- return 0;
-}
-
-char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) {
-#if X11VNC_IPV6
- char name[200];
- if (noipv6) {
- return strdup("unknown");
- }
- if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) {
- return strdup(name);
- }
-#endif
- return strdup("unknown");
-}
-
-char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) {
-#if X11VNC_IPV6 && defined(NI_NUMERICHOST)
- char name[200];
- if (noipv6) {
- return strdup("unknown");
- }
- if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) {
- return strdup(name);
- }
-#endif
- return strdup("unknown");
-}
-
-int listen6(int port) {
-#if X11VNC_IPV6
- struct sockaddr_in6 sin;
- int fd = -1, one = 1;
-
- if (noipv6) {
- return -1;
- }
- if (port <= 0 || 65535 < port) {
- /* for us, invalid port means do not listen. */
- return -1;
- }
-
- fd = socket(AF_INET6, SOCK_STREAM, 0);
- if (fd < 0) {
- rfbLogPerror("listen6: socket");
- rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
- return -1;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
- rfbLogPerror("listen6: setsockopt SO_REUSEADDR");
- close(fd);
- return -1;
- }
-
-#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
- if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
- rfbLogPerror("listen6: setsockopt IPV6_V6ONLY");
- close(fd);
- return -1;
- }
-#endif
-
- memset((char *)&sin, 0, sizeof(sin));
- sin.sin6_family = AF_INET6;
- sin.sin6_port = htons(port);
- sin.sin6_addr = in6addr_any;
-
- if (listen_str6) {
- if (!strcmp(listen_str6, "localhost") || !strcmp(listen_str6, "::1")) {
- sin.sin6_addr = in6addr_loopback;
- } else {
- int err;
- struct addrinfo *ai;
- struct addrinfo hints;
- char service[32];
-
- memset(&hints, 0, sizeof(hints));
- sprintf(service, "%d", port);
-
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
-#ifdef AI_ADDRCONFIG
- hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-#ifdef AI_NUMERICHOST
- if(ipv6_ip(listen_str6)) {
- hints.ai_flags |= AI_NUMERICHOST;
- }
-#endif
-#ifdef AI_NUMERICSERV
- hints.ai_flags |= AI_NUMERICSERV;
-#endif
- err = getaddrinfo(listen_str6, service, &hints, &ai);
- if (err == 0) {
- struct addrinfo *ap = ai;
- err = 1;
- while (ap != NULL) {
- char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
- if (!s) s = strdup("unknown");
-
- rfbLog("listen6: checking: %s family: %d\n", s, ap->ai_family);
- if (ap->ai_family == AF_INET6) {
- memcpy((char *)&sin, ap->ai_addr, sizeof(sin));
- rfbLog("listen6: using: %s scope_id: %d\n", s, sin.sin6_scope_id);
- err = 0;
- free(s);
- break;
- }
- free(s);
- ap = ap->ai_next;
- }
- freeaddrinfo(ai);
- }
-
- if (err != 0) {
- rfbLog("Invalid or Unsupported -listen6 string: %s\n", listen_str6);
- close(fd);
- return -1;
- }
- }
- } else if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
- sin.sin6_addr = in6addr_loopback;
- } else if (listen_str) {
- if (!strcmp(listen_str, "localhost")) {
- sin.sin6_addr = in6addr_loopback;
- }
- }
-
- if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
- rfbLogPerror("listen6: bind");
- close(fd);
- return -1;
- }
- if (listen(fd, 32) < 0) {
- rfbLogPerror("listen6: listen");
- close(fd);
- return -1;
- }
- return fd;
-#else
- if (port) {}
- return -1;
-#endif
-}
-
-#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
-#include <sys/un.h>
-#endif
-
-int listen_unix(char *file) {
-#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
- if (sock) {}
- return -1;
-#else
- int s, len;
- struct sockaddr_un saun;
-
- s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s < 0) {
- rfbLogPerror("listen_unix: socket");
- return -1;
- }
- saun.sun_family = AF_UNIX;
- strcpy(saun.sun_path, file);
- unlink(file);
-
- len = sizeof(saun.sun_family) + strlen(saun.sun_path);
-
- if (bind(s, (struct sockaddr *)&saun, len) < 0) {
- rfbLogPerror("listen_unix: bind");
- close(s);
- return -1;
- }
-
- if (listen(s, 32) < 0) {
- rfbLogPerror("listen_unix: listen");
- close(s);
- return -1;
- }
- rfbLog("listening on unix socket: %s fd=%d\n", file, s);
- return s;
-#endif
-}
-
-int accept_unix(int s) {
-#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
- if (s) {}
- return -1;
-#else
- int fd, fromlen;
- struct sockaddr_un fsaun;
-
- fd = accept(s, (struct sockaddr *)&fsaun, &fromlen);
- if (fd < 0) {
- rfbLogPerror("accept_unix: accept");
- return -1;
- }
- return fd;
-#endif
-}
-
-int connect_tcp(char *host, int port) {
- double t0 = dnow();
- int fd = -1;
- int fail4 = noipv4;
- if (getenv("IPV4_FAILS")) {
- fail4 = 2;
- }
-
- rfbLog("connect_tcp: trying: %s %d\n", host, port);
-
- if (fail4) {
- if (fail4 > 1) {
- rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n");
- }
- } else {
- fd = rfbConnectToTcpAddr(host, port);
- }
-
- if (fd >= 0) {
- return fd;
- }
- rfbLogPerror("connect_tcp: connection failed");
-
- if (dnow() - t0 < 4.0) {
- rfbLog("connect_tcp: re-trying %s %d\n", host, port);
- usleep (100 * 1000);
- if (!fail4) {
- fd = rfbConnectToTcpAddr(host, port);
- }
- if (fd < 0) {
- rfbLogPerror("connect_tcp: connection failed");
- }
- }
-
- if (fd < 0 && !noipv6) {
-#if X11VNC_IPV6
- int err;
- struct addrinfo *ai;
- struct addrinfo hints;
- char service[32], *host2, *q;
-
- rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port);
-
- memset(&hints, 0, sizeof(hints));
- sprintf(service, "%d", port);
-
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-#ifdef AI_ADDRCONFIG
- hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- if(ipv6_ip(host)) {
-#ifdef AI_NUMERICHOST
- rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host);
- hints.ai_flags |= AI_NUMERICHOST;
-#endif
- }
-#ifdef AI_NUMERICSERV
- hints.ai_flags |= AI_NUMERICSERV;
-#endif
-
- if (!strcmp(host, "127.0.0.1")) {
- host2 = strdup("::1");
- } else if (host[0] == '[') {
- host2 = strdup(host+1);
- } else {
- host2 = strdup(host);
- }
- q = strrchr(host2, ']');
- if (q) {
- *q = '\0';
- }
-
- err = getaddrinfo(host2, service, &hints, &ai);
- if (err != 0) {
- rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
- usleep(100 * 1000);
- err = getaddrinfo(host2, service, &hints, &ai);
- }
- free(host2);
-
- if (err != 0) {
- rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
- } else {
- struct addrinfo *ap = ai;
- while (ap != NULL) {
- int sock;
-
- if (fail4) {
- struct sockaddr_in6 *s6ptr;
- if (ap->ai_family != AF_INET6) {
- rfbLog("connect_tcp[ipv6]: skipping AF_INET address under -noipv4\n");
- ap = ap->ai_next;
- continue;
- }
-#ifdef IN6_IS_ADDR_V4MAPPED
- s6ptr = (struct sockaddr_in6 *) ap->ai_addr;
- if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) {
- rfbLog("connect_tcp[ipv6]: skipping V4MAPPED address under -noipv4\n");
- ap = ap->ai_next;
- continue;
- }
-#endif
- }
-
- sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
-
- if (sock == -1) {
- rfbLogPerror("connect_tcp[ipv6]: socket");
- if (0) rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
- } else {
- int res = -1, dmsg = 0;
- char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
- if (!s) s = strdup("unknown");
-
- rfbLog("connect_tcp[ipv6]: trying sock=%d fam=%d proto=%d using %s\n",
- sock, ap->ai_family, ap->ai_protocol, s);
- res = connect(sock, ap->ai_addr, ap->ai_addrlen);
-#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
- if (res != 0) {
- int zero = 0;
- rfbLogPerror("connect_tcp[ipv6]: connect");
- dmsg = 1;
- if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) {
- rfbLog("connect_tcp[ipv6]: trying again with IPV6_V6ONLY=0\n");
- res = connect(sock, ap->ai_addr, ap->ai_addrlen);
- dmsg = 0;
- } else {
- rfbLogPerror("connect_tcp[ipv6]: setsockopt IPV6_V6ONLY");
- }
- }
-#endif
- if (res == 0) {
- rfbLog("connect_tcp[ipv6]: connect OK\n");
- fd = sock;
- if (!ipv6_client_ip_str) {
- ipv6_client_ip_str = strdup(s);
- }
- free(s);
- break;
- } else {
- if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect");
- close(sock);
- }
- free(s);
- }
- ap = ap->ai_next;
- }
- freeaddrinfo(ai);
- }
-#endif
- }
- if (fd < 0 && !fail4) {
- /* this is a kludge for IPv4-only machines getting v4mapped string. */
- char *q, *host2;
- if (host[0] == '[') {
- host2 = strdup(host+1);
- } else {
- host2 = strdup(host);
- }
- q = strrchr(host2, ']');
- if (q) {
- *q = '\0';
- }
- if (strstr(host2, "::ffff:") == host2 || strstr(host2, "::FFFF:") == host2) {
- char *host3 = host2 + strlen("::ffff:");
- if (dotted_ip(host3, 0)) {
- rfbLog("connect_tcp[ipv4]: trying fallback to IPv4 for %s\n", host2);
- fd = rfbConnectToTcpAddr(host3, port);
- if (fd < 0) {
- rfbLogPerror("connect_tcp[ipv4]: connection failed");
- }
- }
- }
- free(host2);
- }
- return fd;
-}
-
-int listen_tcp(int port, in_addr_t iface, int try6) {
- int fd = -1;
- int fail4 = noipv4;
- if (getenv("IPV4_FAILS")) {
- fail4 = 2;
- }
-
- if (port <= 0 || 65535 < port) {
- /* for us, invalid port means do not listen. */
- return -1;
- }
-
- if (fail4) {
- if (fail4 > 1) {
- rfbLog("TESTING: IPV4_FAILS for listen_tcp: port=%d try6=%d\n", port, try6);
- }
- } else {
- fd = rfbListenOnTCPPort(port, iface);
- }
-
- if (fd >= 0) {
- return fd;
- }
- if (fail4 > 1) {
- rfbLogPerror("listen_tcp: listen failed");
- }
-
- if (fd < 0 && try6 && ipv6_listen && !noipv6) {
-#if X11VNC_IPV6
- char *save = listen_str6;
- if (iface == htonl(INADDR_LOOPBACK)) {
- listen_str6 = "localhost";
- rfbLog("listen_tcp: retrying on IPv6 in6addr_loopback ...\n");
- fd = listen6(port);
- } else if (iface == htonl(INADDR_ANY)) {
- listen_str6 = NULL;
- rfbLog("listen_tcp: retrying on IPv6 in6addr_any ...\n");
- fd = listen6(port);
- }
- listen_str6 = save;
-#endif
- }
- return fd;
-}
-
OpenPOWER on IntegriCloud