[PATCH] ws2_32: Also check the FQDN when injecting the local IP (v2).

Stefan Dösinger stefan at codeweavers.com
Tue Aug 29 09:15:21 CDT 2017


Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>

---

Version 2: Don't retrieve the hostname separately, just cut the fqdn at
the first dot. Add some details about what is going on on OSX and Linux.

World of Tanks is affected by this. It refuses to connect to the game
servers when it cannot resolve the full local hostname. The
misconfiguration of having a nonresolvable hostname happens on OSX when
DHCP does not assign a hostname. OSX will set a hostname like
"stefans-macbook.local". The short hostname is stefans-macbook and is
not resolved to an IP. The FQDN stefans-macbook.local is resolved via
the mDNS service. However, the mDNS service only runs if any network
service like ssh or file sharing is enabled.

Note that the same game behavior can be triggered on Linux by setting a
hostname that contains a dot (which violates RFC 1178). In this case
GetComputerNameExA will cut off the hostname at the dot, causing ws2_32
not to match it with the input name. Incidentially the fix makes the
game work in this situation too.
---
 dlls/ws2_32/socket.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 06f1c26d7d..681f340bc6 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -6539,15 +6539,15 @@ static int convert_eai_u2w(int unixret) {
     return unixret;
 }
 
-static char *get_hostname(void)
+static char *get_fqdn(void)
 {
     char *ret;
     DWORD size = 0;
 
-    GetComputerNameExA( ComputerNamePhysicalDnsHostname, NULL, &size );
+    GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
     if (GetLastError() != ERROR_MORE_DATA) return NULL;
     if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
-    if (!GetComputerNameExA( ComputerNamePhysicalDnsHostname, ret, &size ))
+    if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
     {
         HeapFree( GetProcessHeap(), 0, ret );
         return NULL;
@@ -6564,8 +6564,9 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
     struct addrinfo *unixaires = NULL;
     int   result;
     struct addrinfo unixhints, *punixhints = NULL;
-    char *hostname, *nodeV6 = NULL;
+    char *dot, *nodeV6 = NULL, *fqdn;
     const char *node;
+    size_t hostname_len = 0;
 
     *res = NULL;
     if (!nodename && !servname)
@@ -6574,13 +6575,16 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
         return WSAHOST_NOT_FOUND;
     }
 
-    hostname = get_hostname();
-    if (!hostname) return WSA_NOT_ENOUGH_MEMORY;
+    fqdn = get_fqdn();
+    if (!fqdn) return WSA_NOT_ENOUGH_MEMORY;
+    dot = strchr(fqdn, '.');
+    if (dot)
+        hostname_len = dot - fqdn;
 
     if (!nodename)
         node = NULL;
     else if (!nodename[0])
-        node = hostname;
+        node = fqdn;
     else
     {
         node = nodename;
@@ -6595,7 +6599,7 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
                 nodeV6 = HeapAlloc(GetProcessHeap(), 0, close_bracket - node);
                 if (!nodeV6)
                 {
-                    HeapFree(GetProcessHeap(), 0, hostname);
+                    HeapFree(GetProcessHeap(), 0, fqdn);
                     return WSA_NOT_ENOUGH_MEMORY;
                 }
                 lstrcpynA(nodeV6, node + 1, close_bracket - node);
@@ -6624,7 +6628,7 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
         if (punixhints->ai_socktype < 0)
         {
             SetLastError(WSAESOCKTNOSUPPORT);
-            HeapFree(GetProcessHeap(), 0, hostname);
+            HeapFree(GetProcessHeap(), 0, fqdn);
             HeapFree(GetProcessHeap(), 0, nodeV6);
             return SOCKET_ERROR;
         }
@@ -6648,7 +6652,8 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
     /* getaddrinfo(3) is thread safe, no need to wrap in CS */
     result = getaddrinfo(node, servname, punixhints, &unixaires);
 
-    if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && !strcmp(hostname, node))
+    if (result && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST))
+            && (!strcmp(fqdn, node) || (!strncmp(fqdn, node, hostname_len) && !node[hostname_len])))
     {
         /* If it didn't work it means the host name IP is not in /etc/hosts, try again
         * by sending a NULL host and avoid sending a NULL servname too because that
@@ -6657,7 +6662,7 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
         result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
     }
     TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
-    HeapFree(GetProcessHeap(), 0, hostname);
+    HeapFree(GetProcessHeap(), 0, fqdn);
     HeapFree(GetProcessHeap(), 0, nodeV6);
 
     if (!result) {
-- 
2.13.5




More information about the wine-patches mailing list