iphlpapi: Add support for GetTcpTable on Mac OS X.
diff --git a/configure b/configure
index 483725a..266f7af 100755
--- a/configure
+++ b/configure
@@ -6820,6 +6820,7 @@
+
for ac_header in \
AudioUnit/AudioUnit.h \
Carbon/Carbon.h \
@@ -6913,6 +6914,7 @@
sys/shm.h \
sys/signal.h \
sys/socket.h \
+ sys/socketvar.h \
sys/sockio.h \
sys/soundcard.h \
sys/statvfs.h \
@@ -7216,7 +7218,9 @@
-for ac_header in net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h
+
+
+for ac_header in netinet/in_pcb.h netinet/ip_var.h net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
@@ -7276,6 +7280,80 @@
done
+ #if HAVE_SYS_SOCKETVAR_H
+ # include <sys/socketvar.h>
+ #endif
+
+
+for ac_header in netinet/tcp_var.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #if HAVE_SYS_SOCKET_H
+ # include <sys/socket.h>
+ #endif
+ #if HAVE_SYS_SOCKETVAR_H
+ # include <sys/socketvar.h>
+ #endif
+ #if HAVE_NETINET_IN_H
+ # include <netinet/in.h>
+ #endif
+ #ifdef HAVE_NETINET_TCP_H
+ # include <netinet/tcp.h>
+ #endif
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
for ac_header in linux/ipx.h
diff --git a/configure.ac b/configure.ac
index 2dd7cb9..a03f097 100644
--- a/configure.ac
+++ b/configure.ac
@@ -249,6 +249,7 @@
sys/shm.h \
sys/signal.h \
sys/socket.h \
+ sys/socketvar.h \
sys/sockio.h \
sys/soundcard.h \
sys/statvfs.h \
@@ -278,11 +279,29 @@
# include <sys/param.h>
#endif])
-AC_CHECK_HEADERS([net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h],,,
+AC_CHECK_HEADERS([netinet/in_pcb.h netinet/ip_var.h net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h],,,
[#include <sys/types.h>
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif])
+ #if HAVE_SYS_SOCKETVAR_H
+ # include <sys/socketvar.h>
+ #endif
+
+AC_CHECK_HEADERS([netinet/tcp_var.h],,,
+ [#include <sys/types.h>
+ #if HAVE_SYS_SOCKET_H
+ # include <sys/socket.h>
+ #endif
+ #if HAVE_SYS_SOCKETVAR_H
+ # include <sys/socketvar.h>
+ #endif
+ #if HAVE_NETINET_IN_H
+ # include <netinet/in.h>
+ #endif
+ #ifdef HAVE_NETINET_TCP_H
+ # include <netinet/tcp.h>
+ #endif])
AC_CHECK_HEADERS([linux/ipx.h],,,
[#include <sys/types.h>
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 6b7fa62..799f7fc 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -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;
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index b80cf61..7c6488c 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -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
@@ -52,13 +56,27 @@
#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 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
#include "windef.h"
#include "winbase.h"
@@ -66,7 +84,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 +582,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 +698,7 @@
ERR ("Unable to open '%s' to count entries!\n", filename);
return ret;
+#endif
}
DWORD getNumRoutes(void)
@@ -1026,132 +1139,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)
-{
- DWORD ret;
-#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
- ERR ("unimplemented!\n");
- return ERROR_INVALID_PARAMETER;
+/* Why not a lookup table? Because the TCPS_* constants are different
+ on different platforms */
+static DWORD TCPStateToMIBState (int state)
+{
+ 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;
+ }
+}
+
+
+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;
-
- /* 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;
-
- 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);
-
- 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 (!*ppTcpTable)
+ {
+ *ppTcpTable = HeapAlloc (heap, flags,
+ sizeof (MIB_TCPTABLE) +
+ (numEntries - 1) * sizeof (MIB_TCPROW));
+ if (!*ppTcpTable)
+ {
+ ERR ("Out of memory!\n");
+ return ERROR_OUTOFMEMORY;
}
- }
- else
- ret = ERROR_OUTOFMEMORY;
- }
- return ret;
+ maxEntries = numEntries;
+ }
+
+ table = *ppTcpTable;
+ table->dwNumEntries = 0;
+ if (!numEntries)
+ return NO_ERROR;
+
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+
+ 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++;
+ }
+ }
+ fclose(fp);
+#endif
+
+ return NO_ERROR;
}
diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h
index 147276e..ec8dcb0 100644
--- a/dlls/iphlpapi/ipstats.h
+++ b/dlls/iphlpapi/ipstats.h
@@ -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_ */
diff --git a/include/config.h.in b/include/config.h.in
index 9366a9f..c95abd0 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -426,15 +426,24 @@
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
+/* Define to 1 if you have the <netinet/in_pcb.h> header file. */
+#undef HAVE_NETINET_IN_PCB_H
+
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
#undef HAVE_NETINET_IN_SYSTM_H
+/* Define to 1 if you have the <netinet/ip_var.h> header file. */
+#undef HAVE_NETINET_IP_VAR_H
+
/* Define to 1 if you have the <netinet/tcp_fsm.h> header file. */
#undef HAVE_NETINET_TCP_FSM_H
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
+/* Define to 1 if you have the <netinet/tcp_var.h> header file. */
+#undef HAVE_NETINET_TCP_VAR_H
+
/* Define to 1 if you have the <netipx/ipx.h> header file. */
#undef HAVE_NETIPX_IPX_H
@@ -777,6 +786,9 @@
/* Define to 1 if you have the <sys/signal.h> header file. */
#undef HAVE_SYS_SIGNAL_H
+/* Define to 1 if you have the <sys/socketvar.h> header file. */
+#undef HAVE_SYS_SOCKETVAR_H
+
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H