iphlpapi: Implement GetIcmpStatistics() on top of GetIcmpStatisticsEx().

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2021-08-12 10:38:17 +01:00 committed by Alexandre Julliard
parent 1cc49258f7
commit 5b99e791ce
2 changed files with 41 additions and 170 deletions

View File

@ -1495,6 +1495,47 @@ DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
return IfIndex;
}
static void icmp_stats_ex_to_icmp_stats( MIBICMPSTATS_EX *stats_ex, MIBICMPSTATS *stats )
{
stats->dwMsgs = stats_ex->dwMsgs;
stats->dwErrors = stats_ex->dwErrors;
stats->dwDestUnreachs = stats_ex->rgdwTypeCount[ICMP4_DST_UNREACH];
stats->dwTimeExcds = stats_ex->rgdwTypeCount[ICMP4_TIME_EXCEEDED];
stats->dwParmProbs = stats_ex->rgdwTypeCount[ICMP4_PARAM_PROB];
stats->dwSrcQuenchs = stats_ex->rgdwTypeCount[ICMP4_SOURCE_QUENCH];
stats->dwRedirects = stats_ex->rgdwTypeCount[ICMP4_REDIRECT];
stats->dwEchos = stats_ex->rgdwTypeCount[ICMP4_ECHO_REQUEST];
stats->dwEchoReps = stats_ex->rgdwTypeCount[ICMP4_ECHO_REPLY];
stats->dwTimestamps = stats_ex->rgdwTypeCount[ICMP4_TIMESTAMP_REQUEST];
stats->dwTimestampReps = stats_ex->rgdwTypeCount[ICMP4_TIMESTAMP_REPLY];
stats->dwAddrMasks = stats_ex->rgdwTypeCount[ICMP4_MASK_REQUEST];
stats->dwAddrMaskReps = stats_ex->rgdwTypeCount[ICMP4_MASK_REPLY];
}
/******************************************************************
* GetIcmpStatistics (IPHLPAPI.@)
*
* Get the ICMP statistics for the local computer.
*
* PARAMS
* stats [Out] buffer for ICMP statistics
*
* RETURNS
* Success: NO_ERROR
* Failure: error code from winerror.h
*/
DWORD WINAPI GetIcmpStatistics( MIB_ICMP *stats )
{
MIB_ICMP_EX stats_ex;
DWORD err = GetIcmpStatisticsEx( &stats_ex, WS_AF_INET );
if (err) return err;
icmp_stats_ex_to_icmp_stats( &stats_ex.icmpInStats, &stats->stats.icmpInStats );
icmp_stats_ex_to_icmp_stats( &stats_ex.icmpOutStats, &stats->stats.icmpOutStats );
return err;
}
/******************************************************************
* GetIcmpStatisticsEx (IPHLPAPI.@)
*

View File

@ -276,176 +276,6 @@ static void *read_mib_entry( int fd, int level, int name, int *len )
}
#endif /* HAVE_SYS_TIHDR_H && T_OPTMGMT_ACK */
/******************************************************************
* GetIcmpStatistics (IPHLPAPI.@)
*
* Get the ICMP statistics for the local computer.
*
* PARAMS
* stats [Out] buffer for ICMP statistics
*
* RETURNS
* Success: NO_ERROR
* Failure: error code from winerror.h
*/
DWORD WINAPI GetIcmpStatistics(PMIB_ICMP stats)
{
DWORD ret = ERROR_NOT_SUPPORTED;
if (!stats) return ERROR_INVALID_PARAMETER;
memset( stats, 0, sizeof(MIB_ICMP) );
#ifdef __linux__
{
FILE *fp;
if ((fp = fopen("/proc/net/snmp", "r")))
{
static const char hdr[] = "Icmp:";
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 %u %u %u %u %u %u %u %u %u %u %u %u %u",
&stats->stats.icmpInStats.dwMsgs,
&stats->stats.icmpInStats.dwErrors,
&stats->stats.icmpInStats.dwDestUnreachs,
&stats->stats.icmpInStats.dwTimeExcds,
&stats->stats.icmpInStats.dwParmProbs,
&stats->stats.icmpInStats.dwSrcQuenchs,
&stats->stats.icmpInStats.dwRedirects,
&stats->stats.icmpInStats.dwEchos,
&stats->stats.icmpInStats.dwEchoReps,
&stats->stats.icmpInStats.dwTimestamps,
&stats->stats.icmpInStats.dwTimestampReps,
&stats->stats.icmpInStats.dwAddrMasks,
&stats->stats.icmpInStats.dwAddrMaskReps,
&stats->stats.icmpOutStats.dwMsgs,
&stats->stats.icmpOutStats.dwErrors,
&stats->stats.icmpOutStats.dwDestUnreachs,
&stats->stats.icmpOutStats.dwTimeExcds,
&stats->stats.icmpOutStats.dwParmProbs,
&stats->stats.icmpOutStats.dwSrcQuenchs,
&stats->stats.icmpOutStats.dwRedirects,
&stats->stats.icmpOutStats.dwEchos,
&stats->stats.icmpOutStats.dwEchoReps,
&stats->stats.icmpOutStats.dwTimestamps,
&stats->stats.icmpOutStats.dwTimestampReps,
&stats->stats.icmpOutStats.dwAddrMasks,
&stats->stats.icmpOutStats.dwAddrMaskReps );
break;
}
}
fclose(fp);
ret = NO_ERROR;
}
}
#elif defined(HAVE_LIBKSTAT)
{
static char ip[] = "ip", icmp[] = "icmp";
kstat_ctl_t *kc;
kstat_t *ksp;
if ((kc = kstat_open()) &&
(ksp = kstat_lookup( kc, ip, 0, icmp )) &&
kstat_read( kc, ksp, NULL ) != -1 &&
ksp->ks_type == KSTAT_TYPE_NAMED)
{
stats->stats.icmpInStats.dwMsgs = kstat_get_ui32( ksp, "inMsgs" );
stats->stats.icmpInStats.dwErrors = kstat_get_ui32( ksp, "inErrors" );
stats->stats.icmpInStats.dwDestUnreachs = kstat_get_ui32( ksp, "inDestUnreachs" );
stats->stats.icmpInStats.dwTimeExcds = kstat_get_ui32( ksp, "inTimeExcds" );
stats->stats.icmpInStats.dwParmProbs = kstat_get_ui32( ksp, "inParmProbs" );
stats->stats.icmpInStats.dwSrcQuenchs = kstat_get_ui32( ksp, "inSrcQuenchs" );
stats->stats.icmpInStats.dwRedirects = kstat_get_ui32( ksp, "inRedirects" );
stats->stats.icmpInStats.dwEchos = kstat_get_ui32( ksp, "inEchos" );
stats->stats.icmpInStats.dwEchoReps = kstat_get_ui32( ksp, "inEchoReps" );
stats->stats.icmpInStats.dwTimestamps = kstat_get_ui32( ksp, "inTimestamps" );
stats->stats.icmpInStats.dwTimestampReps = kstat_get_ui32( ksp, "inTimestampReps" );
stats->stats.icmpInStats.dwAddrMasks = kstat_get_ui32( ksp, "inAddrMasks" );
stats->stats.icmpInStats.dwAddrMaskReps = kstat_get_ui32( ksp, "inAddrMaskReps" );
stats->stats.icmpOutStats.dwMsgs = kstat_get_ui32( ksp, "outMsgs" );
stats->stats.icmpOutStats.dwErrors = kstat_get_ui32( ksp, "outErrors" );
stats->stats.icmpOutStats.dwDestUnreachs = kstat_get_ui32( ksp, "outDestUnreachs" );
stats->stats.icmpOutStats.dwTimeExcds = kstat_get_ui32( ksp, "outTimeExcds" );
stats->stats.icmpOutStats.dwParmProbs = kstat_get_ui32( ksp, "outParmProbs" );
stats->stats.icmpOutStats.dwSrcQuenchs = kstat_get_ui32( ksp, "outSrcQuenchs" );
stats->stats.icmpOutStats.dwRedirects = kstat_get_ui32( ksp, "outRedirects" );
stats->stats.icmpOutStats.dwEchos = kstat_get_ui32( ksp, "outEchos" );
stats->stats.icmpOutStats.dwEchoReps = kstat_get_ui32( ksp, "outEchoReps" );
stats->stats.icmpOutStats.dwTimestamps = kstat_get_ui32( ksp, "outTimestamps" );
stats->stats.icmpOutStats.dwTimestampReps = kstat_get_ui32( ksp, "outTimestampReps" );
stats->stats.icmpOutStats.dwAddrMasks = kstat_get_ui32( ksp, "outAddrMasks" );
stats->stats.icmpOutStats.dwAddrMaskReps = kstat_get_ui32( ksp, "outAddrMaskReps" );
ret = NO_ERROR;
}
if (kc) kstat_close( kc );
}
#elif defined(HAVE_SYS_SYSCTL_H) && defined(ICMPCTL_STATS) && (defined(HAVE_STRUCT_ICMPSTAT_ICPS_INHIST) || defined(HAVE_STRUCT_ICMPSTAT_ICPS_OUTHIST))
{
int mib[] = {CTL_NET, PF_INET, IPPROTO_ICMP, ICMPCTL_STATS};
struct icmpstat icmp_stat;
size_t needed = sizeof(icmp_stat);
int i;
if(sysctl(mib, ARRAY_SIZE(mib), &icmp_stat, &needed, NULL, 0) != -1)
{
#ifdef HAVE_STRUCT_ICMPSTAT_ICPS_INHIST
/*in stats */
stats->stats.icmpInStats.dwMsgs = icmp_stat.icps_badcode + icmp_stat.icps_checksum + icmp_stat.icps_tooshort + icmp_stat.icps_badlen;
for(i = 0; i <= ICMP_MAXTYPE; i++)
stats->stats.icmpInStats.dwMsgs += icmp_stat.icps_inhist[i];
stats->stats.icmpInStats.dwErrors = icmp_stat.icps_badcode + icmp_stat.icps_tooshort + icmp_stat.icps_checksum + icmp_stat.icps_badlen;
stats->stats.icmpInStats.dwDestUnreachs = icmp_stat.icps_inhist[ICMP_UNREACH];
stats->stats.icmpInStats.dwTimeExcds = icmp_stat.icps_inhist[ICMP_TIMXCEED];
stats->stats.icmpInStats.dwParmProbs = icmp_stat.icps_inhist[ICMP_PARAMPROB];
stats->stats.icmpInStats.dwSrcQuenchs = icmp_stat.icps_inhist[ICMP_SOURCEQUENCH];
stats->stats.icmpInStats.dwRedirects = icmp_stat.icps_inhist[ICMP_REDIRECT];
stats->stats.icmpInStats.dwEchos = icmp_stat.icps_inhist[ICMP_ECHO];
stats->stats.icmpInStats.dwEchoReps = icmp_stat.icps_inhist[ICMP_ECHOREPLY];
stats->stats.icmpInStats.dwTimestamps = icmp_stat.icps_inhist[ICMP_TSTAMP];
stats->stats.icmpInStats.dwTimestampReps = icmp_stat.icps_inhist[ICMP_TSTAMPREPLY];
stats->stats.icmpInStats.dwAddrMasks = icmp_stat.icps_inhist[ICMP_MASKREQ];
stats->stats.icmpInStats.dwAddrMaskReps = icmp_stat.icps_inhist[ICMP_MASKREPLY];
#endif
#ifdef HAVE_STRUCT_ICMPSTAT_ICPS_OUTHIST
/* out stats */
stats->stats.icmpOutStats.dwMsgs = icmp_stat.icps_oldshort + icmp_stat.icps_oldicmp;
for(i = 0; i <= ICMP_MAXTYPE; i++)
stats->stats.icmpOutStats.dwMsgs += icmp_stat.icps_outhist[i];
stats->stats.icmpOutStats.dwErrors = icmp_stat.icps_oldshort + icmp_stat.icps_oldicmp;
stats->stats.icmpOutStats.dwDestUnreachs = icmp_stat.icps_outhist[ICMP_UNREACH];
stats->stats.icmpOutStats.dwTimeExcds = icmp_stat.icps_outhist[ICMP_TIMXCEED];
stats->stats.icmpOutStats.dwParmProbs = icmp_stat.icps_outhist[ICMP_PARAMPROB];
stats->stats.icmpOutStats.dwSrcQuenchs = icmp_stat.icps_outhist[ICMP_SOURCEQUENCH];
stats->stats.icmpOutStats.dwRedirects = icmp_stat.icps_outhist[ICMP_REDIRECT];
stats->stats.icmpOutStats.dwEchos = icmp_stat.icps_outhist[ICMP_ECHO];
stats->stats.icmpOutStats.dwEchoReps = icmp_stat.icps_outhist[ICMP_ECHOREPLY];
stats->stats.icmpOutStats.dwTimestamps = icmp_stat.icps_outhist[ICMP_TSTAMP];
stats->stats.icmpOutStats.dwTimestampReps = icmp_stat.icps_outhist[ICMP_TSTAMPREPLY];
stats->stats.icmpOutStats.dwAddrMasks = icmp_stat.icps_outhist[ICMP_MASKREQ];
stats->stats.icmpOutStats.dwAddrMaskReps = icmp_stat.icps_outhist[ICMP_MASKREPLY];
#endif /* HAVE_STRUCT_ICMPSTAT_ICPS_OUTHIST */
ret = NO_ERROR;
}
}
#else /* ICMPCTL_STATS */
FIXME( "unimplemented\n" );
#endif
return ret;
}
/******************************************************************
* GetTcpStatisticsEx (IPHLPAPI.@)
*