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:
Mark Adams 2007-01-25 20:16:25 -05:00 committed by Alexandre Julliard
parent 1e263e663b
commit 641abc997c
1 changed files with 218 additions and 1 deletions

View File

@ -20,6 +20,7 @@
#include "config.h"
#include "wine/port.h"
#include "wine/debug.h"
#include <stdarg.h>
#include <stdio.h>
@ -51,6 +52,14 @@
#include <netinet/tcp_fsm.h>
#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 "winbase.h"
#include "iprtrmib.h"
@ -71,6 +80,8 @@
#define TCPS_CLOSING 11
#endif
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
{
FILE *fp;
@ -152,6 +163,9 @@ DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
}
fclose(fp);
}
else
ERR ("unimplemented!\n");
return NO_ERROR;
}
@ -279,6 +293,9 @@ DWORD getICMPStats(MIB_ICMP *stats)
}
fclose(fp);
}
else
ERR ("unimplemented!\n");
return NO_ERROR;
}
@ -390,6 +407,9 @@ DWORD getIPStats(PMIB_IPSTATS stats)
}
fclose(fp);
}
else
ERR ("unimplemented!\n");
return NO_ERROR;
}
@ -480,6 +500,9 @@ DWORD getTCPStats(MIB_TCPSTATS *stats)
}
fclose(fp);
}
else
ERR ("unimplemented!\n");
return NO_ERROR;
}
@ -533,6 +556,9 @@ DWORD getUDPStats(MIB_UDPSTATS *stats)
}
fclose(fp);
}
else
ERR ("unimplemented!\n");
return NO_ERROR;
}
@ -556,12 +582,66 @@ static DWORD getNumWithOneHeader(const char *filename)
}
fclose(fp);
}
else
ERR ("Unable to open '%s' to count entries!\n", filename);
return ret;
}
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,
@ -577,6 +657,122 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * sizeof(MIB_IPFORWARDROW));
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;
ret = NO_ERROR;
@ -656,6 +852,12 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
}
fclose(fp);
}
else
{
ERR ("unimplemented!\n");
return ERROR_INVALID_PARAMETER;
}
#endif
}
else
ret = ERROR_OUTOFMEMORY;
@ -672,6 +874,11 @@ DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags)
{
DWORD ret;
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
ERR ("unimplemented!\n");
return ERROR_INVALID_PARAMETER;
#endif
if (!ppIpNetTable)
ret = ERROR_INVALID_PARAMETER;
else {
@ -765,6 +972,11 @@ DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
{
DWORD ret;
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
ERR ("unimplemented!\n");
return ERROR_INVALID_PARAMETER;
#endif
if (!ppUdpTable)
ret = ERROR_INVALID_PARAMETER;
else {
@ -828,6 +1040,11 @@ DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
{
DWORD ret;
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
ERR ("unimplemented!\n");
return ERROR_INVALID_PARAMETER;
#endif
if (!ppTcpTable)
ret = ERROR_INVALID_PARAMETER;
else {