summaryrefslogtreecommitdiffstats
path: root/x11vnc/inet.c
diff options
context:
space:
mode:
authorrunge <runge@karlrunge.com>2010-04-18 19:37:37 -0400
committerrunge <runge@karlrunge.com>2010-04-18 19:37:37 -0400
commitb74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1 (patch)
treec8c8aaec90fd51a10790795030777b2dda548fe7 /x11vnc/inet.c
parent2a8ba97ec5b0f7fbfcfc8adab6732a95e95c7204 (diff)
downloadlibvncserver-b74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1.zip
libvncserver-b74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1.tar.gz
Improvements to demo scripts. Alias -coe for -connect_or_exit. Fix HAVE_V4L2. Warn no Xvfb, Xdummy, or Xvnc. Xinerama screens.
Diffstat (limited to 'x11vnc/inet.c')
-rw-r--r--x11vnc/inet.c187
1 files changed, 157 insertions, 30 deletions
diff --git a/x11vnc/inet.c b/x11vnc/inet.c
index 60e26f5..a70ce24 100644
--- a/x11vnc/inet.c
+++ b/x11vnc/inet.c
@@ -45,7 +45,7 @@ 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 dotted_ip(char *host, int partial);
int get_remote_port(int sock);
int get_local_port(int sock);
char *get_remote_host(int sock);
@@ -143,8 +143,8 @@ int ipv6_ip(char *host_in) {
host = host_in;
}
- if (strstr(host, "::ffff:") == host) {
- return dotted_ip(host + strlen("::ffff:"));
+ if (strstr(host, "::ffff:") == host || strstr(host, "::FFFF:") == host) {
+ return dotted_ip(host + strlen("::ffff:"), 0);
}
a[1] = '\0';
@@ -170,15 +170,34 @@ int ipv6_ip(char *host_in) {
}
}
-int dotted_ip(char *host) {
+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;
}
@@ -253,7 +272,6 @@ char *ident_username(rfbClientPtr client) {
user = cd->username;
}
if (!user || *user == '\0') {
- char msg[128];
int n, sock, ok = 0;
int block = 0;
int refused = 0;
@@ -310,6 +328,7 @@ char *ident_username(rfbClientPtr client) {
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;
@@ -321,14 +340,14 @@ char *ident_username(rfbClientPtr client) {
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
- tv.tv_sec = 4;
+ 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<128; i++) {
+ for (i=0; i < sizeof(msg); i++) {
msg[i] = '\0';
}
usleep(250*1000);
@@ -504,7 +523,7 @@ char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) {
}
char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) {
-#if X11VNC_IPV6
+#if X11VNC_IPV6 && defined(NI_NUMERICHOST)
char name[200];
if (noipv6) {
return strdup("unknown");
@@ -524,22 +543,27 @@ int listen6(int port) {
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: setsockopt1");
+ 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: setsockopt2");
+ rfbLogPerror("listen6: setsockopt IPV6_V6ONLY");
close(fd);
return -1;
}
@@ -551,19 +575,57 @@ int listen6(int port) {
sin.sin6_addr = in6addr_any;
if (listen_str6) {
- if (!strcmp(listen_str6, "localhost")) {
+ if (!strcmp(listen_str6, "localhost") || !strcmp(listen_str6, "::1")) {
sin.sin6_addr = in6addr_loopback;
- } else if (ipv6_ip(listen_str6)) {
- int err = inet_pton(AF_INET6, listen_str6, &(sin.sin6_addr));
- if (err <= 0) {
- rfbLog("inet_pton[%d] failed -listen6 %s\n", err, listen_str6);
+ } 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 {
- rfbLog("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;
@@ -625,7 +687,7 @@ int connect_tcp(char *host, int port) {
}
if (fd < 0 && !noipv6) {
-#if X11VNC_IPV6 && defined(AI_ADDRCONFIG)
+#if X11VNC_IPV6
int err;
struct addrinfo *ai;
struct addrinfo hints;
@@ -638,13 +700,13 @@ int connect_tcp(char *host, int port) {
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_ADDRCONFIG;
+#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;
-#else
- rfbLog("connect_tcp[ipv6]: no AI_NUMERICHOST for %s\n", host);
#endif
}
#ifdef AI_NUMERICSERV
@@ -662,7 +724,6 @@ int connect_tcp(char *host, int port) {
if (q) {
*q = '\0';
}
-
err = getaddrinfo(host2, service, &hints, &ai);
if (err != 0) {
@@ -677,14 +738,53 @@ int connect_tcp(char *host, int port) {
} else {
struct addrinfo *ap = ai;
while (ap != NULL) {
- int sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
+ 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 using %s\n", sock, s);
- if (connect(sock, ap->ai_addr, ap->ai_addrlen) == 0) {
+
+ 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) {
@@ -693,8 +793,8 @@ int connect_tcp(char *host, int port) {
free(s);
break;
} else {
+ if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect");
close(sock);
- rfbLogPerror("connect_tcp[ipv6]: connect");
}
free(s);
}
@@ -704,6 +804,30 @@ int connect_tcp(char *host, int port) {
}
#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;
}
@@ -714,6 +838,11 @@ int listen_tcp(int port, in_addr_t iface, int try6) {
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);
@@ -742,8 +871,6 @@ int listen_tcp(int port, in_addr_t iface, int try6) {
fd = listen6(port);
}
listen_str6 = save;
-#else
- if (try6) {}
#endif
}
return fd;
OpenPOWER on IntegriCloud