iphlpapi: Implement GetIpStatisticsEx() on top of nsi.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a784950260
commit
91494ae6f2
|
@ -2436,6 +2436,88 @@ err:
|
|||
return err;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* GetIpStatistics (IPHLPAPI.@)
|
||||
*
|
||||
* Get the IP statistics for the local computer.
|
||||
*
|
||||
* PARAMS
|
||||
* stats [Out] buffer for IP statistics
|
||||
*
|
||||
* RETURNS
|
||||
* Success: NO_ERROR
|
||||
* Failure: error code from winerror.h
|
||||
*/
|
||||
DWORD WINAPI GetIpStatistics( MIB_IPSTATS *stats )
|
||||
{
|
||||
return GetIpStatisticsEx( stats, WS_AF_INET );
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* GetIpStatisticsEx (IPHLPAPI.@)
|
||||
*
|
||||
* Get the IPv4 and IPv6 statistics for the local computer.
|
||||
*
|
||||
* PARAMS
|
||||
* stats [Out] buffer for IP statistics
|
||||
* family [In] specifies whether IPv4 or IPv6 statistics are returned
|
||||
*
|
||||
* RETURNS
|
||||
* Success: NO_ERROR
|
||||
* Failure: error code from winerror.h
|
||||
*/
|
||||
DWORD WINAPI GetIpStatisticsEx( MIB_IPSTATS *stats, DWORD family )
|
||||
{
|
||||
struct nsi_ip_ipstats_dynamic dyn;
|
||||
struct nsi_ip_ipstats_static stat;
|
||||
struct nsi_ip_cmpt_rw cmpt_rw;
|
||||
struct nsi_ip_cmpt_dynamic cmpt_dyn;
|
||||
const NPI_MODULEID *mod;
|
||||
DWORD err, cmpt = 1;
|
||||
|
||||
TRACE( "%p %d\n", stats, family );
|
||||
|
||||
if (!stats) return ERROR_INVALID_PARAMETER;
|
||||
mod = ip_module_id( family );
|
||||
if (!mod) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
memset( stats, 0, sizeof(*stats) );
|
||||
|
||||
err = NsiGetAllParameters( 1, mod, NSI_IP_IPSTATS_TABLE, NULL, 0, NULL, 0,
|
||||
&dyn, sizeof(dyn), &stat, sizeof(stat) );
|
||||
if (err) return err;
|
||||
|
||||
err = NsiGetAllParameters( 1, mod, NSI_IP_COMPARTMENT_TABLE, &cmpt, sizeof(cmpt), &cmpt_rw, sizeof(cmpt_rw),
|
||||
&cmpt_dyn, sizeof(cmpt_dyn), NULL, 0 );
|
||||
if (err) return err;
|
||||
|
||||
stats->u.Forwarding = cmpt_rw.not_forwarding + 1;
|
||||
stats->dwDefaultTTL = cmpt_rw.default_ttl;
|
||||
stats->dwInReceives = dyn.in_recv;
|
||||
stats->dwInHdrErrors = dyn.in_hdr_errs;
|
||||
stats->dwInAddrErrors = dyn.in_addr_errs;
|
||||
stats->dwForwDatagrams = dyn.fwd_dgrams;
|
||||
stats->dwInUnknownProtos = dyn.in_unk_protos;
|
||||
stats->dwInDiscards = dyn.in_discards;
|
||||
stats->dwInDelivers = dyn.in_delivers;
|
||||
stats->dwOutRequests = dyn.out_reqs;
|
||||
stats->dwRoutingDiscards = dyn.routing_discards;
|
||||
stats->dwOutDiscards = dyn.out_discards;
|
||||
stats->dwOutNoRoutes = dyn.out_no_routes;
|
||||
stats->dwReasmTimeout = stat.reasm_timeout;
|
||||
stats->dwReasmReqds = dyn.reasm_reqds;
|
||||
stats->dwReasmOks = dyn.reasm_oks;
|
||||
stats->dwReasmFails = dyn.reasm_fails;
|
||||
stats->dwFragOks = dyn.frag_oks;
|
||||
stats->dwFragFails = dyn.frag_fails;
|
||||
stats->dwFragCreates = dyn.frag_creates;
|
||||
stats->dwNumIf = cmpt_dyn.num_ifs;
|
||||
stats->dwNumAddr = cmpt_dyn.num_addrs;
|
||||
stats->dwNumRoutes = cmpt_dyn.num_routes;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Gets the DNS server list into the list beginning at list. Assumes that
|
||||
* a single server address may be placed at list if *len is at least
|
||||
* sizeof(IP_ADDR_STRING) long. Otherwise, list->Next is set to firstDynamic,
|
||||
|
|
|
@ -617,258 +617,6 @@ DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX stats, DWORD family)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* GetIpStatisticsEx (IPHLPAPI.@)
|
||||
*
|
||||
* Get the IPv4 and IPv6 statistics for the local computer.
|
||||
*
|
||||
* PARAMS
|
||||
* stats [Out] buffer for IP statistics
|
||||
* family [In] specifies whether IPv4 or IPv6 statistics are returned
|
||||
*
|
||||
* RETURNS
|
||||
* Success: NO_ERROR
|
||||
* Failure: error code from winerror.h
|
||||
*/
|
||||
DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS stats, DWORD family)
|
||||
{
|
||||
DWORD ret = ERROR_NOT_SUPPORTED;
|
||||
MIB_IPFORWARDTABLE *fwd_table;
|
||||
|
||||
if (!stats) return ERROR_INVALID_PARAMETER;
|
||||
if (family != WS_AF_INET && family != WS_AF_INET6) return ERROR_INVALID_PARAMETER;
|
||||
memset( stats, 0, sizeof(*stats) );
|
||||
|
||||
stats->dwNumIf = stats->dwNumAddr = get_interface_indices( FALSE, NULL );
|
||||
if (!AllocateAndGetIpForwardTableFromStack( &fwd_table, FALSE, GetProcessHeap(), 0 ))
|
||||
{
|
||||
stats->dwNumRoutes = fwd_table->dwNumEntries;
|
||||
HeapFree( GetProcessHeap(), 0, fwd_table );
|
||||
}
|
||||
|
||||
if (family == WS_AF_INET6)
|
||||
{
|
||||
#ifdef __linux__
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen("/proc/net/snmp6", "r")))
|
||||
{
|
||||
struct {
|
||||
const char *name;
|
||||
DWORD *elem;
|
||||
} ipstatlist[] = {
|
||||
{ "Ip6InReceives", &stats->dwInReceives },
|
||||
{ "Ip6InHdrErrors", &stats->dwInHdrErrors },
|
||||
{ "Ip6InAddrErrors", &stats->dwInAddrErrors },
|
||||
{ "Ip6OutForwDatagrams", &stats->dwForwDatagrams },
|
||||
{ "Ip6InUnknownProtos", &stats->dwInUnknownProtos },
|
||||
{ "Ip6InDiscards", &stats->dwInDiscards },
|
||||
{ "Ip6InDelivers", &stats->dwInDelivers },
|
||||
{ "Ip6OutRequests", &stats->dwOutRequests },
|
||||
{ "Ip6OutDiscards", &stats->dwOutDiscards },
|
||||
{ "Ip6OutNoRoutes", &stats->dwOutNoRoutes },
|
||||
{ "Ip6ReasmTimeout", &stats->dwReasmTimeout },
|
||||
{ "Ip6ReasmReqds", &stats->dwReasmReqds },
|
||||
{ "Ip6ReasmOKs", &stats->dwReasmOks },
|
||||
{ "Ip6ReasmFails", &stats->dwReasmFails },
|
||||
{ "Ip6FragOKs", &stats->dwFragOks },
|
||||
{ "Ip6FragFails", &stats->dwFragFails },
|
||||
{ "Ip6FragCreates", &stats->dwFragCreates },
|
||||
/* hmm, no routingDiscards, defaultTTL and forwarding? */
|
||||
};
|
||||
char buf[512], *ptr, *value;
|
||||
DWORD res, i;
|
||||
|
||||
while ((ptr = fgets(buf, sizeof(buf), fp)))
|
||||
{
|
||||
if (!(value = strchr(buf, ' ')))
|
||||
continue;
|
||||
|
||||
/* terminate the valuename */
|
||||
ptr = value - 1;
|
||||
*(ptr + 1) = '\0';
|
||||
|
||||
/* and strip leading spaces from value */
|
||||
value += 1;
|
||||
while (*value==' ') value++;
|
||||
if ((ptr = strchr(value, '\n')))
|
||||
*ptr='\0';
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ipstatlist); i++)
|
||||
if (!_strnicmp(buf, ipstatlist[i].name, -1) && sscanf(value, "%d", &res))
|
||||
*ipstatlist[i].elem = res;
|
||||
}
|
||||
fclose(fp);
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
}
|
||||
#else
|
||||
FIXME( "unimplemented for IPv6\n" );
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen("/proc/net/snmp", "r")))
|
||||
{
|
||||
static const char hdr[] = "Ip:";
|
||||
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",
|
||||
&stats->u.dwForwarding,
|
||||
&stats->dwDefaultTTL,
|
||||
&stats->dwInReceives,
|
||||
&stats->dwInHdrErrors,
|
||||
&stats->dwInAddrErrors,
|
||||
&stats->dwForwDatagrams,
|
||||
&stats->dwInUnknownProtos,
|
||||
&stats->dwInDiscards,
|
||||
&stats->dwInDelivers,
|
||||
&stats->dwOutRequests,
|
||||
&stats->dwOutDiscards,
|
||||
&stats->dwOutNoRoutes,
|
||||
&stats->dwReasmTimeout,
|
||||
&stats->dwReasmReqds,
|
||||
&stats->dwReasmOks,
|
||||
&stats->dwReasmFails,
|
||||
&stats->dwFragOks,
|
||||
&stats->dwFragFails,
|
||||
&stats->dwFragCreates );
|
||||
/* hmm, no routingDiscards */
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_LIBKSTAT)
|
||||
{
|
||||
static char ip[] = "ip";
|
||||
kstat_ctl_t *kc;
|
||||
kstat_t *ksp;
|
||||
|
||||
if ((kc = kstat_open()) &&
|
||||
(ksp = kstat_lookup( kc, ip, 0, ip )) &&
|
||||
kstat_read( kc, ksp, NULL ) != -1 &&
|
||||
ksp->ks_type == KSTAT_TYPE_NAMED)
|
||||
{
|
||||
stats->u.dwForwarding = kstat_get_ui32( ksp, "forwarding" );
|
||||
stats->dwDefaultTTL = kstat_get_ui32( ksp, "defaultTTL" );
|
||||
stats->dwInReceives = kstat_get_ui32( ksp, "inReceives" );
|
||||
stats->dwInHdrErrors = kstat_get_ui32( ksp, "inHdrErrors" );
|
||||
stats->dwInAddrErrors = kstat_get_ui32( ksp, "inAddrErrors" );
|
||||
stats->dwForwDatagrams = kstat_get_ui32( ksp, "forwDatagrams" );
|
||||
stats->dwInUnknownProtos = kstat_get_ui32( ksp, "inUnknownProtos" );
|
||||
stats->dwInDiscards = kstat_get_ui32( ksp, "inDiscards" );
|
||||
stats->dwInDelivers = kstat_get_ui32( ksp, "inDelivers" );
|
||||
stats->dwOutRequests = kstat_get_ui32( ksp, "outRequests" );
|
||||
stats->dwRoutingDiscards = kstat_get_ui32( ksp, "routingDiscards" );
|
||||
stats->dwOutDiscards = kstat_get_ui32( ksp, "outDiscards" );
|
||||
stats->dwOutNoRoutes = kstat_get_ui32( ksp, "outNoRoutes" );
|
||||
stats->dwReasmTimeout = kstat_get_ui32( ksp, "reasmTimeout" );
|
||||
stats->dwReasmReqds = kstat_get_ui32( ksp, "reasmReqds" );
|
||||
stats->dwReasmOks = kstat_get_ui32( ksp, "reasmOKs" );
|
||||
stats->dwReasmFails = kstat_get_ui32( ksp, "reasmFails" );
|
||||
stats->dwFragOks = kstat_get_ui32( ksp, "fragOKs" );
|
||||
stats->dwFragFails = kstat_get_ui32( ksp, "fragFails" );
|
||||
stats->dwFragCreates = kstat_get_ui32( ksp, "fragCreates" );
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
if (kc) kstat_close( kc );
|
||||
}
|
||||
#elif defined(HAVE_SYS_SYSCTL_H) && defined(IPCTL_STATS) && (defined(HAVE_STRUCT_IPSTAT_IPS_TOTAL) || defined(HAVE_STRUCT_IP_STATS_IPS_TOTAL))
|
||||
{
|
||||
int mib[] = {CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS};
|
||||
int ip_ttl, ip_forwarding;
|
||||
#if defined(HAVE_STRUCT_IPSTAT_IPS_TOTAL)
|
||||
struct ipstat ip_stat;
|
||||
#elif defined(HAVE_STRUCT_IP_STATS_IPS_TOTAL)
|
||||
struct ip_stats ip_stat;
|
||||
#endif
|
||||
size_t needed;
|
||||
|
||||
needed = sizeof(ip_stat);
|
||||
if(sysctl(mib, ARRAY_SIZE(mib), &ip_stat, &needed, NULL, 0) == -1)
|
||||
{
|
||||
ERR ("failed to get ipstat\n");
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
needed = sizeof(ip_ttl);
|
||||
if (sysctlbyname ("net.inet.ip.ttl", &ip_ttl, &needed, NULL, 0) == -1)
|
||||
{
|
||||
ERR ("failed to get ip Default TTL\n");
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
needed = sizeof(ip_forwarding);
|
||||
if (sysctlbyname ("net.inet.ip.forwarding", &ip_forwarding, &needed, NULL, 0) == -1)
|
||||
{
|
||||
ERR ("failed to get ip forwarding\n");
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* ip.forwarding is 0 or 1 on BSD */
|
||||
stats->u.dwForwarding = ip_forwarding+1;
|
||||
stats->dwDefaultTTL = ip_ttl;
|
||||
stats->dwInReceives = ip_stat.ips_total;
|
||||
stats->dwInHdrErrors = ip_stat.ips_badhlen + ip_stat.ips_badsum + ip_stat.ips_tooshort + ip_stat.ips_badlen +
|
||||
ip_stat.ips_badvers + ip_stat.ips_badoptions;
|
||||
/* ips_badaddr also includes outgoing packets with a bad address, but we can't account for that right now */
|
||||
stats->dwInAddrErrors = ip_stat.ips_cantforward + ip_stat.ips_badaddr + ip_stat.ips_notmember;
|
||||
stats->dwForwDatagrams = ip_stat.ips_forward;
|
||||
stats->dwInUnknownProtos = ip_stat.ips_noproto;
|
||||
stats->dwInDiscards = ip_stat.ips_fragdropped;
|
||||
stats->dwInDelivers = ip_stat.ips_delivered;
|
||||
stats->dwOutRequests = ip_stat.ips_localout;
|
||||
/*stats->dwRoutingDiscards = 0;*/ /* FIXME */
|
||||
stats->dwOutDiscards = ip_stat.ips_odropped;
|
||||
stats->dwOutNoRoutes = ip_stat.ips_noroute;
|
||||
stats->dwReasmTimeout = ip_stat.ips_fragtimeout;
|
||||
stats->dwReasmReqds = ip_stat.ips_fragments;
|
||||
stats->dwReasmOks = ip_stat.ips_reassembled;
|
||||
stats->dwReasmFails = ip_stat.ips_fragments - ip_stat.ips_reassembled;
|
||||
stats->dwFragOks = ip_stat.ips_fragmented;
|
||||
stats->dwFragFails = ip_stat.ips_cantfrag;
|
||||
stats->dwFragCreates = ip_stat.ips_ofragments;
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
#else
|
||||
FIXME( "unimplemented for IPv4\n" );
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* GetIpStatistics (IPHLPAPI.@)
|
||||
*
|
||||
* Get the IP statistics for the local computer.
|
||||
*
|
||||
* PARAMS
|
||||
* stats [Out] buffer for IP statistics
|
||||
*
|
||||
* RETURNS
|
||||
* Success: NO_ERROR
|
||||
* Failure: error code from winerror.h
|
||||
*/
|
||||
DWORD WINAPI GetIpStatistics(PMIB_IPSTATS stats)
|
||||
{
|
||||
return GetIpStatisticsEx(stats, WS_AF_INET);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* GetTcpStatisticsEx (IPHLPAPI.@)
|
||||
*
|
||||
|
|
|
@ -436,14 +436,10 @@ static void test_ip_cmpt( int family )
|
|||
ok( !err, "got %d\n", err );
|
||||
if (err) goto err;
|
||||
|
||||
todo_wine_if(family == AF_INET6 && table.dwForwarding - 1 != rw.not_forwarding)
|
||||
ok( table.dwForwarding - 1 == rw.not_forwarding, "%x vs %x\n", table.dwForwarding, rw.not_forwarding );
|
||||
todo_wine_if(family == AF_INET6 && table.dwDefaultTTL != rw.default_ttl)
|
||||
ok( table.dwDefaultTTL == rw.default_ttl, "%x vs %x\n", table.dwDefaultTTL, rw.default_ttl );
|
||||
ok( table.dwNumIf == dyn.num_ifs, "%x vs %x\n", table.dwNumIf, dyn.num_ifs );
|
||||
todo_wine_if(table.dwNumAddr != dyn.num_addrs)
|
||||
ok( table.dwNumAddr == dyn.num_addrs, "%x vs %x\n", table.dwNumAddr, dyn.num_addrs );
|
||||
todo_wine_if(family == AF_INET6 && table.dwNumRoutes != dyn.num_routes)
|
||||
ok( table.dwNumRoutes == dyn.num_routes, "%x vs %x\n", table.dwNumRoutes, dyn.num_routes );
|
||||
|
||||
err:
|
||||
|
|
Loading…
Reference in New Issue