=?UTF-8?Q?Andr=C3=A9=20Hentschel=20?=: iphlpapi: Implement GetUdpStatisticsEx on Linux.

Alexandre Julliard julliard at winehq.org
Thu Sep 20 15:05:37 CDT 2012


Module: wine
Branch: master
Commit: 5e3cc410044eab23a0368389456cc32779948506
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5e3cc410044eab23a0368389456cc32779948506

Author: André Hentschel <nerv at dawncrow.de>
Date:   Wed Sep 19 23:52:30 2012 +0200

iphlpapi: Implement GetUdpStatisticsEx on Linux.

---

 dlls/iphlpapi/iphlpapi.spec    |    2 +-
 dlls/iphlpapi/ipstats.c        |   78 ++++++++++++++++++++++++++++++++++++++--
 dlls/iphlpapi/tests/iphlpapi.c |   22 +++++++-----
 3 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec
index 1bf4a71..d1cf196 100644
--- a/dlls/iphlpapi/iphlpapi.spec
+++ b/dlls/iphlpapi/iphlpapi.spec
@@ -142,7 +142,7 @@
 @ stub GetTcpTableFromStack
 #@ stub GetTeredoPort
 #@ stub GetUdp6Table
-#@ stub GetUdpStatisticsEx
+@ stdcall GetUdpStatisticsEx( ptr long )
 @ stdcall GetUdpStatistics( ptr )
 @ stub GetUdpStatsFromStack
 @ stdcall GetUdpTable( ptr ptr long )
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 65c070d..f314745 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -943,22 +943,78 @@ DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS stats)
 /******************************************************************
  *    GetUdpStatistics (IPHLPAPI.@)
  *
- * Get the UDP statistics for the local computer.
+ * Get the IPv4 and IPv6 UDP statistics for the local computer.
  *
  * PARAMS
  *  stats [Out] buffer for UDP statistics
+ *  family [In] specifies wether IPv4 or IPv6 statistics are returned
  *
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
  */
-DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
+DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS 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) );
 
+    stats->dwNumAddrs = getNumInterfaces();
+
+    if (family == WS_AF_INET6)
+    {
+#ifdef __linux__
+        {
+            FILE *fp;
+
+            if ((fp = fopen("/proc/net/snmp6", "r")))
+            {
+                struct {
+                    const char *name;
+                    DWORD *elem;
+                } udpstatlist[] = {
+                    { "Udp6InDatagrams",  &stats->dwInDatagrams },
+                    { "Udp6NoPorts",      &stats->dwNoPorts },
+                    { "Udp6InErrors",     &stats->dwInErrors },
+                    { "Udp6OutDatagrams", &stats->dwOutDatagrams },
+                };
+                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(udpstatlist)/sizeof(udpstatlist[0]); i++)
+                        if (!strcasecmp(buf, udpstatlist[i].name))
+                        {
+                            if (sscanf(value, "%d", &res)) *udpstatlist[i].elem = res;
+                            continue;
+                        }
+                }
+                fclose(fp);
+                ret = NO_ERROR;
+            }
+        }
+#else
+        FIXME( "unimplemented for IPv6\n" );
+#endif
+        return ret;
+    }
+
 #ifdef __linux__
     {
         FILE *fp;
@@ -1035,11 +1091,27 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
         else ERR ("failed to get udpstat\n");
     }
 #else
-    FIXME( "unimplemented\n" );
+    FIXME( "unimplemented for IPv4\n" );
 #endif
     return ret;
 }
 
+/******************************************************************
+ *    GetUdpStatistics (IPHLPAPI.@)
+ *
+ * Get the UDP statistics for the local computer.
+ *
+ * PARAMS
+ *  stats [Out] buffer for UDP statistics
+ *
+ * RETURNS
+ *  Success: NO_ERROR
+ *  Failure: error code from winerror.h
+ */
+DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
+{
+    return GetUdpStatisticsEx(stats, WS_AF_INET);
+}
 
 static MIB_IPFORWARDTABLE *append_ipforward_row( HANDLE heap, DWORD flags, MIB_IPFORWARDTABLE *table,
                                                  DWORD *count, const MIB_IPFORWARDROW *row )
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index 1c0e2cc..02a299f 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -546,7 +546,7 @@ static void testGetIcmpStatisticsEx(void)
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
         INT i;
-        trace( "ICMP Ex stats:           %8s %8s\n", "in", "out" );
+        trace( "ICMP IPv4 Ex stats:           %8s %8s\n", "in", "out" );
         trace( "    dwMsgs:              %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
         trace( "    dwErrors:            %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
         for (i = 0; i < 256; i++)
@@ -559,7 +559,7 @@ static void testGetIcmpStatisticsEx(void)
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
         INT i;
-        trace( "ICMP Ex stats:           %8s %8s\n", "in", "out" );
+        trace( "ICMP IPv6 Ex stats:           %8s %8s\n", "in", "out" );
         trace( "    dwMsgs:              %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
         trace( "    dwErrors:            %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
         for (i = 0; i < 256; i++)
@@ -590,7 +590,7 @@ static void testGetIpStatisticsEx(void)
     ok(apiReturn == NO_ERROR, "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "IP Ex stats:\n" );
+        trace( "IP IPv4 Ex stats:\n" );
         trace( "    dwForwarding:      %u\n", U(stats).dwForwarding );
         trace( "    dwDefaultTTL:      %u\n", stats.dwDefaultTTL );
         trace( "    dwInReceives:      %u\n", stats.dwInReceives );
@@ -621,7 +621,7 @@ static void testGetIpStatisticsEx(void)
        "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "IP Ex stats:\n" );
+        trace( "IP IPv6 Ex stats:\n" );
         trace( "    dwForwarding:      %u\n", U(stats).dwForwarding );
         trace( "    dwDefaultTTL:      %u\n", stats.dwDefaultTTL );
         trace( "    dwInReceives:      %u\n", stats.dwInReceives );
@@ -667,7 +667,7 @@ static void testGetTcpStatisticsEx(void)
     ok(apiReturn == NO_ERROR, "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "TCP stats:\n" );
+        trace( "TCP IPv4 Ex stats:\n" );
         trace( "    dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
         trace( "    dwRtoMin:       %u\n", stats.dwRtoMin );
         trace( "    dwRtoMax:       %u\n", stats.dwRtoMax );
@@ -690,7 +690,7 @@ static void testGetTcpStatisticsEx(void)
        "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "TCP stats:\n" );
+        trace( "TCP IPv6 Ex stats:\n" );
         trace( "    dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
         trace( "    dwRtoMin:       %u\n", stats.dwRtoMin );
         trace( "    dwRtoMax:       %u\n", stats.dwRtoMax );
@@ -716,7 +716,7 @@ static void testGetUdpStatisticsEx(void)
 
     if (!pGetUdpStatisticsEx)
     {
-        skip( "GetUdpStatisticsEx not available\n" );
+        win_skip( "GetUdpStatisticsEx not available\n" );
         return;
     }
 
@@ -724,11 +724,15 @@ static void testGetUdpStatisticsEx(void)
     ok(apiReturn == ERROR_INVALID_PARAMETER,
        "GetUdpStatisticsEx(NULL, AF_INET); returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
 
+    apiReturn = pGetUdpStatisticsEx(&stats, AF_BAN);
+    ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
+       "GetUdpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
+
     apiReturn = pGetUdpStatisticsEx(&stats, AF_INET);
     ok(apiReturn == NO_ERROR, "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "UDP stats:\n" );
+        trace( "UDP IPv4 Ex stats:\n" );
         trace( "    dwInDatagrams:  %u\n", stats.dwInDatagrams );
         trace( "    dwNoPorts:      %u\n", stats.dwNoPorts );
         trace( "    dwInErrors:     %u\n", stats.dwInErrors );
@@ -741,7 +745,7 @@ static void testGetUdpStatisticsEx(void)
        "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
     if (apiReturn == NO_ERROR && winetest_debug > 1)
     {
-        trace( "UDP stats:\n" );
+        trace( "UDP IPv6 Ex stats:\n" );
         trace( "    dwInDatagrams:  %u\n", stats.dwInDatagrams );
         trace( "    dwNoPorts:      %u\n", stats.dwNoPorts );
         trace( "    dwInErrors:     %u\n", stats.dwInErrors );




More information about the wine-cvs mailing list