[PATCH 3/3] iphlpapi: Implement GetTcpStatisticsEx() on top of nsi.
Huw Davies
huw at codeweavers.com
Fri Aug 13 02:35:50 CDT 2021
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 62 +++++++++++++
dlls/iphlpapi/ipstats.c | 161 ---------------------------------
dlls/iphlpapi/tests/iphlpapi.c | 4 +-
dlls/nsi/tests/nsi.c | 3 -
4 files changed, 64 insertions(+), 166 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 14a2c719b95..b45bcc41724 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -2807,6 +2807,68 @@ BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHo
return FALSE;
}
+/******************************************************************
+ * GetTcpStatistics (IPHLPAPI.@)
+ *
+ * Get the TCP statistics for the local computer.
+ *
+ * PARAMS
+ * stats [Out] buffer for TCP statistics
+ *
+ * RETURNS
+ * Success: NO_ERROR
+ * Failure: error code from winerror.h
+ */
+DWORD WINAPI GetTcpStatistics( MIB_TCPSTATS *stats )
+{
+ return GetTcpStatisticsEx( stats, WS_AF_INET );
+}
+
+/******************************************************************
+ * GetTcpStatisticsEx (IPHLPAPI.@)
+ *
+ * Get the IPv4 and IPv6 TCP statistics for the local computer.
+ *
+ * PARAMS
+ * stats [Out] buffer for TCP statistics
+ * family [In] specifies whether IPv4 or IPv6 statistics are returned
+ *
+ * RETURNS
+ * Success: NO_ERROR
+ * Failure: error code from winerror.h
+ */
+DWORD WINAPI GetTcpStatisticsEx( MIB_TCPSTATS *stats, DWORD family )
+{
+ struct nsi_tcp_stats_dynamic dyn;
+ struct nsi_tcp_stats_static stat;
+ USHORT key = (USHORT)family;
+ DWORD err;
+
+ if (!stats || !ip_module_id( family )) return ERROR_INVALID_PARAMETER;
+ memset( stats, 0, sizeof(*stats) );
+
+ err = NsiGetAllParameters( 1, &NPI_MS_TCP_MODULEID, NSI_TCP_STATS_TABLE, &key, sizeof(key), NULL, 0,
+ &dyn, sizeof(dyn), &stat, sizeof(stat) );
+ if (err) return err;
+
+ stats->u.RtoAlgorithm = stat.rto_algo;
+ stats->dwRtoMin = stat.rto_min;
+ stats->dwRtoMax = stat.rto_max;
+ stats->dwMaxConn = stat.max_conns;
+ stats->dwActiveOpens = dyn.active_opens;
+ stats->dwPassiveOpens = dyn.passive_opens;
+ stats->dwAttemptFails = dyn.attempt_fails;
+ stats->dwEstabResets = dyn.est_rsts;
+ stats->dwCurrEstab = dyn.cur_est;
+ stats->dwInSegs = (DWORD)dyn.in_segs;
+ stats->dwOutSegs = (DWORD)dyn.out_segs;
+ stats->dwRetransSegs = dyn.retrans_segs;
+ stats->dwInErrs = dyn.in_errs;
+ stats->dwOutRsts = dyn.out_rsts;
+ stats->dwNumConns = dyn.num_conns;
+
+ return err;
+}
/******************************************************************
* GetTcpTable (IPHLPAPI.@)
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index c5621b52dd7..ececfcdcecd 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -276,167 +276,6 @@ static void *read_mib_entry( int fd, int level, int name, int *len )
}
#endif /* HAVE_SYS_TIHDR_H && T_OPTMGMT_ACK */
-/******************************************************************
- * GetTcpStatisticsEx (IPHLPAPI.@)
- *
- * Get the IPv4 and IPv6 TCP statistics for the local computer.
- *
- * PARAMS
- * stats [Out] buffer for TCP statistics
- * family [In] specifies whether IPv4 or IPv6 statistics are returned
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
- */
-DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS stats, DWORD family)
-{
- DWORD ret = ERROR_NOT_SUPPORTED;
-
- if (!stats) return ERROR_INVALID_PARAMETER;
- if (family != WS_AF_INET && family != WS_AF_INET6) return ERROR_INVALID_PARAMETER;
- memset( stats, 0, sizeof(*stats) );
-
- if (family == WS_AF_INET6)
- {
- FIXME( "unimplemented for IPv6\n" );
- return ret;
- }
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen("/proc/net/snmp", "r")))
- {
- static const char hdr[] = "Tcp:";
- MIB_TCPTABLE *tcp_table;
- char buf[512], *ptr;
-
- while ((ptr = fgets(buf, sizeof(buf), fp)))
- {
- if (_strnicmp(buf, hdr, sizeof(hdr) - 1)) continue;
- /* last line was a header, get another */
- if (!(ptr = fgets(buf, sizeof(buf), fp))) break;
- if (!_strnicmp(buf, hdr, sizeof(hdr) - 1))
- {
- ptr += sizeof(hdr);
- sscanf( ptr, "%u %u %u %u %u %u %u %u %u %u %u %u %u %u",
- &stats->u.dwRtoAlgorithm,
- &stats->dwRtoMin,
- &stats->dwRtoMax,
- &stats->dwMaxConn,
- &stats->dwActiveOpens,
- &stats->dwPassiveOpens,
- &stats->dwAttemptFails,
- &stats->dwEstabResets,
- &stats->dwCurrEstab,
- &stats->dwInSegs,
- &stats->dwOutSegs,
- &stats->dwRetransSegs,
- &stats->dwInErrs,
- &stats->dwOutRsts );
- break;
- }
- }
- if (!AllocateAndGetTcpTableFromStack( &tcp_table, FALSE, GetProcessHeap(), 0 ))
- {
- stats->dwNumConns = tcp_table->dwNumEntries;
- HeapFree( GetProcessHeap(), 0, tcp_table );
- }
- fclose(fp);
- ret = NO_ERROR;
- }
- }
-#elif defined(HAVE_LIBKSTAT)
- {
- static char tcp[] = "tcp";
- kstat_ctl_t *kc;
- kstat_t *ksp;
-
- if ((kc = kstat_open()) &&
- (ksp = kstat_lookup( kc, tcp, 0, tcp )) &&
- kstat_read( kc, ksp, NULL ) != -1 &&
- ksp->ks_type == KSTAT_TYPE_NAMED)
- {
- stats->u.dwRtoAlgorithm = kstat_get_ui32( ksp, "rtoAlgorithm" );
- stats->dwRtoMin = kstat_get_ui32( ksp, "rtoMin" );
- stats->dwRtoMax = kstat_get_ui32( ksp, "rtoMax" );
- stats->dwMaxConn = kstat_get_ui32( ksp, "maxConn" );
- stats->dwActiveOpens = kstat_get_ui32( ksp, "activeOpens" );
- stats->dwPassiveOpens = kstat_get_ui32( ksp, "passiveOpens" );
- stats->dwAttemptFails = kstat_get_ui32( ksp, "attemptFails" );
- stats->dwEstabResets = kstat_get_ui32( ksp, "estabResets" );
- stats->dwCurrEstab = kstat_get_ui32( ksp, "currEstab" );
- stats->dwInSegs = kstat_get_ui32( ksp, "inSegs" );
- stats->dwOutSegs = kstat_get_ui32( ksp, "outSegs" );
- stats->dwRetransSegs = kstat_get_ui32( ksp, "retransSegs" );
- stats->dwInErrs = kstat_get_ui32( ksp, "inErrs" );
- stats->dwOutRsts = kstat_get_ui32( ksp, "outRsts" );
- stats->dwNumConns = kstat_get_ui32( ksp, "connTableSize" );
- ret = NO_ERROR;
- }
- if (kc) kstat_close( kc );
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(TCPCTL_STATS) && (defined(HAVE_STRUCT_TCPSTAT_TCPS_CONNATTEMPT) || defined(HAVE_STRUCT_TCP_STATS_TCPS_CONNATTEMPT))
- {
-#ifndef TCPTV_MIN /* got removed in Mac OS X for some reason */
-#define TCPTV_MIN 2
-#define TCPTV_REXMTMAX 128
-#endif
- int mib[] = {CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS};
-#define hz 1000
-#if defined(HAVE_STRUCT_TCPSTAT_TCPS_CONNATTEMPT)
- struct tcpstat tcp_stat;
-#elif defined(HAVE_STRUCT_TCP_STATS_TCPS_CONNATTEMPT)
- struct tcp_stats tcp_stat;
-#endif
- size_t needed = sizeof(tcp_stat);
-
- if(sysctl(mib, ARRAY_SIZE(mib), &tcp_stat, &needed, NULL, 0) != -1)
- {
- stats->u.RtoAlgorithm = MIB_TCP_RTO_VANJ;
- stats->dwRtoMin = TCPTV_MIN;
- stats->dwRtoMax = TCPTV_REXMTMAX;
- stats->dwMaxConn = -1;
- stats->dwActiveOpens = tcp_stat.tcps_connattempt;
- stats->dwPassiveOpens = tcp_stat.tcps_accepts;
- stats->dwAttemptFails = tcp_stat.tcps_conndrops;
- stats->dwEstabResets = tcp_stat.tcps_drops;
- stats->dwCurrEstab = 0;
- stats->dwInSegs = tcp_stat.tcps_rcvtotal;
- stats->dwOutSegs = tcp_stat.tcps_sndtotal - tcp_stat.tcps_sndrexmitpack;
- stats->dwRetransSegs = tcp_stat.tcps_sndrexmitpack;
- stats->dwInErrs = tcp_stat.tcps_rcvbadsum + tcp_stat.tcps_rcvbadoff + tcp_stat.tcps_rcvmemdrop + tcp_stat.tcps_rcvshort;
- stats->dwOutRsts = tcp_stat.tcps_sndctrl - tcp_stat.tcps_closed;
- stats->dwNumConns = tcp_stat.tcps_connects;
- ret = NO_ERROR;
- }
- else ERR ("failed to get tcpstat\n");
- }
-#else
- FIXME( "unimplemented\n" );
-#endif
- return ret;
-}
-
-/******************************************************************
- * GetTcpStatistics (IPHLPAPI.@)
- *
- * Get the TCP statistics for the local computer.
- *
- * PARAMS
- * stats [Out] buffer for TCP statistics
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
- */
-DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS stats)
-{
- return GetTcpStatisticsEx(stats, WS_AF_INET);
-}
-
/******************************************************************
* GetUdpStatistics (IPHLPAPI.@)
*
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index d439f71069b..5ec2f2eaba2 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -715,8 +715,8 @@ static void testGetTcpStatisticsEx(void)
}
apiReturn = GetTcpStatisticsEx(&stats, AF_INET6);
- todo_wine ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
- "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
+ ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
+ "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
if (apiReturn == NO_ERROR && winetest_debug > 1)
{
trace( "TCP IPv6 Ex stats:\n" );
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index fb95ab67d3b..33b4e9e6d97 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -815,9 +815,7 @@ static void test_tcp_stats( int family )
ok( !err, "got %x\n", err );
err = GetTcpStatisticsEx( &table, family );
-todo_wine_if(family == AF_INET6)
ok( !err, "got %d\n", err );
- if (err) goto err;
err = NsiGetAllParameters( 1, &NPI_MS_TCP_MODULEID, NSI_TCP_STATS_TABLE, &key, sizeof(key), NULL, 0,
&dyn2, sizeof(dyn), NULL, 0 );
@@ -847,7 +845,6 @@ todo_wine_if(family == AF_INET6)
table.dwOutRsts, dyn.out_rsts, dyn2.out_rsts );
ok( unstable( table.dwNumConns == dyn.num_conns ), "%d vs %d\n", table.dwNumConns, dyn.num_conns );
-err:
winetest_pop_context();
}
--
2.23.0
More information about the wine-devel
mailing list