[PATCH 5/5] iphlpapi: Implement GetUdpStatisticsEx() on top of nsi.

Huw Davies huw at codeweavers.com
Wed Aug 18 02:54:48 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/iphlpapi/Makefile.in     |   4 +-
 dlls/iphlpapi/ifenum.c        | 395 ----------------------------------
 dlls/iphlpapi/ifenum.h        |  66 ------
 dlls/iphlpapi/iphlpapi_main.c |  48 ++++-
 dlls/iphlpapi/ipstats.c       | 370 -------------------------------
 dlls/nsi/tests/nsi.c          |   1 -
 6 files changed, 48 insertions(+), 836 deletions(-)
 delete mode 100644 dlls/iphlpapi/ifenum.c
 delete mode 100644 dlls/iphlpapi/ifenum.h
 delete mode 100644 dlls/iphlpapi/ipstats.c

diff --git a/dlls/iphlpapi/Makefile.in b/dlls/iphlpapi/Makefile.in
index 3797ac793e6..326cf8bf75e 100644
--- a/dlls/iphlpapi/Makefile.in
+++ b/dlls/iphlpapi/Makefile.in
@@ -5,8 +5,6 @@ EXTRALIBS = $(KSTAT_LIBS) $(PROCSTAT_LIBS)
 
 C_SRCS = \
 	icmp.c \
-	ifenum.c \
-	iphlpapi_main.c \
-	ipstats.c
+	iphlpapi_main.c
 
 RC_SRCS = version.rc
diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c
deleted file mode 100644
index 0264f621b1f..00000000000
--- a/dlls/iphlpapi/ifenum.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/* Copyright (C) 2003,2006,2011 Juan Lang
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-
-#ifdef HAVE_NET_ROUTE_H
-#include <net/route.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-
-#ifdef HAVE_LINUX_RTNETLINK_H
-#include <linux/rtnetlink.h>
-#endif
-
-#include "ifenum.h"
-#include "ws2ipdef.h"
-
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-#define ifreq_len(ifr) \
- max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
-#else
-#define ifreq_len(ifr) sizeof(struct ifreq)
-#endif
-
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-
-#ifndef IF_NAMESIZE
-#define IF_NAMESIZE 16
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE (~0U)
-#endif
-
-#define INITIAL_INTERFACES_ASSUMED 4
-
-/* Functions */
-
-static BOOL isLoopbackInterface(int fd, const char *name)
-{
-  BOOL ret = FALSE;
-
-  if (name) {
-    struct ifreq ifr;
-
-    lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
-      ret = ifr.ifr_flags & IFF_LOOPBACK;
-  }
-  return !!ret;
-}
-
-/* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
- * bytes are necessary.
- */
-static char *getInterfaceNameByIndex(IF_INDEX index, char *name)
-{
-  return if_indextoname(index, name);
-}
-
-DWORD getInterfaceIndexByName(const char *name, IF_INDEX *index)
-{
-  DWORD ret;
-  unsigned int idx;
-
-  if (!name)
-    return ERROR_INVALID_PARAMETER;
-  if (!index)
-    return ERROR_INVALID_PARAMETER;
-  idx = if_nametoindex(name);
-  if (idx) {
-    *index = idx;
-    ret = NO_ERROR;
-  }
-  else
-    ret = ERROR_INVALID_DATA;
-  return ret;
-}
-
-static BOOL isIfIndexLoopback(ULONG idx)
-{
-  BOOL ret = FALSE;
-  char name[IFNAMSIZ];
-  int fd;
-
-  getInterfaceNameByIndex(idx, name);
-  fd = socket(PF_INET, SOCK_DGRAM, 0);
-  if (fd != -1) {
-    ret = isLoopbackInterface(fd, name);
-    close(fd);
-  }
-  return ret;
-}
-
-#ifdef HAVE_IF_NAMEINDEX
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
-    DWORD count = 0, i;
-    struct if_nameindex *p, *indices = if_nameindex();
-    InterfaceIndexTable *ret;
-
-    if (table) *table = NULL;
-    if (!indices) return 0;
-
-    for (p = indices; p->if_name; p++)
-    {
-        if (skip_loopback && isIfIndexLoopback( p->if_index )) continue;
-        count++;
-    }
-
-    if (table)
-    {
-        ret = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(InterfaceIndexTable, indexes[count]) );
-        if (!ret)
-        {
-            count = 0;
-            goto end;
-        }
-        for (p = indices, i = 0; p->if_name && i < count; p++)
-        {
-            if (skip_loopback && isIfIndexLoopback( p->if_index )) continue;
-            ret->indexes[i++] = p->if_index;
-        }
-        ret->numIndexes = count = i;
-        *table = ret;
-    }
-
-end:
-    if_freenameindex( indices );
-    return count;
-}
-
-#elif defined(HAVE_LINUX_RTNETLINK_H)
-static int open_netlink( int *pid )
-{
-    int fd = socket( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
-    struct sockaddr_nl addr;
-    socklen_t len;
-
-    if (fd < 0) return fd;
-
-    memset( &addr, 0, sizeof(addr) );
-    addr.nl_family = AF_NETLINK;
-
-    if (bind( fd, (struct sockaddr *)&addr, sizeof(addr) ) < 0)
-        goto fail;
-
-    len = sizeof(addr);
-    if (getsockname( fd, (struct sockaddr *)&addr, &len ) < 0)
-        goto fail;
-
-    *pid = addr.nl_pid;
-    return fd;
-fail:
-    close( fd );
-    return -1;
-}
-
-static int send_netlink_req( int fd, int pid, int type, int *seq_no )
-{
-    static LONG seq;
-    struct request
-    {
-        struct nlmsghdr hdr;
-        struct rtgenmsg gen;
-    } req;
-    struct sockaddr_nl addr;
-
-    req.hdr.nlmsg_len = sizeof(req);
-    req.hdr.nlmsg_type = type;
-    req.hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
-    req.hdr.nlmsg_pid = pid;
-    req.hdr.nlmsg_seq = InterlockedIncrement( &seq );
-    req.gen.rtgen_family = AF_UNSPEC;
-
-    memset( &addr, 0, sizeof(addr) );
-    addr.nl_family = AF_NETLINK;
-    if (sendto( fd, &req, sizeof(req), 0, (struct sockaddr *)&addr, sizeof(addr) ) != sizeof(req))
-        return -1;
-    *seq_no = req.hdr.nlmsg_seq;
-    return 0;
-}
-
-struct netlink_reply
-{
-    struct netlink_reply *next;
-    int size;
-    struct nlmsghdr *hdr;
-};
-
-static void free_netlink_reply( struct netlink_reply *data )
-{
-    struct netlink_reply *ptr;
-    while( data )
-    {
-        ptr = data->next;
-        HeapFree( GetProcessHeap(), 0, data );
-        data = ptr;
-    }
-}
-
-static int recv_netlink_reply( int fd, int pid, int seq, struct netlink_reply **data )
-{
-    int bufsize = getpagesize();
-    int left, read;
-    BOOL done = FALSE;
-    socklen_t sa_len;
-    struct sockaddr_nl addr;
-    struct netlink_reply *cur, *last = NULL;
-    struct nlmsghdr *hdr;
-    char *buf;
-
-    *data = NULL;
-    buf = HeapAlloc( GetProcessHeap(), 0, bufsize );
-    if (!buf) return -1;
-
-    do
-    {
-        left = read = recvfrom( fd, buf, bufsize, 0, (struct sockaddr *)&addr, &sa_len );
-        if (read < 0) goto fail;
-        if (addr.nl_pid != 0) continue; /* not from kernel */
-
-        for (hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, left); hdr = NLMSG_NEXT(hdr, left))
-        {
-            if (hdr->nlmsg_pid != pid || hdr->nlmsg_seq != seq) continue;
-            if (hdr->nlmsg_type == NLMSG_DONE)
-            {
-                done = TRUE;
-                break;
-            }
-        }
-
-        cur = HeapAlloc( GetProcessHeap(), 0, sizeof(*cur) + read );
-        if (!cur) goto fail;
-        cur->next = NULL;
-        cur->size = read;
-        cur->hdr = (struct nlmsghdr *)(cur + 1);
-        memcpy( cur->hdr, buf, read );
-        if (last) last->next = cur;
-        else *data = cur;
-        last = cur;
-    } while (!done);
-
-    HeapFree( GetProcessHeap(), 0, buf );
-    return 0;
-
-fail:
-    free_netlink_reply( *data );
-    HeapFree( GetProcessHeap(), 0, buf );
-    return -1;
-}
-
-
-static DWORD get_indices_from_reply( struct netlink_reply *reply, int pid, int seq,
-                                     BOOL skip_loopback, InterfaceIndexTable *table )
-{
-    struct nlmsghdr *hdr;
-    struct netlink_reply *r;
-    int count = 0;
-
-    for (r = reply; r; r = r->next)
-    {
-        int size = r->size;
-        for (hdr = r->hdr; NLMSG_OK(hdr, size); hdr = NLMSG_NEXT(hdr, size))
-        {
-            if (hdr->nlmsg_pid != pid || hdr->nlmsg_seq != seq) continue;
-            if (hdr->nlmsg_type == NLMSG_DONE) break;
-
-            if (hdr->nlmsg_type == RTM_NEWLINK)
-            {
-                struct ifinfomsg *info = NLMSG_DATA(hdr);
-
-                if (skip_loopback && (info->ifi_flags & IFF_LOOPBACK)) continue;
-                if (table) table->indexes[count] = info->ifi_index;
-                count++;
-            }
-        }
-    }
-    return count;
-}
-
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
-    int fd, pid, seq;
-    struct netlink_reply *reply = NULL;
-    DWORD count = 0;
-
-    if (table) *table = NULL;
-    fd = open_netlink( &pid );
-    if (fd < 0) return 0;
-
-    if (send_netlink_req( fd, pid, RTM_GETLINK, &seq ) < 0)
-        goto end;
-
-    if (recv_netlink_reply( fd, pid, seq, &reply ) < 0)
-        goto end;
-
-    count = get_indices_from_reply( reply, pid, seq, skip_loopback, NULL );
-
-    if (table)
-    {
-        InterfaceIndexTable *ret = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(InterfaceIndexTable, indexes[count]) );
-        if (!ret)
-        {
-            count = 0;
-            goto end;
-        }
-
-        ret->numIndexes = count;
-        get_indices_from_reply( reply, pid, seq, skip_loopback, ret );
-        *table = ret;
-    }
-
-end:
-    free_netlink_reply( reply );
-    close( fd );
-    return count;
-}
-
-#else
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
-    if (table) *table = NULL;
-    return 0;
-}
-#endif
diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h
deleted file mode 100644
index 710b493ad36..00000000000
--- a/dlls/iphlpapi/ifenum.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ifenum.h
- * Copyright (C) 2003,2006 Juan Lang
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * This module implements network interface and address enumeration.  It's
- * meant to hide some problematic defines like socket(), and make iphlpapi
- * more portable.
- *
- * Like Windows, it uses a numeric index to identify an interface uniquely.
- * As implemented, an interface represents a UNIX network interface, virtual
- * or real, and thus can have 0 or 1 IP addresses associated with it.  (This
- * only supports IPv4.)
- * The indexes returned are not guaranteed to be contiguous, so don't call
- * getNumInterfaces() and assume the values [0,getNumInterfaces() - 1] will be
- * valid indexes; use getInterfaceIndexTable() instead.
- *
- * See also the companion file, ipstats.h, for functions related to getting
- * statistics.
- */
-#ifndef WINE_IFENUM_H_
-#define WINE_IFENUM_H_
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#define USE_WS_PREFIX
-#include "iprtrmib.h"
-#include "winsock2.h"
-
-#define MAX_INTERFACE_PHYSADDR    8
-#define MAX_INTERFACE_DESCRIPTION 256
-
-/* A table of interface indexes, see get_interface_indices(). */
-typedef struct _InterfaceIndexTable {
-  DWORD numIndexes;
-  IF_INDEX indexes[1];
-} InterfaceIndexTable;
-
-/* Returns the count of all interface indexes and optionally a ptr to an interface table.
- * HeapFree() the returned table.  Will optionally ignore loopback devices.
- */
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table ) DECLSPEC_HIDDEN;
-
-/* ByName/ByIndex versions of various getter functions. */
-
-/* Fills index with the index of name, if found.  Returns
- * ERROR_INVALID_PARAMETER if name or index is NULL, ERROR_INVALID_DATA if name
- * is not found, and NO_ERROR on success.
- */
-DWORD getInterfaceIndexByName(const char *name, IF_INDEX *index) DECLSPEC_HIDDEN;
-
-#endif /* ndef WINE_IFENUM_H_ */
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 82c63b0dfce..8a8b6b3e7cf 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -42,7 +42,6 @@
 #include "ws2ipdef.h"
 #include "windns.h"
 #include "iphlpapi.h"
-#include "ifenum.h"
 #include "ipifcons.h"
 #include "fltdefs.h"
 #include "ifdef.h"
@@ -3282,6 +3281,53 @@ DWORD WINAPI AllocateAndGetTcpExTableFromStack( void **table, BOOL sort, HANDLE
     return allocate_tcp_table( table, sort, heap, flags, family, TCP_TABLE_OWNER_PID_ALL );
 }
 
+/******************************************************************
+ *    GetUdpStatistics (IPHLPAPI.@)
+ *
+ * Get the UDP statistics for the local computer.
+ *
+ * PARAMS
+ *  stats [Out] buffer for UDP statistics
+ */
+DWORD WINAPI GetUdpStatistics( MIB_UDPSTATS *stats )
+{
+    return GetUdpStatisticsEx( stats, WS_AF_INET );
+}
+
+/******************************************************************
+ *    GetUdpStatisticsEx (IPHLPAPI.@)
+ *
+ * Get the IPv4 and IPv6 UDP statistics for the local computer.
+ *
+ * PARAMS
+ *  stats [Out] buffer for UDP statistics
+ *  family [In] specifies whether IPv4 or IPv6 statistics are returned
+ *
+ * RETURNS
+ *  Success: NO_ERROR
+ *  Failure: error code from winerror.h
+ */
+DWORD WINAPI GetUdpStatisticsEx( MIB_UDPSTATS *stats, DWORD family )
+{
+    struct nsi_udp_stats_dynamic dyn;
+    USHORT key = (USHORT)family;
+    DWORD err;
+
+    if (!stats || !ip_module_id( family )) return ERROR_INVALID_PARAMETER;
+    memset( stats, 0, sizeof(*stats) );
+
+    err = NsiGetAllParameters( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_STATS_TABLE, &key, sizeof(key), NULL, 0,
+                               &dyn, sizeof(dyn), NULL, 0 );
+    if (err) return err;
+
+    stats->dwInDatagrams = dyn.in_dgrams;
+    stats->dwNoPorts = dyn.no_ports;
+    stats->dwInErrors = dyn.in_errs;
+    stats->dwOutDatagrams = dyn.out_dgrams;
+    stats->dwNumAddrs = dyn.num_addrs;
+    return err;
+}
+
 /******************************************************************
  *    GetUdpTable (IPHLPAPI.@)
  *
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
deleted file mode 100644
index 1a71396e388..00000000000
--- a/dlls/iphlpapi/ipstats.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2003,2006 Juan Lang
- * Copyright (C) 2007 TransGaming Technologies Inc.
- * Copyright (C) 2009 Alexandre Julliard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_ALIAS_H
-#include <alias.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_SOCKETVAR_H
-#include <sys/socketvar.h>
-#endif
-#ifdef HAVE_SYS_TIMEOUT_H
-#include <sys/timeout.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_IN_SYSTM_H
-#include <netinet/in_systm.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-#ifdef HAVE_NET_ROUTE_H
-#include <net/route.h>
-#endif
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-#ifdef HAVE_NETINET_IF_ETHER_H
-#include <netinet/if_ether.h>
-#endif
-#ifdef HAVE_NETINET_IF_INARP_H
-#include <netinet/if_inarp.h>
-#endif
-#ifdef HAVE_NETINET_IP_H
-#include <netinet/ip.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#ifdef HAVE_NETINET_IP_VAR_H
-#include <netinet/ip_var.h>
-#endif
-#ifdef HAVE_NETINET_TCP_FSM_H
-#include <netinet/tcp_fsm.h>
-#endif
-#ifdef HAVE_NETINET_IN_PCB_H
-#include <netinet/in_pcb.h>
-#endif
-#ifdef HAVE_NETINET_TCP_TIMER_H
-#include <netinet/tcp_timer.h>
-#endif
-#ifdef HAVE_NETINET_TCP_VAR_H
-#include <netinet/tcp_var.h>
-#endif
-#ifdef HAVE_NETINET_IP_ICMP_H
-#include <netinet/ip_icmp.h>
-#endif
-#ifdef HAVE_NETINET_ICMP_VAR_H
-#include <netinet/icmp_var.h>
-#endif
-#ifdef HAVE_NETINET_UDP_H
-#include <netinet/udp.h>
-#endif
-#ifdef HAVE_NETINET_UDP_VAR_H
-#include <netinet/udp_var.h>
-#endif
-#ifdef HAVE_SYS_PROTOSW_H
-#include <sys/protosw.h>
-#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-#ifdef HAVE_KSTAT_H
-#include <kstat.h>
-#endif
-#ifdef HAVE_INET_MIB2_H
-#include <inet/mib2.h>
-#endif
-#ifdef HAVE_STROPTS_H
-#include <stropts.h>
-#endif
-#ifdef HAVE_SYS_TIHDR_H
-#include <sys/tihdr.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h>
-#endif
-#ifdef HAVE_SYS_USER_H
-/* Make sure the definitions of struct kinfo_proc are the same. */
-#include <sys/user.h>
-#endif
-#ifdef HAVE_LIBPROCSTAT_H
-#include <libprocstat.h>
-#endif
-#ifdef HAVE_LIBPROC_H
-#include <libproc.h>
-#endif
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-
-#ifndef ROUNDUP
-#define ROUNDUP(a) \
-	((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))
-#endif
-#ifndef ADVANCE
-#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
-#endif
-
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#define NONAMELESSUNION
-#define USE_WS_PREFIX
-#include "winsock2.h"
-#include "ws2ipdef.h"
-#include "ifenum.h"
-#include "iphlpapi.h"
-
-#include "wine/debug.h"
-#include "wine/server.h"
-#include "wine/unicode.h"
-
-#ifndef HAVE_NETINET_TCP_FSM_H
-#define TCPS_ESTABLISHED  1
-#define TCPS_SYN_SENT     2
-#define TCPS_SYN_RECEIVED 3
-#define TCPS_FIN_WAIT_1   4
-#define TCPS_FIN_WAIT_2   5
-#define TCPS_TIME_WAIT    6
-#define TCPS_CLOSED       7
-#define TCPS_CLOSE_WAIT   8
-#define TCPS_LAST_ACK     9
-#define TCPS_LISTEN      10
-#define TCPS_CLOSING     11
-#endif
-
-#ifndef RTF_MULTICAST
-#define RTF_MULTICAST 0 /* Not available on NetBSD/OpenBSD */
-#endif
-
-#ifndef RTF_LLINFO
-#define RTF_LLINFO 0 /* Not available on FreeBSD 8 and above */
-#endif
-
-WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
-
-#ifdef HAVE_LIBKSTAT
-static DWORD kstat_get_ui32( kstat_t *ksp, const char *name )
-{
-    unsigned int i;
-    kstat_named_t *data = ksp->ks_data;
-
-    for (i = 0; i < ksp->ks_ndata; i++)
-        if (!strcmp( data[i].name, name )) return data[i].value.ui32;
-    return 0;
-}
-#endif
-
-/******************************************************************
- *    GetUdpStatistics (IPHLPAPI.@)
- *
- * Get the IPv4 and IPv6 UDP statistics for the local computer.
- *
- * PARAMS
- *  stats [Out] buffer for UDP statistics
- *  family [In] specifies whether IPv4 or IPv6 statistics are returned
- *
- * RETURNS
- *  Success: NO_ERROR
- *  Failure: error code from winerror.h
- */
-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 = get_interface_indices( FALSE, NULL );
-
-    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 < ARRAY_SIZE(udpstatlist); i++)
-                        if (!_strnicmp(buf, udpstatlist[i].name, -1) && sscanf(value, "%d", &res))
-                            *udpstatlist[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[] = "Udp:";
-            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",
-                            &stats->dwInDatagrams, &stats->dwNoPorts,
-                            &stats->dwInErrors, &stats->dwOutDatagrams, &stats->dwNumAddrs );
-                    break;
-                }
-            }
-            fclose(fp);
-            ret = NO_ERROR;
-        }
-    }
-#elif defined(HAVE_LIBKSTAT)
-    {
-        static char udp[] = "udp";
-        kstat_ctl_t *kc;
-        kstat_t *ksp;
-        MIB_UDPTABLE *udp_table;
-
-        if ((kc = kstat_open()) &&
-            (ksp = kstat_lookup( kc, udp, 0, udp )) &&
-            kstat_read( kc, ksp, NULL ) != -1 &&
-            ksp->ks_type == KSTAT_TYPE_NAMED)
-        {
-            stats->dwInDatagrams  = kstat_get_ui32( ksp, "inDatagrams" );
-            stats->dwNoPorts      = 0;  /* FIXME */
-            stats->dwInErrors     = kstat_get_ui32( ksp, "inErrors" );
-            stats->dwOutDatagrams = kstat_get_ui32( ksp, "outDatagrams" );
-            if (!AllocateAndGetUdpTableFromStack( &udp_table, FALSE, GetProcessHeap(), 0 ))
-            {
-                stats->dwNumAddrs = udp_table->dwNumEntries;
-                HeapFree( GetProcessHeap(), 0, udp_table );
-            }
-            ret = NO_ERROR;
-        }
-        if (kc) kstat_close( kc );
-    }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_STATS) && defined(HAVE_STRUCT_UDPSTAT_UDPS_IPACKETS)
-    {
-        int mib[] = {CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS};
-        struct udpstat udp_stat;
-        MIB_UDPTABLE *udp_table;
-        size_t needed = sizeof(udp_stat);
-
-        if(sysctl(mib, ARRAY_SIZE(mib), &udp_stat, &needed, NULL, 0) != -1)
-        {
-            stats->dwInDatagrams = udp_stat.udps_ipackets;
-            stats->dwOutDatagrams = udp_stat.udps_opackets;
-            stats->dwNoPorts = udp_stat.udps_noport;
-            stats->dwInErrors = udp_stat.udps_hdrops + udp_stat.udps_badsum + udp_stat.udps_fullsock + udp_stat.udps_badlen;
-            if (!AllocateAndGetUdpTableFromStack( &udp_table, FALSE, GetProcessHeap(), 0 ))
-            {
-                stats->dwNumAddrs = udp_table->dwNumEntries;
-                HeapFree( GetProcessHeap(), 0, udp_table );
-            }
-            ret = NO_ERROR;
-        }
-        else ERR ("failed to get udpstat\n");
-    }
-#else
-    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);
-}
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index bd7992f6916..f1f3c4f387f 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -966,7 +966,6 @@ static void test_udp_stats( int family )
         table.dwInErrors, dyn.in_errs, dyn2.in_errs );
     ok( bounded( table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams ), "%d vs [%I64d %I64d]\n",
         table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams );
-todo_wine_if(!unstable(0) && table.dwNumAddrs != dyn.num_addrs)
     ok( unstable( table.dwNumAddrs == dyn.num_addrs ), "%d %d\n", table.dwNumAddrs, dyn.num_addrs );
 
     winetest_pop_context();
-- 
2.23.0




More information about the wine-devel mailing list