diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index a3fc93ee69d..ffc064a5ade 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -1318,31 +1318,17 @@ DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSi */ DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder) { - DWORD ret; + DWORD ret; + PMIB_IPNETTABLE table; - TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize, - (DWORD)bOrder); - if (!pdwSize) - ret = ERROR_INVALID_PARAMETER; - else { - DWORD numEntries = getNumArpEntries(); - ULONG size = sizeof(MIB_IPNETTABLE); + TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize, bOrder); - if (numEntries > 1) - size += (numEntries - 1) * sizeof(MIB_IPNETROW); - if (!pIpNetTable || *pdwSize < size) { - *pdwSize = size; - ret = ERROR_INSUFFICIENT_BUFFER; - } - else { - PMIB_IPNETTABLE table; + if (!pdwSize) return ERROR_INVALID_PARAMETER; - ret = getArpTable(&table, GetProcessHeap(), 0); - if (!ret) { - size = sizeof(MIB_IPNETTABLE); - if (table->dwNumEntries > 1) - size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW); - if (*pdwSize < size) { + ret = getArpTable(&table, GetProcessHeap(), 0); + if (!ret) { + DWORD size = FIELD_OFFSET( MIB_IPNETTABLE, table[table->dwNumEntries] ); + if (!pIpNetTable || *pdwSize < size) { *pdwSize = size; ret = ERROR_INSUFFICIENT_BUFFER; } @@ -1352,14 +1338,11 @@ DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOr if (bOrder) qsort(pIpNetTable->table, pIpNetTable->dwNumEntries, sizeof(MIB_IPNETROW), IpNetTableSorter); - ret = NO_ERROR; } HeapFree(GetProcessHeap(), 0, table); - } } - } - TRACE("returning %d\n", ret); - return ret; + TRACE("returning %d\n", ret); + return ret; } diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index 49e18080b1d..852b3037580 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -1312,47 +1312,116 @@ DWORD getNumArpEntries(void) return getNumWithOneHeader("/proc/net/arp"); } +static MIB_IPNETTABLE *append_ipnet_row( HANDLE heap, DWORD flags, MIB_IPNETTABLE *table, + DWORD *count, const MIB_IPNETROW *row ) +{ + if (table->dwNumEntries >= *count) + { + MIB_IPNETTABLE *new_table; + DWORD new_count = table->dwNumEntries * 2; + + if (!(new_table = HeapReAlloc( heap, flags, table, + FIELD_OFFSET(MIB_IPNETTABLE, table[new_count] )))) + { + HeapFree( heap, 0, table ); + return NULL; + } + *count = new_count; + table = new_table; + } + memcpy( &table->table[table->dwNumEntries++], row, sizeof(*row) ); + return table; +} + DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) { - DWORD ret = NO_ERROR; - if (!ppIpNetTable) - ret = ERROR_INVALID_PARAMETER; - else { - DWORD numEntries = getNumArpEntries(); - DWORD size = sizeof(MIB_IPNETTABLE); - PMIB_IPNETTABLE table; + MIB_IPNETTABLE *table; + MIB_IPNETROW row; + DWORD ret = NO_ERROR, count = 16; - if (numEntries > 1) - size += (numEntries - 1) * sizeof(MIB_IPNETROW); - table = HeapAlloc(heap, flags, size); -#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) - if (table) + if (!ppIpNetTable) return ERROR_INVALID_PARAMETER; + + if (!(table = HeapAlloc( heap, flags, FIELD_OFFSET(MIB_IPNETTABLE, table[count] )))) + return ERROR_OUTOFMEMORY; + + table->dwNumEntries = 0; + +#ifdef __linux__ + { + FILE *fp; + + if ((fp = fopen("/proc/net/arp", "r"))) + { + char buf[512], *ptr; + DWORD flags; + + /* skip header line */ + ptr = fgets(buf, sizeof(buf), fp); + while ((ptr = fgets(buf, sizeof(buf), fp))) + { + memset( &row, 0, sizeof(row) ); + + row.dwAddr = inet_addr(ptr); + while (*ptr && !isspace(*ptr)) ptr++; + strtoul(ptr + 1, &ptr, 16); /* hw type (skip) */ + flags = strtoul(ptr + 1, &ptr, 16); + +#ifdef ATF_COM + if (flags & ATF_COM) row.dwType = MIB_IPNET_TYPE_DYNAMIC; + else +#endif +#ifdef ATF_PERM + if (flags & ATF_PERM) row.dwType = MIB_IPNET_TYPE_STATIC; + else +#endif + row.dwType = MIB_IPNET_TYPE_OTHER; + + while (*ptr && isspace(*ptr)) ptr++; + while (*ptr && !isspace(*ptr)) + { + row.bPhysAddr[row.dwPhysAddrLen++] = strtoul(ptr, &ptr, 16); + if (*ptr) ptr++; + } + while (*ptr && isspace(*ptr)) ptr++; + while (*ptr && !isspace(*ptr)) ptr++; /* mask (skip) */ + while (*ptr && isspace(*ptr)) ptr++; + getInterfaceIndexByName(ptr, &row.dwIndex); + + if (!(table = append_ipnet_row( heap, flags, table, &count, &row ))) + break; + } + fclose(fp); + } + else ret = ERROR_NOT_SUPPORTED; + } +#elif defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) { int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; #define MIB_LEN (sizeof(mib) / sizeof(mib[0])) size_t needed; - char *buf, *lim, *next; + char *buf = NULL, *lim, *next; struct rt_msghdr *rtm; struct sockaddr_inarp *sinarp; struct sockaddr_dl *sdl; - *ppIpNetTable = table; - table->dwNumEntries = 0; - if (sysctl (mib, MIB_LEN, NULL, &needed, NULL, 0) == -1) { - ERR ("failed to get size of arp table\n"); - return ERROR_NOT_SUPPORTED; + ERR ("failed to get arp table\n"); + ret = ERROR_NOT_SUPPORTED; + goto done; } buf = HeapAlloc (GetProcessHeap (), 0, needed); - if (!buf) return ERROR_OUTOFMEMORY; + if (!buf) + { + ret = ERROR_OUTOFMEMORY; + goto done; + } if (sysctl (mib, MIB_LEN, buf, &needed, NULL, 0) == -1) { - ERR ("failed to get arp table\n"); - HeapFree (GetProcessHeap (), 0, buf); - return ERROR_NOT_SUPPORTED; + ret = ERROR_NOT_SUPPORTED; + goto done; } lim = buf + needed; @@ -1364,110 +1433,33 @@ DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); if(sdl->sdl_alen) /* arp entry */ { - DWORD byte = strtoul(&sdl->sdl_data[sdl->sdl_alen], NULL, 16); - memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW)); - table->table[table->dwNumEntries].dwAddr = sinarp->sin_addr.s_addr; - table->table[table->dwNumEntries].dwIndex = sdl->sdl_index; - table->table[table->dwNumEntries].dwPhysAddrLen = sdl->sdl_alen; + memset( &row, 0, sizeof(row) ); + row.dwAddr = sinarp->sin_addr.s_addr; + row.dwIndex = sdl->sdl_index; + row.dwPhysAddrLen = min( 8, sdl->sdl_alen ); + memcpy( row.bPhysAddr, &sdl->sdl_data[sdl->sdl_nlen], row.dwPhysAddrLen ); + if(rtm->rtm_rmx.rmx_expire == 0) row.dwType = MIB_IPNET_TYPE_STATIC; + else if(sinarp->sin_other & SIN_PROXY) row.dwType = MIB_IPNET_TYPE_OTHER; + else if(rtm->rtm_rmx.rmx_expire != 0) row.dwType = MIB_IPNET_TYPE_DYNAMIC; + else row.dwType = MIB_IPNET_TYPE_INVALID; - table->table[table->dwNumEntries].bPhysAddr[ - table->table[table->dwNumEntries].dwPhysAddrLen++] = - byte & 0x0ff; - if(rtm->rtm_rmx.rmx_expire == 0) - table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC; - else if(sinarp->sin_other & SIN_PROXY) - table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER; - else if(rtm->rtm_rmx.rmx_expire != 0) - table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC; - else - table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_INVALID; - - table->dwNumEntries++; + if (!(table = append_ipnet_row( heap, flags, table, &count, &row ))) + break; } next += rtm->rtm_msglen; } - HeapFree (GetProcessHeap (), 0, buf); +done: + HeapFree( GetProcessHeap (), 0, buf ); } - else - ret = ERROR_OUTOFMEMORY; - return ret; +#else + FIXME( "not implemented\n" ); + ret = ERROR_NOT_SUPPORTED; #endif - if (table) { - FILE *fp; - *ppIpNetTable = table; - table->dwNumEntries = 0; - /* get from /proc/net/arp, no error if can't */ - fp = fopen("/proc/net/arp", "r"); - if (fp) { - char buf[512] = { 0 }, *ptr; - - /* skip header line */ - ptr = fgets(buf, sizeof(buf), fp); - while (ptr && table->dwNumEntries < numEntries) { - ptr = fgets(buf, sizeof(buf), fp); - if (ptr) { - char *endPtr; - - memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW)); - table->table[table->dwNumEntries].dwAddr = inet_addr(ptr); - while (ptr && *ptr && !isspace(*ptr)) - ptr++; - - if (ptr && *ptr) { - strtoul(ptr, &endPtr, 16); /* hw type (skip) */ - ptr = endPtr; - } - if (ptr && *ptr) { - DWORD flags = strtoul(ptr, &endPtr, 16); - -#ifdef ATF_COM - if (flags & ATF_COM) - table->table[table->dwNumEntries].dwType = - MIB_IPNET_TYPE_DYNAMIC; - else -#endif -#ifdef ATF_PERM - if (flags & ATF_PERM) - table->table[table->dwNumEntries].dwType = - MIB_IPNET_TYPE_STATIC; - else -#endif - table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER; - - ptr = endPtr; - } - while (ptr && *ptr && isspace(*ptr)) - ptr++; - while (ptr && *ptr && !isspace(*ptr)) { - DWORD byte = strtoul(ptr, &endPtr, 16); - - if (endPtr && *endPtr) { - endPtr++; - table->table[table->dwNumEntries].bPhysAddr[ - table->table[table->dwNumEntries].dwPhysAddrLen++] = - byte & 0x0ff; - } - ptr = endPtr; - } - if (ptr && *ptr) { - strtoul(ptr, &endPtr, 16); /* mask (skip) */ - ptr = endPtr; - } - getInterfaceIndexByName(ptr, - &table->table[table->dwNumEntries].dwIndex); - table->dwNumEntries++; - } - } - fclose(fp); - } - else - ret = ERROR_NOT_SUPPORTED; - } - else - ret = ERROR_OUTOFMEMORY; - } - return ret; + if (!table) return ERROR_OUTOFMEMORY; + if (!ret) *ppIpNetTable = table; + else HeapFree( heap, flags, table ); + return ret; } DWORD getNumUdpEntries(void)