[PATCH 4/4] iphlpapi: Implement GetIpStatisticsEx() on top of nsi.

Huw Davies huw at codeweavers.com
Wed Aug 11 05:01:31 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/iphlpapi/iphlpapi_main.c |  82 +++++++++++
 dlls/iphlpapi/ipstats.c       | 252 ----------------------------------
 dlls/nsi/tests/nsi.c          |   4 -
 3 files changed, 82 insertions(+), 256 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index fe2daa0f24d..78f4c582e1a 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -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,
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 115bafa6f8e..8335e4871c1 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -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.@)
  *
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index 598e7124afd..7d9d8e12bac 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -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:
-- 
2.23.0




More information about the wine-devel mailing list