ws2_32: Update WS_get_local_ips to not return a bogus IP address.

Bruno Jesus 00cpxxx at gmail.com
Tue Nov 24 06:30:13 CST 2015


On Sat, Nov 21, 2015 at 2:12 PM, Jamie Taylor <Jamie.Taylor at pobox.com> wrote:
> There were many shortcomings in the previous behavior, but most
> importantly it resulted in the first IP address in the
> returned hostent structure being the magic loopback address in
> the default network configuration on Mac OS X.  The new behavior
> returns all IP addresses from non-loopback network adapters, and
> ensures that the addresses from the adapter for the default route
> are at the front of the list.  Testing confirmed this behavior
> on Mac OS X.
>
> This will most likely fix https://bugs.winehq.org/show_bug.cgi?id=37271
> and https://bugs.winehq.org/show_bug.cgi?id=22819
> but I do not have the programs under test in those bugs, so I can't
> verify.
>
> I also do not have convenient access to a linux machine with an
> equivalent network configuration (i.e., at least two interfaces
> with default routes) to test.

Hi, Jamie. Thanks for your effort, as you may have observed in the
patches list your patch is marked as deferred because we are in code
freeze for Wine 1.8 release. This code was touched a few times in
attempts to fix this same issue you are addressing so maybe this time
it will be the definitive fix =)

I have a similar (not so robust) old patch that I used on FreeBSD (and
also works in Linux), could you try it in OSX just out of curiosity,
please? It has printf to help showing the results so a make test in
the ws2_32/tests folder is enough to check if it works.

About your patch I just would like to say that you should follow the
surrounding code style, so the { goes in the next line. I tested it on
Linux and it works for Heroes of Might & Magic 2
(https://bugs.winehq.org/show_bug.cgi?id=22819).

Best wishes,
Bruno
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d31f0b4..d8f6b62 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -5955,6 +5955,7 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
     PMIB_IPFORWARDTABLE routes = NULL;
     struct route *route_addrs = NULL;
     DWORD adap_size, route_size;
+    int default_routes = 0;
 
     /* Obtain the size of the adapter list and routing table, also allocate memory */
     if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
@@ -5978,10 +5979,18 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
         DWORD ifmetric;
         BOOL exists = FALSE;
 
-        if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
-            continue;
         ifindex = routes->table[n].dwForwardIfIndex;
-        ifmetric = routes->table[n].dwForwardMetric1;
+        /* Check if this is the default route (there may be more than one) */
+        if (!routes->table[n].dwForwardDest)
+            ifmetric = ++default_routes;
+        else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
+            continue;
+        else
+        {
+            ifmetric = routes->table[n].dwForwardMetric1;
+            if (!ifmetric) ifmetric = 1000; /* Ignore 0 to not mess with the default routes */
+        }
+
         /* Only store the lowest valued metric for an interface */
         for (j = 0; j < numroutes; j++)
         {
@@ -6005,7 +6014,7 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
         memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
         numroutes++;
     }
-   if (numroutes == 0)
+    if (numroutes == 0)
        goto cleanup; /* No routes, fall back to the Magic IP */
     /* Find the IP address associated with each found interface */
     for (i = 0; i < numroutes; i++)
@@ -6036,7 +6045,10 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
         qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
 
     for (i = 0; i < numroutes; i++)
+    {
         (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
+        printf("IP[%d] %s, metric %d\n", i, inet_ntoa(route_addrs[i].addr), route_addrs[i].metric);
+    }
 
     /* Cleanup all allocated memory except the address list,
      * the address list is used by the calling app.


More information about the wine-devel mailing list