From 1155531cb3092918e4d52c6a5e92e42836ce916c Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Mon, 8 Sep 2003 19:00:25 +0000 Subject: [PATCH] - Fix buffer overrun in GetNetworkParams. - Implement GetBest(Route,Interface). - Implement some AllocateAndGet*FromStack functions. --- dlls/iphlpapi/Makefile.in | 2 +- dlls/iphlpapi/iphlpapi.spec | 12 +- dlls/iphlpapi/iphlpapi_main.c | 419 ++++++++++++++++++++++++++++++++-- 3 files changed, 405 insertions(+), 28 deletions(-) diff --git a/dlls/iphlpapi/Makefile.in b/dlls/iphlpapi/Makefile.in index 76d5bb460d8..28ebe57c07f 100644 --- a/dlls/iphlpapi/Makefile.in +++ b/dlls/iphlpapi/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = iphlpapi.dll -IMPORTS = kernel32 +IMPORTS = advapi32 kernel32 LDDLLFLAGS = @LDDLLFLAGS@ SYMBOLFILE = $(MODULE).tmp.o diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec index 599b2c1fad2..a9797ac6689 100644 --- a/dlls/iphlpapi/iphlpapi.spec +++ b/dlls/iphlpapi/iphlpapi.spec @@ -1,11 +1,11 @@ @ stdcall AddIPAddress( long long long ptr ptr ) @ stub AllocateAndGetArpEntTableFromStack -@ stub AllocateAndGetIfTableFromStack -@ stub AllocateAndGetIpAddrTableFromStack -@ stub AllocateAndGetIpForwardTableFromStack -@ stub AllocateAndGetIpNetTableFromStack -@ stub AllocateAndGetTcpTableFromStack -@ stub AllocateAndGetUdpTableFromStack +@ stdcall AllocateAndGetIfTableFromStack( ptr long long long ) +@ stdcall AllocateAndGetIpAddrTableFromStack( ptr long long long ) +@ stdcall AllocateAndGetIpForwardTableFromStack( ptr long long long ) +@ stdcall AllocateAndGetIpNetTableFromStack( ptr long long long ) +@ stdcall AllocateAndGetTcpTableFromStack( ptr long long long ) +@ stdcall AllocateAndGetUdpTableFromStack( ptr long long long ) @ stdcall CreateIpForwardEntry( ptr ) @ stdcall CreateIpNetEntry( ptr ) @ stdcall CreateProxyArpEntry( long long long ) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 411ceacfd0a..b19793a3195 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -35,6 +35,7 @@ #include "windef.h" #include "winbase.h" +#include "winreg.h" #include "iphlpapi.h" #include "ifenum.h" #include "ipstats.h" @@ -68,6 +69,220 @@ DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG N } +/****************************************************************** + * AllocateAndGetIfTableFromStack (IPHLPAPI.@) + * + * + * PARAMS + * + * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is + * allocated and returned. + * bOrder [In] -- passed to GetIfTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever + * GetIfTable returns otherwise + * + */ +DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable, + BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppIfTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetIfTable(*ppIfTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetIfTable(*ppIfTable, &dwSize, bOrder); + } + } + return ret; +} + + +/****************************************************************** + * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@) + * + * + * PARAMS + * + * ppIpAddrTable [Out] + * bOrder [In] -- passed to GetIpAddrTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable, + BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppIpAddrTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder); + } + } + return ret; +} + + +/****************************************************************** + * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@) + * + * + * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is + * allocated and returned. + * bOrder [In] -- passed to GetIfTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever + * GetIpForwardTable returns otherwise + * + */ +DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE * + ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppIpForwardTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder); + } + } + return ret; +} + + +/****************************************************************** + * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@) + * + * + * PARAMS + * + * ppIpNetTable [Out] + * bOrder [In] -- passed to GetIpNetTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable, + BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppIpNetTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder); + } + } + return ret; +} + + +/****************************************************************** + * AllocateAndGetTcpTableFromStack (IPHLPAPI.@) + * + * + * PARAMS + * + * ppTcpTable [Out] + * bOrder [In] -- passed to GetTcpTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable, + BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppTcpTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder); + } + } + return ret; +} + + +/****************************************************************** + * AllocateAndGetUdpTableFromStack (IPHLPAPI.@) + * + * + * PARAMS + * + * ppUdpTable [Out] + * bOrder [In] -- passed to GetUdpTable to order the table + * heap [In] -- heap from which the table is allocated + * flags [In] -- flags to HeapAlloc + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, + BOOL bOrder, HANDLE heap, DWORD flags) +{ + DWORD ret; + + if (!ppUdpTable) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD dwSize = 0; + + ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize); + ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder); + } + } + return ret; +} + + /****************************************************************** * CreateIpForwardEntry (IPHLPAPI.@) * @@ -390,8 +605,18 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) */ DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) { - FIXME(":stub\n"); - return (DWORD) 0; + DWORD ret; + + if (!pdwBestIfIndex) + ret = ERROR_INVALID_PARAMETER; + else { + MIB_IPFORWARDROW ipRow; + + ret = GetBestRoute(dwDestAddr, 0, &ipRow); + if (ret == ERROR_SUCCESS) + *pdwBestIfIndex = ipRow.dwForwardIfIndex; + } + return ret; } @@ -412,8 +637,37 @@ DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) */ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute) { - FIXME(":stub\n"); - return (DWORD) 0; + PMIB_IPFORWARDTABLE table; + DWORD ret; + + if (!pBestRoute) + return ERROR_INVALID_PARAMETER; + + AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0); + if (table) { + DWORD ndx, matchedBits, matchedNdx = 0; + + for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) { + if ((dwDestAddr & table->table[ndx].dwForwardMask) == + (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) { + DWORD numShifts, mask; + + for (numShifts = 0, mask = table->table[ndx].dwForwardMask; + mask && !(mask & 1); mask >>= 1, numShifts++) + ; + if (numShifts > matchedBits) { + matchedBits = numShifts; + matchedNdx = ndx; + } + } + } + memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW)); + HeapFree(GetProcessHeap(), 0, table); + ret = ERROR_SUCCESS; + } + else + ret = ERROR_OUTOFMEMORY; + return ret; } @@ -433,7 +687,7 @@ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDRO DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex) { /* windows doesn't validate these, either, just makes sure the top byte is - cleared. I assume my ipshared module never gives an index with the top + cleared. I assume my ifenum module never gives an index with the top byte set. */ return IfIndex; } @@ -491,6 +745,18 @@ DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow) } +static int IfTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) + ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex; + else + ret = 0; + return ret; +} + + /****************************************************************** * GetIfTable (IPHLPAPI.@) * @@ -533,14 +799,15 @@ DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) else { DWORD ndx; - if (bOrder) - FIXME(":order not implemented"); pIfTable->dwNumEntries = 0; for (ndx = 0; ndx < table->numIndexes; ndx++) { pIfTable->table[ndx].dwIndex = table->indexes[ndx]; GetIfEntry(&pIfTable->table[ndx]); pIfTable->dwNumEntries++; } + if (bOrder) + qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW), + IfTableSorter); ret = NO_ERROR; } free(table); @@ -622,6 +889,18 @@ DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen) } +static int IpAddrTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) + ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr; + else + ret = 0; + return ret; +} + + /****************************************************************** * GetIpAddrTable (IPHLPAPI.@) * @@ -665,8 +944,6 @@ DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL else { DWORD ndx; - if (bOrder) - FIXME(":order not implemented"); pIpAddrTable->dwNumEntries = 0; for (ndx = 0; ndx < table->numIndexes; ndx++) { pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx]; @@ -682,6 +959,9 @@ DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */ pIpAddrTable->dwNumEntries++; } + if (bOrder) + qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries, + sizeof(MIB_IPADDRROW), IpAddrTableSorter); ret = NO_ERROR; } free(table); @@ -694,6 +974,29 @@ DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL } +static int IpForwardTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) { + PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b; + + ret = rowA->dwForwardDest - rowB->dwForwardDest; + if (ret == 0) { + ret = rowA->dwForwardProto - rowB->dwForwardProto; + if (ret == 0) { + ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy; + if (ret == 0) + ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop; + } + } + } + else + ret = 0; + return ret; +} + + /****************************************************************** * GetIpForwardTable (IPHLPAPI.@) * @@ -736,8 +1039,6 @@ DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSi else { DWORD ndx; - if (bOrder) - FIXME(":order not implemented"); pIpForwardTable->dwNumEntries = table->numRoutes; for (ndx = 0; ndx < numRoutes; ndx++) { pIpForwardTable->table[ndx].dwForwardIfIndex = @@ -766,6 +1067,9 @@ DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSi pIpForwardTable->table[ndx].dwForwardMetric4 = 0; pIpForwardTable->table[ndx].dwForwardMetric5 = 0; } + if (bOrder) + qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries, + sizeof(MIB_IPFORWARDROW), IpForwardTableSorter); ret = NO_ERROR; } free(table); @@ -778,6 +1082,18 @@ DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSi } +static int IpNetTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) + ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr; + else + ret = 0; + return ret; +} + + /****************************************************************** * GetIpNetTable (IPHLPAPI.@) * @@ -819,9 +1135,10 @@ DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOr ret = ERROR_INSUFFICIENT_BUFFER; } else { - if (bOrder) - FIXME(":order not implemented"); memcpy(pIpNetTable, table, size); + if (bOrder) + qsort(pIpNetTable->table, pIpNetTable->dwNumEntries, + sizeof(MIB_IPNETROW), IpNetTableSorter); ret = NO_ERROR; } free(table); @@ -870,12 +1187,14 @@ DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats) DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) { DWORD size; + HKEY hKey; if (!pOutBufLen) return ERROR_INVALID_PARAMETER; - size = sizeof(FIXED_INFO) + min(1, (_res.nscount - 1) * - sizeof(IP_ADDR_STRING)); + res_init(); + size = sizeof(FIXED_INFO) + (_res.nscount > 0 ? (_res.nscount - 1) * + sizeof(IP_ADDR_STRING) : 0); if (!pFixedInfo || *pOutBufLen < size) { *pOutBufLen = size; return ERROR_BUFFER_OVERFLOW; @@ -890,13 +1209,29 @@ DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) PIP_ADDR_STRING ptr; int i; - for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount; + for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount && ptr; i++, ptr = ptr->Next) { toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr, ptr->IpAddress.String); - ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDRESS_STRING)); + if (i == _res.nscount - 1) + ptr->Next = NULL; + else if (i == 0) + ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO)); + else + ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING)); } } + pFixedInfo->NodeType = HYBRID_NODETYPE; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "\\SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey) + == ERROR_SUCCESS) + { + DWORD size = sizeof(pFixedInfo->ScopeId); + + RegQueryValueExA(hKey, "ScopeID", NULL, NULL, pFixedInfo->ScopeId, &size); + RegCloseKey(hKey); + } + /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward I suppose could also check for a listener on port 53 to set EnableDns */ return NO_ERROR; @@ -995,6 +1330,29 @@ DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats) } +static int TcpTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) { + PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b; + + ret = rowA->dwLocalAddr - rowB->dwLocalAddr; + if (ret == 0) { + ret = rowA->dwLocalPort - rowB->dwLocalPort; + if (ret == 0) { + ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr; + if (ret == 0) + ret = rowA->dwRemotePort - rowB->dwRemotePort; + } + } + } + else + ret = 0; + return ret; +} + + /****************************************************************** * GetTcpTable (IPHLPAPI.@) * @@ -1035,9 +1393,10 @@ DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) ret = ERROR_INSUFFICIENT_BUFFER; } else { - if (bOrder) - FIXME(":order not implemented"); memcpy(pTcpTable, table, size); + if (bOrder) + qsort(pTcpTable->table, pTcpTable->dwNumEntries, + sizeof(MIB_TCPROW), TcpTableSorter); ret = NO_ERROR; } free(table); @@ -1069,6 +1428,23 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats) } +static int UdpTableSorter(const void *a, const void *b) +{ + int ret; + + if (a && b) { + PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b; + + ret = rowA->dwLocalAddr - rowB->dwLocalAddr; + if (ret == 0) + ret = rowA->dwLocalPort - rowB->dwLocalPort; + } + else + ret = 0; + return ret; +} + + /****************************************************************** * GetUdpTable (IPHLPAPI.@) * @@ -1109,9 +1485,10 @@ DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) ret = ERROR_INSUFFICIENT_BUFFER; } else { - if (bOrder) - FIXME(":order not implemented"); memcpy(pUdpTable, table, size); + if (bOrder) + qsort(pUdpTable->table, pUdpTable->dwNumEntries, + sizeof(MIB_UDPROW), UdpTableSorter); ret = NO_ERROR; } free(table);