iphlpapi: Support for non-linux platforms, including Mac OS X.
- Add error messages when unimplemented functions are called on non-linux platforms. - Implement retrieving the interface list on MacOS X (and other platforms that use NET_RT_DUMP).
This commit is contained in:
parent
1e263e663b
commit
641abc997c
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -51,6 +52,14 @@
|
||||||
#include <netinet/tcp_fsm.h>
|
#include <netinet/tcp_fsm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SYSCTL_H
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ROUNDUP(a) \
|
||||||
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||||
|
#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "iprtrmib.h"
|
#include "iprtrmib.h"
|
||||||
|
@ -71,6 +80,8 @@
|
||||||
#define TCPS_CLOSING 11
|
#define TCPS_CLOSING 11
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
|
||||||
|
|
||||||
DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
|
DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -152,6 +163,9 @@ DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +293,9 @@ DWORD getICMPStats(MIB_ICMP *stats)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,6 +407,9 @@ DWORD getIPStats(PMIB_IPSTATS stats)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,6 +500,9 @@ DWORD getTCPStats(MIB_TCPSTATS *stats)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,6 +556,9 @@ DWORD getUDPStats(MIB_UDPSTATS *stats)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,12 +582,66 @@ static DWORD getNumWithOneHeader(const char *filename)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ERR ("Unable to open '%s' to count entries!\n", filename);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD getNumRoutes(void)
|
DWORD getNumRoutes(void)
|
||||||
{
|
{
|
||||||
return getNumWithOneHeader("/proc/net/route");
|
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
int mib[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
|
||||||
|
size_t needed;
|
||||||
|
char *buf, *lim, *next;
|
||||||
|
struct rt_msghdr *rtm;
|
||||||
|
DWORD RouteCount = 0;
|
||||||
|
|
||||||
|
if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("sysctl 1 failed!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = HeapAlloc (GetProcessHeap (), 0, needed);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
ERR ("HeapAlloc of %ld failed!\n", needed);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("sysctl 2 failed!\n");
|
||||||
|
HeapFree (GetProcessHeap (), 0, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lim = buf + needed;
|
||||||
|
for (next = buf; next < lim; next += rtm->rtm_msglen)
|
||||||
|
{
|
||||||
|
rtm = (struct rt_msghdr *)next;
|
||||||
|
|
||||||
|
if (rtm->rtm_type != RTM_GET)
|
||||||
|
{
|
||||||
|
WARN ("Got unexpected message type 0x%x!\n",
|
||||||
|
rtm->rtm_type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore all entries except for gateway routes which aren't
|
||||||
|
multicast */
|
||||||
|
if (!(rtm->rtm_flags & RTF_GATEWAY) || (rtm->rtm_flags & RTF_MULTICAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RouteCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree (GetProcessHeap (), 0, buf);
|
||||||
|
return RouteCount;
|
||||||
|
#else
|
||||||
|
return getNumWithOneHeader("/proc/net/route");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
||||||
|
@ -577,6 +657,122 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
||||||
sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * sizeof(MIB_IPFORWARDROW));
|
sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * sizeof(MIB_IPFORWARDROW));
|
||||||
|
|
||||||
if (table) {
|
if (table) {
|
||||||
|
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
int mib[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
|
||||||
|
size_t needed;
|
||||||
|
char *buf, *lim, *next, *addrPtr;
|
||||||
|
struct rt_msghdr *rtm;
|
||||||
|
|
||||||
|
if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("sysctl 1 failed!\n");
|
||||||
|
HeapFree (GetProcessHeap (), 0, table);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = HeapAlloc (GetProcessHeap (), 0, needed);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
ERR ("HeapAlloc of %ld failed!\n", needed);
|
||||||
|
HeapFree (GetProcessHeap (), 0, table);
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("sysctl 2 failed!\n");
|
||||||
|
HeapFree (GetProcessHeap (), 0, table);
|
||||||
|
HeapFree (GetProcessHeap (), 0, buf);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppIpForwardTable = table;
|
||||||
|
table->dwNumEntries = 0;
|
||||||
|
|
||||||
|
lim = buf + needed;
|
||||||
|
for (next = buf; next < lim; next += rtm->rtm_msglen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
rtm = (struct rt_msghdr *)next;
|
||||||
|
|
||||||
|
if (rtm->rtm_type != RTM_GET)
|
||||||
|
{
|
||||||
|
WARN ("Got unexpected message type 0x%x!\n",
|
||||||
|
rtm->rtm_type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore all entries except for gateway routes which aren't
|
||||||
|
multicast */
|
||||||
|
if (!(rtm->rtm_flags & RTF_GATEWAY) ||
|
||||||
|
(rtm->rtm_flags & RTF_MULTICAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset (&table->table[table->dwNumEntries], 0,
|
||||||
|
sizeof (MIB_IPFORWARDROW));
|
||||||
|
table->table[table->dwNumEntries].dwForwardIfIndex = rtm->rtm_index;
|
||||||
|
table->table[table->dwNumEntries].dwForwardType =
|
||||||
|
MIB_IPROUTE_TYPE_INDIRECT;
|
||||||
|
table->table[table->dwNumEntries].dwForwardMetric1 =
|
||||||
|
rtm->rtm_rmx.rmx_hopcount;
|
||||||
|
table->table[table->dwNumEntries].dwForwardProto =
|
||||||
|
MIB_IPPROTO_LOCAL;
|
||||||
|
|
||||||
|
addrPtr = (char *)(rtm + 1);
|
||||||
|
|
||||||
|
for (i = 1; i; i <<= 1)
|
||||||
|
{
|
||||||
|
struct sockaddr *sa;
|
||||||
|
DWORD addr;
|
||||||
|
|
||||||
|
if (!(i & rtm->rtm_addrs))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sa = (struct sockaddr *)addrPtr;
|
||||||
|
ADVANCE (addrPtr, sa);
|
||||||
|
|
||||||
|
/* default routes are encoded by length-zero sockaddr */
|
||||||
|
if (sa->sa_len == 0)
|
||||||
|
addr = 0;
|
||||||
|
else if (sa->sa_family != AF_INET)
|
||||||
|
{
|
||||||
|
ERR ("Received unsupported sockaddr family 0x%x\n",
|
||||||
|
sa->sa_family);
|
||||||
|
addr = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||||
|
|
||||||
|
addr = sin->sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case RTA_DST:
|
||||||
|
table->table[table->dwNumEntries].dwForwardDest = addr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTA_GATEWAY:
|
||||||
|
table->table[table->dwNumEntries].dwForwardNextHop = addr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTA_NETMASK:
|
||||||
|
table->table[table->dwNumEntries].dwForwardMask = addr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERR ("Unexpected address type 0x%x\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table->dwNumEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree (GetProcessHeap (), 0, buf);
|
||||||
|
ret = NO_ERROR;
|
||||||
|
#else
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
ret = NO_ERROR;
|
ret = NO_ERROR;
|
||||||
|
@ -656,6 +852,12 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = ERROR_OUTOFMEMORY;
|
ret = ERROR_OUTOFMEMORY;
|
||||||
|
@ -672,6 +874,11 @@ DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!ppIpNetTable)
|
if (!ppIpNetTable)
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
ret = ERROR_INVALID_PARAMETER;
|
||||||
else {
|
else {
|
||||||
|
@ -765,6 +972,11 @@ DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!ppUdpTable)
|
if (!ppUdpTable)
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
ret = ERROR_INVALID_PARAMETER;
|
||||||
else {
|
else {
|
||||||
|
@ -828,6 +1040,11 @@ DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
|
||||||
|
ERR ("unimplemented!\n");
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!ppTcpTable)
|
if (!ppTcpTable)
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
ret = ERROR_INVALID_PARAMETER;
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in New Issue