Juan Lang : iphlpapi: Set gateway addresses in GetAdaptersAddresses.

Alexandre Julliard julliard at winehq.org
Fri Sep 24 11:43:43 CDT 2010


Module: wine
Branch: master
Commit: f776aea60d5d79c1fbcf7994f945da833e5c342a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f776aea60d5d79c1fbcf7994f945da833e5c342a

Author: Juan Lang <juan.lang at gmail.com>
Date:   Thu Sep 16 10:14:18 2010 -0700

iphlpapi: Set gateway addresses in GetAdaptersAddresses.

---

 dlls/iphlpapi/iphlpapi_main.c |   94 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 88 insertions(+), 6 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 6ec06e8..88b699b 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -696,34 +696,82 @@ static char *debugstr_ipv6(const struct WS_sockaddr_in6 *sin, char *buf)
     return buf;
 }
 
+static ULONG count_v4_gateways(DWORD index, PMIB_IPFORWARDTABLE routeTable)
+{
+    DWORD i, num_gateways = 0;
+
+    for (i = 0; i < routeTable->dwNumEntries; i++)
+    {
+        if (routeTable->table[i].dwForwardIfIndex == index &&
+            routeTable->table[i].dwForwardType == MIB_IPROUTE_TYPE_INDIRECT)
+            num_gateways++;
+    }
+    return num_gateways;
+}
+
+static PMIB_IPFORWARDROW findIPv4Gateway(DWORD index,
+                                         PMIB_IPFORWARDTABLE routeTable)
+{
+    DWORD i;
+    PMIB_IPFORWARDROW row = NULL;
+
+    for (i = 0; !row && i < routeTable->dwNumEntries; i++)
+    {
+        if (routeTable->table[i].dwForwardIfIndex == index &&
+            routeTable->table[i].dwForwardType == MIB_IPROUTE_TYPE_INDIRECT)
+            row = &routeTable->table[i];
+    }
+    return row;
+}
+
 static ULONG adapterAddressesFromIndex(ULONG family, DWORD index, IP_ADAPTER_ADDRESSES *aa, ULONG *size)
 {
-    ULONG ret, i, num_v4addrs = 0, num_v6addrs = 0, total_size;
+    ULONG ret, i, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0, total_size;
     DWORD *v4addrs = NULL;
     SOCKET_ADDRESS *v6addrs = NULL;
+    PMIB_IPFORWARDTABLE routeTable = NULL;
 
     if (family == AF_INET)
-        ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+    {
+        ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE,
+                                                    GetProcessHeap(), 0);
+        if (!ret)
+        {
+            ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+            num_v4_gateways = count_v4_gateways(index, routeTable);
+        }
+    }
     else if (family == AF_INET6)
         ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
     else if (family == AF_UNSPEC)
     {
-        ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+        ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE,
+                                                    GetProcessHeap(), 0);
         if (!ret)
-            ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
+        {
+            ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs);
+            num_v4_gateways = count_v4_gateways(index, routeTable);
+            if (!ret)
+                ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs);
+        }
     }
     else
     {
         FIXME("address family %u unsupported\n", family);
         ret = ERROR_NO_DATA;
     }
-    if (ret) return ret;
+    if (ret)
+    {
+        HeapFree(GetProcessHeap(), 0, routeTable);
+        return ret;
+    }
 
     total_size = sizeof(IP_ADAPTER_ADDRESSES);
     total_size += IF_NAMESIZE;
     total_size += IF_NAMESIZE * sizeof(WCHAR);
     total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v4addrs;
     total_size += sizeof(struct sockaddr_in) * num_v4addrs;
+    total_size += (sizeof(IP_ADAPTER_GATEWAY_ADDRESS) + sizeof(SOCKADDR_IN)) * num_v4_gateways;
     total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v6addrs;
     total_size += sizeof(SOCKET_ADDRESS) * num_v6addrs;
     for (i = 0; i < num_v6addrs; i++)
@@ -751,11 +799,44 @@ static ULONG adapterAddressesFromIndex(ULONG family, DWORD index, IP_ADAPTER_ADD
 
         TRACE("%s: %d IPv4 addresses, %d IPv6 addresses:\n", name, num_v4addrs,
               num_v6addrs);
+        if (num_v4_gateways)
+        {
+            PMIB_IPFORWARDROW adapterRow;
+
+            if ((adapterRow = findIPv4Gateway(index, routeTable)))
+            {
+                PIP_ADAPTER_GATEWAY_ADDRESS gw;
+                PSOCKADDR_IN sin;
+
+                for (gw = aa->FirstGatewayAddress; gw && gw->Next;
+                     gw = gw->Next)
+                    ;
+                if (!gw)
+                {
+                    gw = (PIP_ADAPTER_GATEWAY_ADDRESS)ptr;
+                    aa->FirstGatewayAddress = gw;
+                }
+                else
+                {
+                    gw->Next = (PIP_ADAPTER_GATEWAY_ADDRESS)ptr;
+                    gw = gw->Next;
+                }
+                gw->u.s.Length = sizeof(IP_ADAPTER_GATEWAY_ADDRESS);
+                ptr += sizeof(IP_ADAPTER_GATEWAY_ADDRESS);
+                sin = (PSOCKADDR_IN)ptr;
+                sin->sin_family = AF_INET;
+                sin->sin_port = 0;
+                memcpy(&sin->sin_addr, &adapterRow->dwForwardNextHop,
+                       sizeof(DWORD));
+                gw->Address.lpSockaddr = (LPSOCKADDR)sin;
+                gw->Address.iSockaddrLength = sizeof(SOCKADDR_IN);
+                ptr += sizeof(SOCKADDR_IN);
+            }
+        }
         if (num_v4addrs)
         {
             IP_ADAPTER_UNICAST_ADDRESS *ua;
             struct sockaddr_in *sa;
-
             aa->Flags |= IP_ADAPTER_IPV4_ENABLED;
             ua = aa->FirstUnicastAddress = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
             for (i = 0; i < num_v4addrs; i++)
@@ -834,6 +915,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, DWORD index, IP_ADAPTER_ADD
         else aa->OperStatus = IfOperStatusUnknown;
     }
     *size = total_size;
+    HeapFree(GetProcessHeap(), 0, routeTable);
     HeapFree(GetProcessHeap(), 0, v6addrs);
     HeapFree(GetProcessHeap(), 0, v4addrs);
     return ERROR_SUCCESS;




More information about the wine-cvs mailing list