iphlpapi: Reimplement GetIpForwardTable to avoid parsing the same information three times.
This commit is contained in:
parent
add9e025c2
commit
3ce9eb0f85
|
@ -1251,48 +1251,31 @@ DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
|
DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
PMIB_IPFORWARDTABLE table;
|
||||||
|
|
||||||
TRACE("pIpForwardTable %p, pdwSize %p, bOrder %d\n", pIpForwardTable,
|
TRACE("pIpForwardTable %p, pdwSize %p, bOrder %d\n", pIpForwardTable, pdwSize, bOrder);
|
||||||
pdwSize, (DWORD)bOrder);
|
|
||||||
if (!pdwSize)
|
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
|
||||||
else {
|
|
||||||
DWORD numRoutes = getNumRoutes();
|
|
||||||
ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE);
|
|
||||||
|
|
||||||
if (numRoutes > 1)
|
if (!pdwSize) return ERROR_INVALID_PARAMETER;
|
||||||
sizeNeeded += (numRoutes - 1) * sizeof(MIB_IPFORWARDROW);
|
|
||||||
if (!pIpForwardTable || *pdwSize < sizeNeeded) {
|
|
||||||
*pdwSize = sizeNeeded;
|
|
||||||
ret = ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PMIB_IPFORWARDTABLE table;
|
|
||||||
|
|
||||||
ret = getRouteTable(&table, GetProcessHeap(), 0);
|
ret = getRouteTable(&table, GetProcessHeap(), 0);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
sizeNeeded = sizeof(MIB_IPFORWARDTABLE);
|
DWORD size = FIELD_OFFSET( MIB_IPFORWARDTABLE, table[table->dwNumEntries] );
|
||||||
if (table->dwNumEntries > 1)
|
if (!pIpForwardTable || *pdwSize < size) {
|
||||||
sizeNeeded += (table->dwNumEntries - 1) * sizeof(MIB_IPFORWARDROW);
|
*pdwSize = size;
|
||||||
if (*pdwSize < sizeNeeded) {
|
|
||||||
*pdwSize = sizeNeeded;
|
|
||||||
ret = ERROR_INSUFFICIENT_BUFFER;
|
ret = ERROR_INSUFFICIENT_BUFFER;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*pdwSize = sizeNeeded;
|
*pdwSize = size;
|
||||||
memcpy(pIpForwardTable, table, sizeNeeded);
|
memcpy(pIpForwardTable, table, size);
|
||||||
if (bOrder)
|
if (bOrder)
|
||||||
qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
|
qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
|
||||||
sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
|
sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
|
||||||
ret = NO_ERROR;
|
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, table);
|
HeapFree(GetProcessHeap(), 0, table);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
TRACE("returning %d\n", ret);
|
||||||
TRACE("returning %d\n", ret);
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1044,53 +1044,110 @@ DWORD getNumRoutes(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
static MIB_IPFORWARDTABLE *append_ipforward_row( HANDLE heap, DWORD flags, MIB_IPFORWARDTABLE *table,
|
||||||
DWORD flags)
|
DWORD *count, const MIB_IPFORWARDROW *row )
|
||||||
{
|
{
|
||||||
DWORD ret;
|
if (table->dwNumEntries >= *count)
|
||||||
|
{
|
||||||
|
MIB_IPFORWARDTABLE *new_table;
|
||||||
|
DWORD new_count = table->dwNumEntries * 2;
|
||||||
|
|
||||||
if (!ppIpForwardTable)
|
if (!(new_table = HeapReAlloc( heap, flags, table,
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
FIELD_OFFSET(MIB_IPFORWARDTABLE, table[new_count] ))))
|
||||||
else {
|
{
|
||||||
DWORD numRoutes = getNumRoutes();
|
HeapFree( heap, 0, table );
|
||||||
DWORD size = sizeof(MIB_IPFORWARDTABLE);
|
return NULL;
|
||||||
PMIB_IPFORWARDTABLE table;
|
}
|
||||||
|
*count = new_count;
|
||||||
|
table = new_table;
|
||||||
|
}
|
||||||
|
memcpy( &table->table[table->dwNumEntries++], row, sizeof(*row) );
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
if (numRoutes > 1)
|
DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap, DWORD flags)
|
||||||
size += (numRoutes - 1) * sizeof(MIB_IPFORWARDROW);
|
{
|
||||||
table = HeapAlloc(heap, flags, size);
|
MIB_IPFORWARDTABLE *table;
|
||||||
if (table) {
|
MIB_IPFORWARDROW row;
|
||||||
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
DWORD ret = NO_ERROR, count = 16;
|
||||||
|
|
||||||
|
if (!ppIpForwardTable) return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (!(table = HeapAlloc( heap, flags, FIELD_OFFSET(MIB_IPFORWARDTABLE, table[count] ))))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
table->dwNumEntries = 0;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if ((fp = fopen("/proc/net/route", "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) );
|
||||||
|
|
||||||
|
while (!isspace(*ptr)) ptr++;
|
||||||
|
*ptr++ = 0;
|
||||||
|
if (getInterfaceIndexByName(buf, &row.dwForwardIfIndex) != NO_ERROR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
row.dwForwardDest = strtoul(ptr, &ptr, 16);
|
||||||
|
row.dwForwardNextHop = strtoul(ptr + 1, &ptr, 16);
|
||||||
|
flags = strtoul(ptr + 1, &ptr, 16);
|
||||||
|
|
||||||
|
if (!(flags & RTF_UP)) row.dwForwardType = MIB_IPROUTE_TYPE_INVALID;
|
||||||
|
else if (flags & RTF_GATEWAY) row.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT;
|
||||||
|
else row.dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
|
||||||
|
|
||||||
|
strtoul(ptr + 1, &ptr, 16); /* refcount, skip */
|
||||||
|
strtoul(ptr + 1, &ptr, 16); /* use, skip */
|
||||||
|
row.dwForwardMetric1 = strtoul(ptr + 1, &ptr, 16);
|
||||||
|
row.dwForwardMask = strtoul(ptr + 1, &ptr, 16);
|
||||||
|
/* FIXME: other protos might be appropriate, e.g. the default
|
||||||
|
* route is typically set with MIB_IPPROTO_NETMGMT instead */
|
||||||
|
row.dwForwardProto = MIB_IPPROTO_LOCAL;
|
||||||
|
|
||||||
|
if (!(table = append_ipforward_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[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
|
int mib[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
|
||||||
size_t needed;
|
size_t needed;
|
||||||
char *buf, *lim, *next, *addrPtr;
|
char *buf = NULL, *lim, *next, *addrPtr;
|
||||||
struct rt_msghdr *rtm;
|
struct rt_msghdr *rtm;
|
||||||
|
|
||||||
if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
|
if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
ERR ("sysctl 1 failed!\n");
|
ERR ("sysctl 1 failed!\n");
|
||||||
HeapFree (GetProcessHeap (), 0, table);
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
return NO_ERROR;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = HeapAlloc (GetProcessHeap (), 0, needed);
|
buf = HeapAlloc (GetProcessHeap (), 0, needed);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
HeapFree (GetProcessHeap (), 0, table);
|
ret = ERROR_OUTOFMEMORY;
|
||||||
return ERROR_OUTOFMEMORY;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
|
if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
ERR ("sysctl 2 failed!\n");
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
HeapFree (GetProcessHeap (), 0, table);
|
goto done;
|
||||||
HeapFree (GetProcessHeap (), 0, buf);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppIpForwardTable = table;
|
|
||||||
table->dwNumEntries = 0;
|
|
||||||
|
|
||||||
lim = buf + needed;
|
lim = buf + needed;
|
||||||
for (next = buf; next < lim; next += rtm->rtm_msglen)
|
for (next = buf; next < lim; next += rtm->rtm_msglen)
|
||||||
{
|
{
|
||||||
|
@ -1111,15 +1168,11 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
||||||
(rtm->rtm_flags & RTF_MULTICAST))
|
(rtm->rtm_flags & RTF_MULTICAST))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memset (&table->table[table->dwNumEntries], 0,
|
memset( &row, 0, sizeof(row) );
|
||||||
sizeof (MIB_IPFORWARDROW));
|
row.dwForwardIfIndex = rtm->rtm_index;
|
||||||
table->table[table->dwNumEntries].dwForwardIfIndex = rtm->rtm_index;
|
row.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT;
|
||||||
table->table[table->dwNumEntries].dwForwardType =
|
row.dwForwardMetric1 = rtm->rtm_rmx.rmx_hopcount;
|
||||||
MIB_IPROUTE_TYPE_INDIRECT;
|
row.dwForwardProto = MIB_IPPROTO_LOCAL;
|
||||||
table->table[table->dwNumEntries].dwForwardMetric1 =
|
|
||||||
rtm->rtm_rmx.rmx_hopcount;
|
|
||||||
table->table[table->dwNumEntries].dwForwardProto =
|
|
||||||
MIB_IPPROTO_LOCAL;
|
|
||||||
|
|
||||||
addrPtr = (char *)(rtm + 1);
|
addrPtr = (char *)(rtm + 1);
|
||||||
|
|
||||||
|
@ -1152,119 +1205,29 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
||||||
|
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case RTA_DST:
|
case RTA_DST: row.dwForwardDest = addr; break;
|
||||||
table->table[table->dwNumEntries].dwForwardDest = addr;
|
case RTA_GATEWAY: row.dwForwardNextHop = addr; break;
|
||||||
break;
|
case RTA_NETMASK: row.dwForwardMask = addr; break;
|
||||||
|
|
||||||
case RTA_GATEWAY:
|
|
||||||
table->table[table->dwNumEntries].dwForwardNextHop = addr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTA_NETMASK:
|
|
||||||
table->table[table->dwNumEntries].dwForwardMask = addr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN ("Unexpected address type 0x%x\n", i);
|
WARN ("Unexpected address type 0x%x\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table->dwNumEntries++;
|
if (!(table = append_ipforward_row( heap, flags, table, &count, &row )))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
HeapFree (GetProcessHeap (), 0, buf);
|
HeapFree( GetProcessHeap (), 0, buf );
|
||||||
ret = NO_ERROR;
|
|
||||||
#else
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
ret = NO_ERROR;
|
|
||||||
*ppIpForwardTable = table;
|
|
||||||
table->dwNumEntries = 0;
|
|
||||||
/* get from /proc/net/route, no error if can't */
|
|
||||||
fp = fopen("/proc/net/route", "r");
|
|
||||||
if (fp) {
|
|
||||||
char buf[512] = { 0 }, *ptr;
|
|
||||||
|
|
||||||
/* skip header line */
|
|
||||||
ptr = fgets(buf, sizeof(buf), fp);
|
|
||||||
while (ptr && table->dwNumEntries < numRoutes) {
|
|
||||||
memset(&table->table[table->dwNumEntries], 0,
|
|
||||||
sizeof(MIB_IPFORWARDROW));
|
|
||||||
ptr = fgets(buf, sizeof(buf), fp);
|
|
||||||
if (ptr) {
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
while (!isspace(*ptr))
|
|
||||||
ptr++;
|
|
||||||
*ptr = '\0';
|
|
||||||
ptr++;
|
|
||||||
if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
|
|
||||||
char *endPtr;
|
|
||||||
|
|
||||||
table->table[table->dwNumEntries].dwForwardIfIndex = index;
|
|
||||||
if (*ptr) {
|
|
||||||
table->table[table->dwNumEntries].dwForwardDest =
|
|
||||||
strtoul(ptr, &endPtr, 16);
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
table->table[table->dwNumEntries].dwForwardNextHop =
|
|
||||||
strtoul(ptr, &endPtr, 16);
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
DWORD flags = strtoul(ptr, &endPtr, 16);
|
|
||||||
|
|
||||||
if (!(flags & RTF_UP))
|
|
||||||
table->table[table->dwNumEntries].dwForwardType =
|
|
||||||
MIB_IPROUTE_TYPE_INVALID;
|
|
||||||
else if (flags & RTF_GATEWAY)
|
|
||||||
table->table[table->dwNumEntries].dwForwardType =
|
|
||||||
MIB_IPROUTE_TYPE_INDIRECT;
|
|
||||||
else
|
|
||||||
table->table[table->dwNumEntries].dwForwardType =
|
|
||||||
MIB_IPROUTE_TYPE_DIRECT;
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
strtoul(ptr, &endPtr, 16); /* refcount, skip */
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
strtoul(ptr, &endPtr, 16); /* use, skip */
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
table->table[table->dwNumEntries].dwForwardMetric1 =
|
|
||||||
strtoul(ptr, &endPtr, 16);
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
if (ptr && *ptr) {
|
|
||||||
table->table[table->dwNumEntries].dwForwardMask =
|
|
||||||
strtoul(ptr, &endPtr, 16);
|
|
||||||
ptr = endPtr;
|
|
||||||
}
|
|
||||||
/* FIXME: other protos might be appropriate, e.g. the default
|
|
||||||
* route is typically set with MIB_IPPROTO_NETMGMT instead */
|
|
||||||
table->table[table->dwNumEntries].dwForwardProto =
|
|
||||||
MIB_IPPROTO_LOCAL;
|
|
||||||
table->dwNumEntries++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR ("unimplemented!\n");
|
|
||||||
return ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
#else
|
||||||
ret = ERROR_OUTOFMEMORY;
|
FIXME( "not implemented\n" );
|
||||||
}
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
return ret;
|
#endif
|
||||||
|
|
||||||
|
if (!table) return ERROR_OUTOFMEMORY;
|
||||||
|
if (!ret) *ppIpForwardTable = table;
|
||||||
|
else HeapFree( heap, flags, table );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD getNumArpEntries(void)
|
DWORD getNumArpEntries(void)
|
||||||
|
|
Loading…
Reference in New Issue