iphlpapi: Add support for GetTcpTable on Mac OS X.
This commit is contained in:
parent
154389ce8e
commit
2569635cbf
|
@ -6818,6 +6818,7 @@ done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_header in \
|
for ac_header in \
|
||||||
|
@ -6913,6 +6914,7 @@ for ac_header in \
|
||||||
sys/shm.h \
|
sys/shm.h \
|
||||||
sys/signal.h \
|
sys/signal.h \
|
||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
|
sys/socketvar.h \
|
||||||
sys/sockio.h \
|
sys/sockio.h \
|
||||||
sys/soundcard.h \
|
sys/soundcard.h \
|
||||||
sys/statvfs.h \
|
sys/statvfs.h \
|
||||||
|
@ -7216,7 +7218,9 @@ done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
do
|
||||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||||
|
@ -7274,6 +7278,80 @@ _ACEOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
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
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
21
configure.ac
21
configure.ac
|
@ -249,6 +249,7 @@ AC_CHECK_HEADERS(\
|
||||||
sys/shm.h \
|
sys/shm.h \
|
||||||
sys/signal.h \
|
sys/signal.h \
|
||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
|
sys/socketvar.h \
|
||||||
sys/sockio.h \
|
sys/sockio.h \
|
||||||
sys/soundcard.h \
|
sys/soundcard.h \
|
||||||
sys/statvfs.h \
|
sys/statvfs.h \
|
||||||
|
@ -278,11 +279,29 @@ AC_CHECK_HEADERS([sys/mount.h sys/statfs.h sys/user.h sys/vfs.h],,,
|
||||||
# include <sys/param.h>
|
# include <sys/param.h>
|
||||||
#endif])
|
#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>
|
[#include <sys/types.h>
|
||||||
#if HAVE_SYS_SOCKET_H
|
#if HAVE_SYS_SOCKET_H
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif])
|
#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],,,
|
AC_CHECK_HEADERS([linux/ipx.h],,,
|
||||||
[#include <sys/types.h>
|
[#include <sys/types.h>
|
||||||
|
|
|
@ -336,7 +336,9 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
|
||||||
|
|
||||||
TRACE("ppTcpTable %p, bOrder %d, heap %p, flags 0x%08x\n",
|
TRACE("ppTcpTable %p, bOrder %d, heap %p, flags 0x%08x\n",
|
||||||
ppTcpTable, bOrder, heap, flags);
|
ppTcpTable, bOrder, heap, flags);
|
||||||
ret = getTcpTable(ppTcpTable, heap, flags);
|
|
||||||
|
*ppTcpTable = NULL;
|
||||||
|
ret = getTcpTable(ppTcpTable, 0, heap, flags);
|
||||||
if (!ret && bOrder)
|
if (!ret && bOrder)
|
||||||
qsort((*ppTcpTable)->table, (*ppTcpTable)->dwNumEntries,
|
qsort((*ppTcpTable)->table, (*ppTcpTable)->dwNumEntries,
|
||||||
sizeof(MIB_TCPROW), TcpTableSorter);
|
sizeof(MIB_TCPROW), TcpTableSorter);
|
||||||
|
@ -1545,25 +1547,16 @@ DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
|
||||||
ret = ERROR_INSUFFICIENT_BUFFER;
|
ret = ERROR_INSUFFICIENT_BUFFER;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PMIB_TCPTABLE table;
|
ret = getTcpTable(&pTcpTable, numEntries, 0, 0);
|
||||||
|
|
||||||
ret = getTcpTable(&table, GetProcessHeap(), 0);
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
|
size = sizeof(MIB_TCPTABLE) + (pTcpTable->dwNumEntries - 1) *
|
||||||
sizeof(MIB_TCPROW);
|
sizeof(MIB_TCPROW);
|
||||||
if (*pdwSize < size) {
|
*pdwSize = size;
|
||||||
*pdwSize = size;
|
|
||||||
ret = ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*pdwSize = size;
|
|
||||||
memcpy(pTcpTable, table, size);
|
|
||||||
if (bOrder)
|
if (bOrder)
|
||||||
qsort(pTcpTable->table, pTcpTable->dwNumEntries,
|
qsort(pTcpTable->table, pTcpTable->dwNumEntries,
|
||||||
sizeof(MIB_TCPROW), TcpTableSorter);
|
sizeof(MIB_TCPROW), TcpTableSorter);
|
||||||
ret = NO_ERROR;
|
ret = NO_ERROR;
|
||||||
}
|
|
||||||
HeapFree(GetProcessHeap(), 0, table);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = ERROR_OUTOFMEMORY;
|
ret = ERROR_OUTOFMEMORY;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* Copyright (C) 2003,2006 Juan Lang
|
/* Copyright (C) 2003,2006 Juan Lang
|
||||||
|
* Copyright (C) 2007 TransGaming Technologies Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -30,6 +31,9 @@
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKETVAR_H
|
||||||
|
#include <sys/socketvar.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,13 +56,27 @@
|
||||||
#include <netinet/tcp_fsm.h>
|
#include <netinet/tcp_fsm.h>
|
||||||
#endif
|
#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
|
#ifdef HAVE_SYS_SYSCTL_H
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ROUNDUP
|
||||||
#define ROUNDUP(a) \
|
#define ROUNDUP(a) \
|
||||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||||
|
#endif
|
||||||
|
#ifndef ADVANCE
|
||||||
#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
|
#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -66,7 +84,7 @@
|
||||||
#include "ifenum.h"
|
#include "ifenum.h"
|
||||||
#include "ipstats.h"
|
#include "ipstats.h"
|
||||||
|
|
||||||
#ifdef linux
|
#ifndef HAVE_NETINET_TCP_FSM_H
|
||||||
#define TCPS_ESTABLISHED 1
|
#define TCPS_ESTABLISHED 1
|
||||||
#define TCPS_SYN_SENT 2
|
#define TCPS_SYN_SENT 2
|
||||||
#define TCPS_SYN_RECEIVED 3
|
#define TCPS_SYN_RECEIVED 3
|
||||||
|
@ -564,6 +582,100 @@ DWORD getUDPStats(MIB_UDPSTATS *stats)
|
||||||
|
|
||||||
static DWORD getNumWithOneHeader(const char *filename)
|
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;
|
FILE *fp;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -586,6 +698,7 @@ static DWORD getNumWithOneHeader(const char *filename)
|
||||||
ERR ("Unable to open '%s' to count entries!\n", filename);
|
ERR ("Unable to open '%s' to count entries!\n", filename);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD getNumRoutes(void)
|
DWORD getNumRoutes(void)
|
||||||
|
@ -1026,132 +1139,209 @@ DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DWORD getNumTcpEntries(void)
|
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)
|
/* Why not a lookup table? Because the TCPS_* constants are different
|
||||||
ERR ("unimplemented!\n");
|
on different platforms */
|
||||||
return ERROR_INVALID_PARAMETER;
|
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
|
#endif
|
||||||
|
|
||||||
if (!ppTcpTable)
|
if (!ppTcpTable)
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
else {
|
|
||||||
DWORD numEntries = getNumTcpEntries();
|
|
||||||
PMIB_TCPTABLE table = HeapAlloc(heap, flags,
|
|
||||||
sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
|
|
||||||
|
|
||||||
if (table) {
|
numEntries = getNumTcpEntries ();
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
ret = NO_ERROR;
|
if (!*ppTcpTable)
|
||||||
*ppTcpTable = table;
|
{
|
||||||
table->dwNumEntries = 0;
|
*ppTcpTable = HeapAlloc (heap, flags,
|
||||||
/* get from /proc/net/tcp, no error if can't */
|
sizeof (MIB_TCPTABLE) +
|
||||||
fp = fopen("/proc/net/tcp", "r");
|
(numEntries - 1) * sizeof (MIB_TCPROW));
|
||||||
if (fp) {
|
if (!*ppTcpTable)
|
||||||
char buf[512] = { 0 }, *ptr;
|
{
|
||||||
|
ERR ("Out of memory!\n");
|
||||||
/* skip header line */
|
return ERROR_OUTOFMEMORY;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
maxEntries = numEntries;
|
||||||
else
|
}
|
||||||
ret = ERROR_OUTOFMEMORY;
|
|
||||||
}
|
table = *ppTcpTable;
|
||||||
return ret;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ DWORD getNumTcpEntries(void);
|
||||||
/* Allocates the TCP state table from heap and returns it to you in *ppTcpTable.
|
/* Allocates the TCP state table from heap and returns it to you in *ppTcpTable.
|
||||||
* Returns NO_ERROR on success, something else on failure.
|
* 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_ */
|
#endif /* ndef WINE_IPSTATS_H_ */
|
||||||
|
|
|
@ -426,15 +426,24 @@
|
||||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
#undef HAVE_NETINET_IN_H
|
#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. */
|
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
|
||||||
#undef HAVE_NETINET_IN_SYSTM_H
|
#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. */
|
/* Define to 1 if you have the <netinet/tcp_fsm.h> header file. */
|
||||||
#undef HAVE_NETINET_TCP_FSM_H
|
#undef HAVE_NETINET_TCP_FSM_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||||
#undef HAVE_NETINET_TCP_H
|
#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. */
|
/* Define to 1 if you have the <netipx/ipx.h> header file. */
|
||||||
#undef HAVE_NETIPX_IPX_H
|
#undef HAVE_NETIPX_IPX_H
|
||||||
|
|
||||||
|
@ -777,6 +786,9 @@
|
||||||
/* Define to 1 if you have the <sys/signal.h> header file. */
|
/* Define to 1 if you have the <sys/signal.h> header file. */
|
||||||
#undef HAVE_SYS_SIGNAL_H
|
#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. */
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
#undef HAVE_SYS_SOCKET_H
|
#undef HAVE_SYS_SOCKET_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue