diff options
author | runge <[email protected]> | 2010-04-18 19:37:37 -0400 |
---|---|---|
committer | runge <[email protected]> | 2010-04-18 19:37:37 -0400 |
commit | b74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1 (patch) | |
tree | c8c8aaec90fd51a10790795030777b2dda548fe7 /x11vnc/inet.c | |
parent | 2a8ba97ec5b0f7fbfcfc8adab6732a95e95c7204 (diff) | |
download | libtdevnc-b74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1.tar.gz libtdevnc-b74c8f4241ec8c3d972ee97d0ce9a399ddd09ce1.zip |
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.c | 187 |
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; |