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 \
|
||||
|
@ -6913,6 +6914,7 @@ for ac_header in \
|
|||
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 @@ 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
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||
|
@ -7274,6 +7278,80 @@ _ACEOF
|
|||
|
||||
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
|
||||
|
||||
|
||||
|
|
21
configure.ac
21
configure.ac
|
@ -249,6 +249,7 @@ AC_CHECK_HEADERS(\
|
|||
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 @@ AC_CHECK_HEADERS([sys/mount.h sys/statfs.h sys/user.h sys/vfs.h],,,
|
|||
# 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>
|
||||
|
|
|
@ -336,7 +336,9 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
|
|||
|
||||
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 @@ DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
|
|||
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;
|
||||
|
|
|
@ -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 @@ DWORD getUDPStats(MIB_UDPSTATS *stats)
|
|||
|
||||
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 @@ static DWORD getNumWithOneHeader(const char *filename)
|
|||
ERR ("Unable to open '%s' to count entries!\n", filename);
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD getNumRoutes(void)
|
||||
|
@ -1026,132 +1139,209 @@ DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ DWORD getNumTcpEntries(void);
|
|||
/* 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_ */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue