CVS: winex/dlls/iphlpapi iphlpapi_main.c, 1.12, 1.13 ipstats.c, 1.6, 1.7 ipstats.h, 1.3, 1.4
[email protected] 27 Jun 2007 11:45:06 -0000
Newsgroups
gmane.comp.emulators.winex.cvs
Message-ID
<[email protected] >
Subject: winex/dlls/iphlpapi iphlpapi_main.c,1.12,1.13 ipstats.c,1.6,1.7 ipstats.h,1.3,1.4Update of /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi
In directory agravaine:/tmp/cvs-serv21475/dlls/iphlpapi
Modified Files:
iphlpapi_main.c ipstats.c ipstats.h
Log Message:
- add support for GetTcpTable on Mac OS X
(change by Mark)
Index: iphlpapi_main.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/iphlpapi_main.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- iphlpapi_main.c 27 Apr 2007 13:08:30 -0000 1.12
+++ iphlpapi_main.c 27 Jun 2007 11:45:04 -0000 1.13
@@ -336,7 +336,9 @@
TRACE("ppTcpTable %p, bOrder %d, heap %p, flags 0x%08x\n",
ppTcpTable, bOrder, heap, flags);
- ret = getTcpTable(ppTcpTable, heap, flags);
+
+ *ppTcpTable = NULL;
+ ret = getTcpTable(ppTcpTable, 0, heap, flags);
if (!ret && bOrder)
qsort((*ppTcpTable)->table, (*ppTcpTable)->dwNumEntries,
sizeof(MIB_TCPROW), TcpTableSorter);
@@ -1545,25 +1547,16 @@
ret = ERROR_INSUFFICIENT_BUFFER;
}
else {
- PMIB_TCPTABLE table;
-
- ret = getTcpTable(&table, GetProcessHeap(), 0);
+ ret = getTcpTable(&pTcpTable, numEntries, 0, 0);
if (!ret) {
- size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
+ size = sizeof(MIB_TCPTABLE) + (pTcpTable->dwNumEntries - 1) *
sizeof(MIB_TCPROW);
- if (*pdwSize < size) {
- *pdwSize = size;
- ret = ERROR_INSUFFICIENT_BUFFER;
- }
- else {
- *pdwSize = size;
- memcpy(pTcpTable, table, size);
+ *pdwSize = size;
+
if (bOrder)
- qsort(pTcpTable->table, pTcpTable->dwNumEntries,
- sizeof(MIB_TCPROW), TcpTableSorter);
+ qsort(pTcpTable->table, pTcpTable->dwNumEntries,
+ sizeof(MIB_TCPROW), TcpTableSorter);
ret = NO_ERROR;
- }
- HeapFree(GetProcessHeap(), 0, table);
}
else
ret = ERROR_OUTOFMEMORY;
Index: ipstats.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/ipstats.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ipstats.c 30 Mar 2007 20:25:44 -0000 1.6
+++ ipstats.c 27 Jun 2007 11:45:04 -0000 1.7
@@ -1,4 +1,5 @@
/* Copyright (C) 2003,2006 Juan Lang
+ * Copyright (C) 2007 TransGaming Technologies Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,6 +31,9 @@
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
+#ifdef HAVE_SYS_SOCKETVAR_H
+#include <sys/socketvar.h>
+#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@@ -51,12 +55,25 @@
#ifdef HAVE_NETINET_TCP_FSM_H
#include <netinet/tcp_fsm.h>
#endif
+#ifdef HAVE_NETINET_IN_PCB_H
+#include <netinet/in_pcb.h>
+#endif
+#ifdef HAVE_NETINET_TCP_VAR_H
+#include <netinet/tcp_var.h>
+#endif
+#ifdef HAVE_NETINET_IP_VAR_H
+#include <netinet/ip_var.h>
+#endif
-#ifdef __APPLE__
+#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
+#endif
+#ifndef ROUNDUP
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#endif
+#ifndef ADVANCE
#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
#endif
@@ -66,7 +83,7 @@
#include "ifenum.h"
#include "ipstats.h"
-#ifdef linux
+#ifndef HAVE_NETINET_TCP_FSM_H
#define TCPS_ESTABLISHED 1
#define TCPS_SYN_SENT 2
#define TCPS_SYN_RECEIVED 3
@@ -564,6 +581,100 @@
static DWORD getNumWithOneHeader(const char *filename)
{
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+ size_t Len = 0;
+ char *Buf;
+ struct xinpgen *pXIG, *pOrigXIG;
+ int Protocol;
+ DWORD NumEntries = 0;
+
+ if (!strcmp (filename, "net.inet.tcp.pcblist"))
+ Protocol = IPPROTO_TCP;
+ else if (!strcmp (filename, "net.inet.udp.pcblist"))
+ Protocol = IPPROTO_UDP;
+ else
+ {
+ ERR ("Unsupported mib '%s', needs protocol mapping\n",
+ filename);
+ return 0;
+ }
+
+ if (sysctlbyname (filename, NULL, &Len, NULL, 0) < 0)
+ {
+ WARN ("Unable to read '%s' via sysctlbyname\n", filename);
+ return 0;
+ }
+
+ Buf = HeapAlloc (GetProcessHeap (), 0, Len);
+ if (!Buf)
+ {
+ ERR ("Out of memory!\n");
+ return 0;
+ }
+
+ if (sysctlbyname (filename, Buf, &Len, NULL, 0) < 0)
+ {
+ ERR ("Failure to read '%s' via sysctlbyname!\n", filename);
+ HeapFree (GetProcessHeap (), 0, Buf);
+ return 0;
+ }
+
+ /* Might be nothing here; first entry is just a header it seems */
+ if (Len <= sizeof (struct xinpgen))
+ {
+ HeapFree (GetProcessHeap (), 0, Buf);
+ return 0;
+ }
+
+ pOrigXIG = (struct xinpgen *)Buf;
+ pXIG = pOrigXIG;
+
+ for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
+ pXIG->xig_len > sizeof (struct xinpgen);
+ pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
+ {
+ struct tcpcb *pTCPData = NULL;
+ struct inpcb *pINData;
+ struct xsocket *pSockData;
+
+ if (Protocol == IPPROTO_TCP)
+ {
+ pTCPData = &((struct xtcpcb *)pXIG)->xt_tp;
+ pINData = &((struct xtcpcb *)pXIG)->xt_inp;
+ pSockData = &((struct xtcpcb *)pXIG)->xt_socket;
+ }
+ else
+ {
+ pINData = &((struct xinpcb *)pXIG)->xi_inp;
+ pSockData = &((struct xinpcb *)pXIG)->xi_socket;
+ }
+
+ /* Ignore sockets for other protocols */
+ if (pSockData->xso_protocol != Protocol)
+ continue;
+
+ /* Ignore PCBs that were freed while generating the data */
+ if (pINData->inp_gencnt > pOrigXIG->xig_gen)
+ continue;
+
+ /* we're only interested in IPv4 addresses */
+ if (!(pINData->inp_vflag & INP_IPV4) ||
+ (pINData->inp_vflag & INP_IPV6))
+ continue;
+
+ /* If all 0's, skip it */
+ if (!pINData->inp_laddr.s_addr &&
+ !pINData->inp_lport &&
+ !pINData->inp_faddr.s_addr &&
+ !pINData->inp_fport)
+ continue;
+
+ NumEntries++;
+ }
+
+ HeapFree (GetProcessHeap (), 0, Buf);
+ return NumEntries;
+#else
FILE *fp;
int ret = 0;
@@ -586,6 +697,7 @@
ERR ("Unable to open '%s' to count entries!\n", filename);
return ret;
+#endif
}
DWORD getNumRoutes(void)
@@ -1026,132 +1138,209 @@
return ret;
}
+
DWORD getNumTcpEntries(void)
{
- return getNumWithOneHeader("/proc/net/tcp");
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+ return getNumWithOneHeader ("net.inet.tcp.pcblist");
+#else
+ return getNumWithOneHeader ("/proc/net/tcp");
+#endif
}
-DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
+
+/* Why not a lookup table? Because the TCPS_* constants are different
+ on different platforms */
+static DWORD TCPStateToMIBState (int state)
{
- DWORD ret;
+ switch (state)
+ {
+ case TCPS_ESTABLISHED: return MIB_TCP_STATE_ESTAB;
+ case TCPS_SYN_SENT: return MIB_TCP_STATE_SYN_SENT;
+ case TCPS_SYN_RECEIVED: return MIB_TCP_STATE_SYN_RCVD;
+ case TCPS_FIN_WAIT_1: return MIB_TCP_STATE_FIN_WAIT1;
+ case TCPS_FIN_WAIT_2: return MIB_TCP_STATE_FIN_WAIT2;
+ case TCPS_TIME_WAIT: return MIB_TCP_STATE_TIME_WAIT;
+ case TCPS_CLOSE_WAIT: return MIB_TCP_STATE_CLOSE_WAIT;
+ case TCPS_LAST_ACK: return MIB_TCP_STATE_LAST_ACK;
+ case TCPS_LISTEN: return MIB_TCP_STATE_LISTEN;
+ case TCPS_CLOSING: return MIB_TCP_STATE_CLOSING;
+ default:
+ case TCPS_CLOSED: return MIB_TCP_STATE_CLOSED;
+ }
+}
-#ifdef __APPLE__
- ERR ("unimplemented!\n");
- return ERROR_INVALID_PARAMETER;
+
+DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, DWORD maxEntries, HANDLE heap,
+ DWORD flags)
+{
+ DWORD numEntries;
+ PMIB_TCPTABLE table;
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+ size_t Len = 0;
+ char *Buf;
+ struct xinpgen *pXIG, *pOrigXIG;
+#else
+ FILE *fp;
+ char buf[512] = { 0 }, *ptr;
#endif
- if (!ppTcpTable)
- ret = ERROR_INVALID_PARAMETER;
- else {
- DWORD numEntries = getNumTcpEntries();
- PMIB_TCPTABLE table = HeapAlloc(heap, flags,
- sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
+ if (!ppTcpTable)
+ return ERROR_INVALID_PARAMETER;
- if (table) {
- FILE *fp;
+ numEntries = getNumTcpEntries ();
- ret = NO_ERROR;
- *ppTcpTable = table;
- table->dwNumEntries = 0;
- /* get from /proc/net/tcp, no error if can't */
- fp = fopen("/proc/net/tcp", "r");
- if (fp) {
- char buf[512] = { 0 }, *ptr;
+ if (!*ppTcpTable)
+ {
+ *ppTcpTable = HeapAlloc (heap, flags,
+ sizeof (MIB_TCPTABLE) +
+ (numEntries - 1) * sizeof (MIB_TCPROW));
+ if (!*ppTcpTable)
+ {
+ ERR ("Out of memory!\n");
+ return ERROR_OUTOFMEMORY;
+ }
+ maxEntries = numEntries;
+ }
- /* skip header line */
- ptr = fgets(buf, sizeof(buf), fp);
- while (ptr && table->dwNumEntries < numEntries) {
- memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_TCPROW));
- ptr = fgets(buf, sizeof(buf), fp);
- if (ptr) {
- char *endPtr;
+ table = *ppTcpTable;
+ table->dwNumEntries = 0;
+ if (!numEntries)
+ return NO_ERROR;
- while (ptr && *ptr && *ptr != ':')
- ptr++;
- if (ptr && *ptr)
- ptr++;
- if (ptr && *ptr) {
- table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
- &endPtr, 16);
- ptr = endPtr;
- }
- if (ptr && *ptr) {
- ptr++;
- table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
- &endPtr, 16);
- ptr = endPtr;
- }
- if (ptr && *ptr) {
- table->table[table->dwNumEntries].dwRemoteAddr = strtoul(ptr,
- &endPtr, 16);
- ptr = endPtr;
- }
- if (ptr && *ptr) {
- ptr++;
- table->table[table->dwNumEntries].dwRemotePort = strtoul(ptr,
- &endPtr, 16);
- ptr = endPtr;
- }
- if (ptr && *ptr) {
- DWORD state = strtoul(ptr, &endPtr, 16);
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
- switch (state)
- {
- case TCPS_ESTABLISHED:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_ESTAB;
- break;
- case TCPS_SYN_SENT:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_SYN_SENT;
- break;
- case TCPS_SYN_RECEIVED:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_SYN_RCVD;
- break;
- case TCPS_FIN_WAIT_1:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_FIN_WAIT1;
- break;
- case TCPS_FIN_WAIT_2:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_FIN_WAIT2;
- break;
- case TCPS_TIME_WAIT:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_TIME_WAIT;
- break;
- case TCPS_CLOSED:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_CLOSED;
- break;
- case TCPS_CLOSE_WAIT:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_CLOSE_WAIT;
- break;
- case TCPS_LAST_ACK:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_LAST_ACK;
- break;
- case TCPS_LISTEN:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_LISTEN;
- break;
- case TCPS_CLOSING:
- table->table[table->dwNumEntries].dwState =
- MIB_TCP_STATE_CLOSING;
- break;
- }
- ptr = endPtr;
- }
- table->dwNumEntries++;
- }
- }
- fclose(fp);
+ if (sysctlbyname ("net.inet.tcp.pcblist", NULL, &Len, NULL, 0) < 0)
+ {
+ ERR ("Failure to read net.inet.tcp.pcblist via sysctlbyname!\n");
+ return ERROR_OUTOFMEMORY;
+ }
+
+ Buf = HeapAlloc (GetProcessHeap (), 0, Len);
+ if (!Buf)
+ {
+ ERR ("Out of memory!\n");
+ return ERROR_OUTOFMEMORY;
+ }
+
+ if (sysctlbyname ("net.inet.tcp.pcblist", Buf, &Len, NULL, 0) < 0)
+ {
+ ERR ("Failure to read net.inet.tcp.pcblist via sysctlbyname!\n");
+ HeapFree (GetProcessHeap (), 0, Buf);
+ return ERROR_OUTOFMEMORY;
+ }
+
+ /* Might be nothing here; first entry is just a header it seems */
+ if (Len <= sizeof (struct xinpgen))
+ {
+ HeapFree (GetProcessHeap (), 0, Buf);
+ return NO_ERROR;
+ }
+
+ pOrigXIG = (struct xinpgen *)Buf;
+ pXIG = pOrigXIG;
+
+ for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
+ (pXIG->xig_len > sizeof (struct xinpgen)) &&
+ (table->dwNumEntries < maxEntries);
+ pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
+ {
+ struct tcpcb *pTCPData = NULL;
+ struct inpcb *pINData;
+ struct xsocket *pSockData;
+
+ pTCPData = &((struct xtcpcb *)pXIG)->xt_tp;
+ pINData = &((struct xtcpcb *)pXIG)->xt_inp;
+ pSockData = &((struct xtcpcb *)pXIG)->xt_socket;
+
+ /* Ignore sockets for other protocols */
+ if (pSockData->xso_protocol != IPPROTO_TCP)
+ continue;
+
+ /* Ignore PCBs that were freed while generating the data */
+ if (pINData->inp_gencnt > pOrigXIG->xig_gen)
+ continue;
+
+ /* we're only interested in IPv4 addresses */
+ if (!(pINData->inp_vflag & INP_IPV4) ||
+ (pINData->inp_vflag & INP_IPV6))
+ continue;
+
+ /* If all 0's, skip it */
+ if (!pINData->inp_laddr.s_addr &&
+ !pINData->inp_lport &&
+ !pINData->inp_faddr.s_addr &&
+ !pINData->inp_fport)
+ continue;
+
+ /* Fill in structure details */
+ table->table[table->dwNumEntries].dwLocalAddr =
+ pINData->inp_laddr.s_addr;
+ table->table[table->dwNumEntries].dwLocalPort =
+ pINData->inp_lport;
+ table->table[table->dwNumEntries].dwRemoteAddr =
+ pINData->inp_faddr.s_addr;
+ table->table[table->dwNumEntries].dwRemotePort =
+ pINData->inp_fport;
+ table->table[table->dwNumEntries].dwState =
+ TCPStateToMIBState (pTCPData->t_state);
+
+ table->dwNumEntries++;
+ }
+
+ HeapFree (GetProcessHeap (), 0, Buf);
+#else
+ /* get from /proc/net/tcp, no error if can't */
+ fp = fopen("/proc/net/tcp", "r");
+ if (!fp)
+ return NO_ERROR;
+
+ /* skip header line */
+ ptr = fgets(buf, sizeof(buf), fp);
+ while (ptr && table->dwNumEntries < maxEntries) {
+ memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_TCPROW));
+ ptr = fgets(buf, sizeof(buf), fp);
+ if (ptr) {
+ char *endPtr;
+
+ while (ptr && *ptr && *ptr != ':')
+ ptr++;
+ if (ptr && *ptr)
+ ptr++;
+ if (ptr && *ptr) {
+ table->table[table->dwNumEntries].dwLocalAddr =
+ strtoul(ptr, &endPtr, 16);
+ ptr = endPtr;
+ }
+ if (ptr && *ptr) {
+ ptr++;
+ table->table[table->dwNumEntries].dwLocalPort =
+ strtoul(ptr, &endPtr, 16);
+ ptr = endPtr;
+ }
+ if (ptr && *ptr) {
+ table->table[table->dwNumEntries].dwRemoteAddr =
+ strtoul(ptr, &endPtr, 16);
+ ptr = endPtr;
+ }
+ if (ptr && *ptr) {
+ ptr++;
+ table->table[table->dwNumEntries].dwRemotePort =
+ strtoul(ptr, &endPtr, 16);
+ ptr = endPtr;
+ }
+ if (ptr && *ptr) {
+ DWORD state = strtoul(ptr, &endPtr, 16);
+
+ table->table[table->dwNumEntries].dwState =
+ TCPStateToMIBState (state);
+ ptr = endPtr;
+ }
+ table->dwNumEntries++;
}
- }
- else
- ret = ERROR_OUTOFMEMORY;
- }
- return ret;
+ }
+ fclose(fp);
+#endif
+
+ return NO_ERROR;
}
Index: ipstats.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/ipstats.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ipstats.h 30 Mar 2007 20:11:02 -0000 1.3
+++ ipstats.h 27 Jun 2007 11:45:04 -0000 1.4
@@ -83,6 +83,7 @@
/* Allocates the TCP state table from heap and returns it to you in *ppTcpTable.
* Returns NO_ERROR on success, something else on failure.
*/
-DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags);
+DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, DWORD maxEntries, HANDLE heap,
+ DWORD flags);
#endif /* ndef WINE_IPSTATS_H_ */