ws2_32: Use qsort() to order routes by metric in WS_get_local_ips

Joachim Priesner joachim.priesner at web.de
Tue Dec 2 03:24:11 CST 2014


Supersedes 107283 (changed patch title to be more concise).

This is a bugfix. The previous implementation required the metrics to be mutually
inequal (because of the "this_metric > last_metric" check). If the metrics were
not mutually inequal, it would write only one address per metric value to the list
and fill up the rest of the list with the magic loopback IP address 127.12.34.56.

Try 3 that removes the null check in the comparison function as
suggested by Stefan Doesinger.
---
 dlls/ws2_32/socket.c | 38 +++++++++++++++++---------------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 29ac800..142e964 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -5167,6 +5167,17 @@ struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
 }
 
 /***********************************************************************
+ *		WS_compare_routes_by_metric_asc (INTERNAL)
+ *
+ * Comparison function for qsort(), for sorting two routes (struct route)
+ * by metric in ascending order.
+ */
+static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
+{
+    return ((const struct route*)left)->metric - ((const struct route*)right)->metric;
+}
+
+/***********************************************************************
  *		WS_get_local_ips		(INTERNAL)
  *
  * Returns the list of local IP addresses by going through the network
@@ -5180,7 +5191,7 @@ struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
  */
 static struct WS_hostent* WS_get_local_ips( char *hostname )
 {
-    int last_metric, numroutes = 0, i, j;
+    int numroutes = 0, i, j;
     DWORD n;
     PIP_ADAPTER_INFO adapters = NULL, k;
     struct WS_hostent *hostlist = NULL;
@@ -5260,30 +5271,15 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
     hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
     hostlist->h_addrtype = AF_INET;
     hostlist->h_length = sizeof(struct in_addr); /* = 4 */
-    /* Reorder the entries when placing them in the host list, Windows expects
+    /* Reorder the entries before placing them in the host list. Windows expects
      * the IP list in order from highest priority to lowest (the critical thing
      * is that most applications expect the first IP to be the default route).
      */
-    last_metric = -1;
-    for (i = 0; i < numroutes; i++)
-    {
-       struct in_addr addr;
-       int metric = 0xFFFF;
+    if (numroutes > 1)
+        qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
 
-       memcpy(&addr, magic_loopback_addr, 4);
-       for (j = 0; j < numroutes; j++)
-       {
-           int this_metric = route_addrs[j].metric;
-
-           if (this_metric > last_metric && this_metric < metric)
-           {
-               addr = route_addrs[j].addr;
-               metric = this_metric;
-           }
-       }
-       last_metric = metric;
-       (*(struct in_addr *) hostlist->h_addr_list[i]) = addr;
-    }
+    for (i = 0; i < numroutes; i++)
+        (*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
 
     /* Cleanup all allocated memory except the address list,
      * the address list is used by the calling app.
-- 
1.8.4.5




More information about the wine-patches mailing list