From b63195d595db662e6d716395bc4fd5c12710790f Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 10 Aug 2021 09:20:50 +0100 Subject: [PATCH] iphlpapi: Implement AllocateAndGetIpNetTableFromStack() on top of GetIpNetTable(). Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/iphlpapi/iphlpapi_main.c | 23 ++++ dlls/iphlpapi/ipstats.c | 193 ---------------------------------- 2 files changed, 23 insertions(+), 193 deletions(-) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 24cfedd2b02..fe2daa0f24d 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2317,6 +2317,29 @@ err: return err; } +/****************************************************************** + * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@) + */ +DWORD WINAPI AllocateAndGetIpNetTableFromStack( MIB_IPNETTABLE **table, BOOL sort, HANDLE heap, DWORD flags ) +{ + DWORD err, size = FIELD_OFFSET(MIB_IPNETTABLE, table[2]), attempt; + + TRACE( "table %p, sort %d, heap %p, flags 0x%08x\n", table, sort, heap, flags ); + + for (attempt = 0; attempt < 5; attempt++) + { + *table = HeapAlloc( heap, flags, size ); + if (!*table) return ERROR_NOT_ENOUGH_MEMORY; + + err = GetIpNetTable( *table, &size, sort ); + if (!err) break; + HeapFree( heap, flags, *table ); + if (err != ERROR_INSUFFICIENT_BUFFER) break; + } + + return err; +} + static void ipnet_row2_fill( MIB_IPNET_ROW2 *row, USHORT fam, void *key, struct nsi_ip_neighbour_rw *rw, struct nsi_ip_neighbour_dynamic *dyn ) { diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index 7bb4ff0603e..115bafa6f8e 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -1220,199 +1220,6 @@ static void *append_table_row( HANDLE heap, DWORD flags, void *table, DWORD *tab return table; } -static int compare_ipnet_rows(const void *a, const void *b) -{ - const MIB_IPNETROW *rowA = a; - const MIB_IPNETROW *rowB = b; - - return ntohl(rowA->dwAddr) - ntohl(rowB->dwAddr); -} - - -/****************************************************************** - * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@) - * - * Get the IP-to-physical address mapping table. - * Like GetIpNetTable(), but allocate the returned table from heap. - * - * PARAMS - * ppIpNetTable [Out] pointer into which the MIB_IPNETTABLE is - * allocated and returned. - * bOrder [In] whether to sort the table - * heap [In] heap from which the table is allocated - * flags [In] flags to HeapAlloc - * - * RETURNS - * ERROR_INVALID_PARAMETER if ppIpNetTable is NULL, other error codes - * on failure, NO_ERROR on success. - */ -DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable, BOOL bOrder, - HANDLE heap, DWORD flags) -{ - MIB_IPNETTABLE *table; - MIB_IPNETROW row; - DWORD ret = NO_ERROR, count = 16, table_size = FIELD_OFFSET( MIB_IPNETTABLE, table[count] ); - - TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppIpNetTable, bOrder, heap, flags); - - if (!ppIpNetTable) return ERROR_INVALID_PARAMETER; - - if (!(table = HeapAlloc( heap, flags, table_size ))) - return ERROR_OUTOFMEMORY; - - table->dwNumEntries = 0; - -#ifdef __linux__ - { - FILE *fp; - - if ((fp = fopen("/proc/net/arp", "r"))) - { - char buf[512], *ptr; - DWORD atf_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) */ - atf_flags = strtoul(ptr + 1, &ptr, 16); - -#ifdef ATF_COM - if (atf_flags & ATF_COM) row.u.Type = MIB_IPNET_TYPE_DYNAMIC; - else -#endif -#ifdef ATF_PERM - if (atf_flags & ATF_PERM) row.u.Type = MIB_IPNET_TYPE_STATIC; - else -#endif - row.u.Type = 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_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) ))) - break; - } - fclose(fp); - } - else ret = ERROR_NOT_SUPPORTED; - } -#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK) - { - void *data; - int fd, len, namelen; - mib2_ipNetToMediaEntry_t *entry; - char name[64]; - - if ((fd = open_streams_mib( NULL )) != -1) - { - if ((data = read_mib_entry( fd, MIB2_IP, MIB2_IP_MEDIA, &len ))) - { - for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++) - { - row.dwPhysAddrLen = min( entry->ipNetToMediaPhysAddress.o_length, MAXLEN_PHYSADDR ); - memcpy( row.bPhysAddr, entry->ipNetToMediaPhysAddress.o_bytes, row.dwPhysAddrLen ); - row.dwAddr = entry->ipNetToMediaNetAddress; - row.u.Type = entry->ipNetToMediaType; - namelen = min( sizeof(name) - 1, entry->ipNetToMediaIfIndex.o_length ); - memcpy( name, entry->ipNetToMediaIfIndex.o_bytes, namelen ); - name[namelen] = 0; - getInterfaceIndexByName( name, &row.dwIndex ); - if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) ))) - break; - } - HeapFree( GetProcessHeap(), 0, data ); - } - close( fd ); - } - 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}; - size_t needed; - char *buf = NULL, *lim, *next; - struct rt_msghdr *rtm; - struct sockaddr_inarp *sinarp; - struct sockaddr_dl *sdl; - - if (sysctl (mib, ARRAY_SIZE(mib), NULL, &needed, NULL, 0) == -1) - { - ERR ("failed to get arp table\n"); - ret = ERROR_NOT_SUPPORTED; - goto done; - } - - buf = HeapAlloc (GetProcessHeap (), 0, needed); - if (!buf) - { - ret = ERROR_OUTOFMEMORY; - goto done; - } - - if (sysctl (mib, ARRAY_SIZE(mib), buf, &needed, NULL, 0) == -1) - { - ret = ERROR_NOT_SUPPORTED; - goto done; - } - - lim = buf + needed; - next = buf; - while(next < lim) - { - rtm = (struct rt_msghdr *)next; - sinarp=(struct sockaddr_inarp *)(rtm + 1); - sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); - if(sdl->sdl_alen) /* arp entry */ - { - 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.u.Type = MIB_IPNET_TYPE_STATIC; - else if(sinarp->sin_other & SIN_PROXY) row.u.Type = MIB_IPNET_TYPE_OTHER; - else if(rtm->rtm_rmx.rmx_expire != 0) row.u.Type = MIB_IPNET_TYPE_DYNAMIC; - else row.u.Type = MIB_IPNET_TYPE_INVALID; - - if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) ))) - break; - } - next += rtm->rtm_msglen; - } -done: - HeapFree( GetProcessHeap (), 0, buf ); - } -#else - FIXME( "not implemented\n" ); - ret = ERROR_NOT_SUPPORTED; -#endif - - if (!table) return ERROR_OUTOFMEMORY; - if (!ret) - { - if (bOrder && table->dwNumEntries) - qsort( table->table, table->dwNumEntries, sizeof(row), compare_ipnet_rows ); - *ppIpNetTable = table; - } - else HeapFree( heap, flags, table ); - TRACE( "returning ret %u table %p\n", ret, table ); - return ret; -} - static DWORD get_tcp_table_sizes( TCP_TABLE_CLASS class, DWORD row_count, DWORD *row_size ) { DWORD table_size;