iphlpapi - MacOS / BSD support
Gavriel State
gav at transgaming.com
Mon Jan 15 20:17:25 CST 2007
Author: Mark Adams <mark at transgaming.com>
ChangeLog:
- Clarify interface counting
- Filter out no-ip addresses when building ip address table
- Add error messages when unimplemented functions are called on
non-linux platforms (ie: platforms without routing info in /proc)
- Implement retrieving the interface list on MacOS X (and other
platforms that use NET_RT_DUMP)
--
Gavriel State
Founder & CTO
TransGaming Technologies Inc.
gav at transgaming.com
http://www.transgaming.com
Broadening The Playing Field
-------------- next part --------------
Index: iphlpapi/ifenum.c
===================================================================
RCS file: /home/wine/wine/dlls/iphlpapi/ifenum.c,v
retrieving revision 1.25
diff -u -r1.25 ifenum.c
--- iphlpapi/ifenum.c 21 Dec 2006 16:37:51 -0000 1.25
+++ iphlpapi/ifenum.c 15 Jan 2007 23:16:54 -0000
@@ -22,7 +22,7 @@
* interface:
* - a specific IOCTL (Linux)
* - looking in the ARP cache (at least Solaris)
- * - using the sysctl interface (FreeBSD and Mac OS X)
+ * - using the sysctl interface (FreeBSD and MacOS X)
* Solaris and some others have SIOCGENADDR, but I haven't gotten that to work
* on the Solaris boxes at SourceForge's compile farm, whereas SIOCGARP does.
*/
@@ -673,14 +673,16 @@
int ioctlRet = 0;
DWORD guessedNumAddresses = 0, numAddresses = 0;
caddr_t ifPtr;
+ int lastlen;
ret = NO_ERROR;
ifc->ifc_len = 0;
ifc->ifc_buf = NULL;
/* there is no way to know the interface count beforehand,
so we need to loop again and again upping our max each time
- until returned < max */
+ until returned is constant across 2 calls */
do {
+ lastlen = ifc->ifc_len;
HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
if (guessedNumAddresses == 0)
guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
@@ -689,13 +691,16 @@
ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len);
ioctlRet = ioctl(fd, SIOCGIFCONF, ifc);
- } while (ioctlRet == 0 &&
- ifc->ifc_len > (sizeof(struct ifreq) * (guessedNumAddresses - 2)));
+ } while ((ioctlRet == 0) && (ifc->ifc_len != lastlen));
if (ioctlRet == 0) {
ifPtr = ifc->ifc_buf;
while (ifPtr && ifPtr < ifc->ifc_buf + ifc->ifc_len) {
- numAddresses++;
+ struct ifreq *ifr = (struct ifreq *)ifPtr;
+
+ if (ifr->ifr_addr.sa_family == AF_INET)
+ numAddresses++;
+
ifPtr += ifreq_len((struct ifreq *)ifPtr);
}
}
@@ -751,6 +756,11 @@
while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
struct ifreq *ifr = (struct ifreq *)ifPtr;
+ ifPtr += ifreq_len(ifr);
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+
ret = getInterfaceIndexByName(ifr->ifr_name,
&(*ppIpAddrTable)->table[i].dwIndex);
memcpy(&(*ppIpAddrTable)->table[i].dwAddr, ifr->ifr_addr.sa_data + 2,
@@ -769,7 +779,6 @@
(*ppIpAddrTable)->table[i].unused1 = 0;
(*ppIpAddrTable)->table[i].wType = 0;
- ifPtr += ifreq_len(ifr);
i++;
}
}
Index: iphlpapi/ipstats.c
===================================================================
RCS file: /home/wine/wine/dlls/iphlpapi/ipstats.c,v
retrieving revision 1.16
diff -u -r1.16 ipstats.c
--- iphlpapi/ipstats.c 23 May 2006 12:48:02 -0000 1.16
+++ iphlpapi/ipstats.c 15 Jan 2007 23:16:54 -0000
@@ -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 @@
}
fclose(fp);
}
+ else
+ ERR ("unimplemented!\n");
+
return NO_ERROR;
}
@@ -279,6 +293,9 @@
}
fclose(fp);
}
+ else
+ ERR ("unimplemented!\n");
+
return NO_ERROR;
}
@@ -390,6 +407,9 @@
}
fclose(fp);
}
+ else
+ ERR ("unimplemented!\n");
+
return NO_ERROR;
}
@@ -480,6 +500,9 @@
}
fclose(fp);
}
+ else
+ ERR ("unimplemented!\n");
+
return NO_ERROR;
}
@@ -533,6 +556,9 @@
}
fclose(fp);
}
+ else
+ ERR ("unimplemented!\n");
+
return NO_ERROR;
}
@@ -556,12 +582,66 @@
}
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 @@
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 @@
}
fclose(fp);
}
+ else
+ {
+ ERR ("unimplemented!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+#endif
}
else
ret = ERROR_OUTOFMEMORY;
@@ -672,6 +874,11 @@
{
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 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 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 {
More information about the wine-patches
mailing list