[1/4] iphlpapi: Implement GetIpStatisticsEx on Linux

André Hentschel nerv at dawncrow.de
Wed Sep 19 16:48:59 CDT 2012


---
 dlls/iphlpapi/iphlpapi.spec    |    2 +-
 dlls/iphlpapi/ipstats.c        |   92 ++++++++++++++++++++++++++++++++++++++--
 dlls/iphlpapi/tests/iphlpapi.c |    6 ++-
 3 files changed, 94 insertions(+), 6 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec
index cadb247..1bf4a71 100644
--- a/dlls/iphlpapi/iphlpapi.spec
+++ b/dlls/iphlpapi/iphlpapi.spec
@@ -112,7 +112,7 @@
 @ stub GetIpNetTableFromStack
 #@ stub GetIpPathEntry
 #@ stub GetIpPathTable
-#@ stub GetIpStatisticsEx
+@ stdcall GetIpStatisticsEx( ptr long )
 @ stdcall GetIpStatistics( ptr )
 @ stub GetIpStatsFromStack
 #@ stub GetMulticastIpAddressEntry
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 7c64b41..65c070d 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -553,23 +553,25 @@ DWORD WINAPI GetIcmpStatistics(PMIB_ICMP stats)
 
 
 /******************************************************************
- *    GetIpStatistics (IPHLPAPI.@)
+ *    GetIpStatisticsEx (IPHLPAPI.@)
  *
- * Get the IP statistics for the local computer.
+ * Get the IPv4 and IPv6 statistics for the local computer.
  *
  * PARAMS
  *  stats [Out] buffer for IP statistics
+ *  family [In] specifies wether IPv4 or IPv6 statistics are returned
  *
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
  */
-DWORD WINAPI GetIpStatistics(PMIB_IPSTATS stats)
+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 = getNumInterfaces();
@@ -579,6 +581,72 @@ DWORD WINAPI GetIpStatistics(PMIB_IPSTATS stats)
         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 < sizeof(ipstatlist)/sizeof(ipstatlist[0]); i++)
+                        if (!strcasecmp(buf, ipstatlist[i].name))
+                        {
+                            if (sscanf(value, "%d", &res)) *ipstatlist[i].elem = res;
+                            continue;
+                        }
+                }
+                fclose(fp);
+                ret = NO_ERROR;
+            }
+        }
+#else
+        FIXME( "unimplemented for IPv6\n" );
+#endif
+        return ret;
+    }
+
 #ifdef __linux__
     {
         FILE *fp;
@@ -712,11 +780,27 @@ DWORD WINAPI GetIpStatistics(PMIB_IPSTATS stats)
         ret = NO_ERROR;
     }
 #else
-    FIXME( "unimplemented\n" );
+    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);
+}
 
 /******************************************************************
  *    GetTcpStatistics (IPHLPAPI.@)
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index 638d7e5..1c0e2cc 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -574,7 +574,7 @@ static void testGetIpStatisticsEx(void)
 
     if (!pGetIpStatisticsEx)
     {
-        skip( "GetIpStatisticsEx not available\n" );
+        win_skip( "GetIpStatisticsEx not available\n" );
         return;
     }
 
@@ -582,6 +582,10 @@ static void testGetIpStatisticsEx(void)
     ok(apiReturn == ERROR_INVALID_PARAMETER,
        "GetIpStatisticsEx(NULL, AF_INET) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
 
+    apiReturn = pGetIpStatisticsEx(&stats, AF_BAN);
+    ok(apiReturn == ERROR_INVALID_PARAMETER,
+       "GetIpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
+
     apiReturn = pGetIpStatisticsEx(&stats, AF_INET);
     ok(apiReturn == NO_ERROR, "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
-- 
1.7.4.1



-- 

Best Regards, André Hentschel


More information about the wine-patches mailing list