Signed-off-by: Huw Davies huw@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();