[PATCH 2/4] nsiproxy: Implement IPv6 ipstats get_all_parameters on linux.

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


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/nsi/tests/nsi.c   |  1 -
 dlls/nsiproxy.sys/ip.c | 85 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index dd1a552cce6..feed72a1626 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -424,7 +424,6 @@ static void test_ip_ipstats( int family )
     /* The table appears to consist of a single object without a key.  The rw data does exist but
        isn't part of GetIpStatisticsEx() and isn't yet tested */
     err = NsiGetAllParameters( 1, mod, NSI_IP_IPSTATS_TABLE, NULL, 0, NULL, 0, &dyn, sizeof(dyn), &stat, sizeof(stat) );
-todo_wine_if( family == AF_INET6 )
     ok( !err, "got %x\n", err );
     if (err) goto err;
 
diff --git a/dlls/nsiproxy.sys/ip.c b/dlls/nsiproxy.sys/ip.c
index 438ae219174..7d9af08c711 100644
--- a/dlls/nsiproxy.sys/ip.c
+++ b/dlls/nsiproxy.sys/ip.c
@@ -226,6 +226,82 @@ static NTSTATUS ipv4_ipstats_get_all_parameters( const void *key, DWORD key_size
 #endif
 }
 
+static NTSTATUS ipv6_ipstats_get_all_parameters( const void *key, DWORD key_size, void *rw_data, DWORD rw_size,
+                                                 void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size )
+{
+    struct nsi_ip_ipstats_dynamic dyn;
+    struct nsi_ip_ipstats_static stat;
+
+    memset( &dyn, 0, sizeof(dyn) );
+    memset( &stat, 0, sizeof(stat) );
+
+#ifdef __linux__
+    {
+        struct
+        {
+            const char *name;
+            void *elem;
+            int size;
+        } ipstatlist[] =
+        {
+#define X(x) &x, sizeof(x)
+            { "Ip6InReceives",       X( dyn.in_recv ) },
+            { "Ip6InHdrErrors",      X( dyn.in_hdr_errs ) },
+            { "Ip6InAddrErrors",     X( dyn.in_addr_errs ) },
+            { "Ip6OutForwDatagrams", X( dyn.fwd_dgrams ) },
+            { "Ip6InUnknownProtos",  X( dyn.in_unk_protos ) },
+            { "Ip6InDiscards",       X( dyn.in_discards ) },
+            { "Ip6InDelivers",       X( dyn.in_delivers ) },
+            { "Ip6OutRequests",      X( dyn.out_reqs ) },
+            { "Ip6OutDiscards",      X( dyn.out_discards ) },
+            { "Ip6OutNoRoutes",      X( dyn.out_no_routes ) },
+            { "Ip6ReasmTimeout",     X( stat.reasm_timeout ) },
+            { "Ip6ReasmReqds",       X( dyn.reasm_reqds ) },
+            { "Ip6ReasmOKs",         X( dyn.reasm_oks ) },
+            { "Ip6ReasmFails",       X( dyn.reasm_fails ) },
+            { "Ip6FragOKs",          X( dyn.frag_oks ) },
+            { "Ip6FragFails",        X( dyn.frag_fails ) },
+            { "Ip6FragCreates",      X( dyn.frag_creates ) },
+            /* no routingDiscards */
+#undef X
+        };
+        NTSTATUS status = STATUS_NOT_SUPPORTED;
+        char buf[512], *ptr, *value;
+        DWORD i;
+        FILE *fp;
+
+        if (!(fp = fopen( "/proc/net/snmp6", "r" ))) return STATUS_NOT_SUPPORTED;
+
+        while ((ptr = fgets( buf, sizeof(buf), fp )))
+        {
+            if (!(value = strchr( buf, ' ' ))) continue;
+            /* terminate the valuename */
+            *value++ = '\0';
+            /* and strip leading spaces from value */
+            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 ))
+                {
+                    if (ipstatlist[i].size == sizeof(long))
+                        *(long *)ipstatlist[i].elem = strtoul( value, NULL, 10 );
+                    else
+                        *(long long *)ipstatlist[i].elem = strtoull( value, NULL, 10 );
+                    status = STATUS_SUCCESS;
+                }
+        }
+        fclose( fp );
+        if (dynamic_data) *(struct nsi_ip_ipstats_dynamic *)dynamic_data = dyn;
+        if (static_data) *(struct nsi_ip_ipstats_static *)static_data = stat;
+        return status;;
+    }
+#else
+    FIXME( "not implemented\n" );
+    return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
 static void unicast_fill_entry( struct ifaddrs *entry, void *key, struct nsi_ip_unicast_rw *rw,
                                 struct nsi_ip_unicast_dynamic *dyn, struct nsi_ip_unicast_static *stat )
 {
@@ -840,6 +916,15 @@ const struct module ipv4_module =
 
 static struct module_table ipv6_tables[] =
 {
+    {
+        NSI_IP_IPSTATS_TABLE,
+        {
+            0, 0,
+            sizeof(struct nsi_ip_ipstats_dynamic), sizeof(struct nsi_ip_ipstats_static)
+        },
+        NULL,
+        ipv6_ipstats_get_all_parameters,
+    },
     {
         NSI_IP_UNICAST_TABLE,
         {
-- 
2.23.0




More information about the wine-devel mailing list