Module: wine Branch: master Commit: f776aea60d5d79c1fbcf7994f945da833e5c342a URL: http://source.winehq.org/git/wine.git/?a=commit;h=f776aea60d5d79c1fbcf7994f9...
Author: Juan Lang juan.lang@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;