[2/4] iphlpapi: Implement GetUdpStatisticsEx on Linux
André Hentschel
nerv at dawncrow.de
Wed Sep 19 16:52:30 CDT 2012
---
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 );
--
1.7.4.1
--
Best Regards, André Hentschel
More information about the wine-patches
mailing list