iphlpapi: Implement AllocateAndGetIpNetTableFromStack() on top of GetIpNetTable().
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a16697398b
commit
b63195d595
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue