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

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


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/iphlpapi/iphlpapi_main.c |  21 ++
 dlls/iphlpapi/ipstats.c       | 524 ----------------------------------
 2 files changed, 21 insertions(+), 524 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index bcda2b81b6e..82c63b0dfce 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -3491,6 +3491,27 @@ DWORD WINAPI GetExtendedUdpTable( void *table, DWORD *size, BOOL sort, ULONG fam
     return err;
 }
 
+DWORD WINAPI AllocateAndGetUdpTableFromStack( MIB_UDPTABLE **table, BOOL sort, HANDLE heap, DWORD flags )
+{
+    DWORD err, size = 0x100, attempt;
+
+    TRACE("table %p, sort %d, heap %p, flags 0x%08x\n", table, sort, heap, flags );
+
+    if (!table) return ERROR_INVALID_PARAMETER;
+
+    for (attempt = 0; attempt < 5; attempt++)
+    {
+        *table = HeapAlloc( heap, flags, size );
+        if (!*table) return ERROR_NOT_ENOUGH_MEMORY;
+        err = GetExtendedUdpTable( *table, &size, sort, WS_AF_INET, UDP_TABLE_BASIC, 0 );
+        if (!err) break;
+        HeapFree( heap, flags, *table );
+        *table = NULL;
+        if (err != ERROR_INSUFFICIENT_BUFFER) break;
+    }
+    return err;
+}
+
 static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
                               struct nsi_ip_unicast_dynamic *dyn, struct nsi_ip_unicast_static *stat )
 {
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 65bf65fec7b..1a71396e388 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -200,81 +200,6 @@ static DWORD kstat_get_ui32( kstat_t *ksp, const char *name )
 }
 #endif
 
-#if defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
-static int open_streams_mib( const char *proto )
-{
-    int fd;
-    struct strbuf buf;
-    struct request
-    {
-        struct T_optmgmt_req req_header;
-        struct opthdr        opt_header;
-    } request;
-
-    if ((fd = open( "/dev/arp", O_RDWR )) == -1)
-    {
-        WARN( "could not open /dev/arp: %s\n", strerror(errno) );
-        return -1;
-    }
-    if (proto) ioctl( fd, I_PUSH, proto );
-
-    request.req_header.PRIM_type  = T_SVR4_OPTMGMT_REQ;
-    request.req_header.OPT_length = sizeof(request.opt_header);
-    request.req_header.OPT_offset = FIELD_OFFSET( struct request, opt_header );
-    request.req_header.MGMT_flags = T_CURRENT;
-    request.opt_header.level      = MIB2_IP;
-    request.opt_header.name       = 0;
-    request.opt_header.len        = 0;
-
-    buf.len = sizeof(request);
-    buf.buf = (caddr_t)&request;
-    if (putmsg( fd, &buf, NULL, 0 ) == -1)
-    {
-        WARN( "putmsg: %s\n", strerror(errno) );
-        close( fd );
-        fd = -1;
-    }
-    return fd;
-}
-
-static void *read_mib_entry( int fd, int level, int name, int *len )
-{
-    struct strbuf buf;
-    void *data;
-    int ret, flags = 0;
-
-    struct reply
-    {
-        struct T_optmgmt_ack ack_header;
-        struct opthdr        opt_header;
-    } reply;
-
-    for (;;)
-    {
-        buf.maxlen = sizeof(reply);
-        buf.buf = (caddr_t)&reply;
-        if ((ret = getmsg( fd, &buf, NULL, &flags )) < 0) return NULL;
-        if (!(ret & MOREDATA)) return NULL;
-        if (reply.ack_header.PRIM_type != T_OPTMGMT_ACK) return NULL;
-        if (buf.len < sizeof(reply.ack_header)) return NULL;
-        if (reply.ack_header.OPT_length < sizeof(reply.opt_header)) return NULL;
-
-        if (!(data = HeapAlloc( GetProcessHeap(), 0, reply.opt_header.len ))) return NULL;
-        buf.maxlen = reply.opt_header.len;
-        buf.buf = (caddr_t)data;
-        flags = 0;
-        if (getmsg( fd, NULL, &buf, &flags ) >= 0 &&
-            reply.opt_header.level == level &&
-            reply.opt_header.name == name)
-        {
-            *len = buf.len;
-            return data;
-        }
-        HeapFree( GetProcessHeap(), 0, data );
-    }
-}
-#endif /* HAVE_SYS_TIHDR_H && T_OPTMGMT_ACK */
-
 /******************************************************************
  *    GetUdpStatistics (IPHLPAPI.@)
  *
@@ -443,452 +368,3 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
 {
     return GetUdpStatisticsEx(stats, WS_AF_INET);
 }
-
-static void *append_table_row( HANDLE heap, DWORD flags, void *table, DWORD *table_size, DWORD *table_capacity,
-                               const void *row, DWORD row_size )
-{
-    DWORD *num_entries = table; /* this must be the first field */
-    if (*num_entries == *table_capacity)
-    {
-        void *new_table;
-        *table_size += *table_capacity * row_size;
-        if (!(new_table = HeapReAlloc( heap, flags, table, *table_size )))
-        {
-            HeapFree( heap, 0, table );
-            return NULL;
-        }
-        num_entries = table = new_table;
-        *table_capacity *= 2;
-    }
-    memcpy( (char *)table + *table_size - (*table_capacity - *num_entries) * row_size, row, row_size );
-    (*num_entries)++;
-    return table;
-}
-
-struct pid_map
-{
-    unsigned int pid;
-    unsigned int unix_pid;
-};
-
-static struct pid_map *get_pid_map( unsigned int *num_entries )
-{
-    struct pid_map *map;
-    unsigned int i = 0, buffer_len = 4096, process_count, pos = 0;
-    NTSTATUS ret;
-    char *buffer = NULL, *new_buffer;
-
-    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;
-
-    for (;;)
-    {
-        SERVER_START_REQ( list_processes )
-        {
-            wine_server_set_reply( req, buffer, buffer_len );
-            ret = wine_server_call( req );
-            buffer_len = reply->info_size;
-            process_count = reply->process_count;
-        }
-        SERVER_END_REQ;
-
-        if (ret != STATUS_INFO_LENGTH_MISMATCH) break;
-
-        if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, buffer_len )))
-        {
-            HeapFree( GetProcessHeap(), 0, buffer );
-            return NULL;
-        }
-        buffer = new_buffer;
-    }
-
-    if (!(map = HeapAlloc( GetProcessHeap(), 0, process_count * sizeof(*map) )))
-    {
-        HeapFree( GetProcessHeap(), 0, buffer );
-        return NULL;
-    }
-
-    for (i = 0; i < process_count; ++i)
-    {
-        const struct process_info *process;
-
-        pos = (pos + 7) & ~7;
-        process = (const struct process_info *)(buffer + pos);
-
-        map[i].pid = process->pid;
-        map[i].unix_pid = process->unix_pid;
-
-        pos += sizeof(struct process_info) + process->name_len;
-        pos = (pos + 7) & ~7;
-        pos += process->thread_count * sizeof(struct thread_info);
-    }
-
-    HeapFree( GetProcessHeap(), 0, buffer );
-    *num_entries = process_count;
-    return map;
-}
-
-static unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode )
-{
-#ifdef __linux__
-    unsigned int i, len_socket;
-    char socket[32];
-
-    sprintf( socket, "socket:[%lu]", inode );
-    len_socket = strlen( socket );
-    for (i = 0; i < num_entries; i++)
-    {
-        char dir[32];
-        struct dirent *dirent;
-        DIR *dirfd;
-
-        sprintf( dir, "/proc/%u/fd", map[i].unix_pid );
-        if ((dirfd = opendir( dir )))
-        {
-            while ((dirent = readdir( dirfd )))
-            {
-                char link[sizeof(dirent->d_name) + 32], name[32];
-                int len;
-
-                sprintf( link, "/proc/%u/fd/%s", map[i].unix_pid, dirent->d_name );
-                if ((len = readlink( link, name, sizeof(name) - 1 )) > 0) name[len] = 0;
-                if (len == len_socket && !strcmp( socket, name ))
-                {
-                    closedir( dirfd );
-                    return map[i].pid;
-                }
-            }
-            closedir( dirfd );
-        }
-    }
-    return 0;
-#elif defined(HAVE_LIBPROCSTAT)
-    struct procstat *pstat;
-    struct kinfo_proc *proc;
-    struct filestat_list *fds;
-    struct filestat *fd;
-    struct sockstat sock;
-    unsigned int i, proc_count;
-
-    pstat = procstat_open_sysctl();
-    if (!pstat) return 0;
-
-    for (i = 0; i < num_entries; i++)
-    {
-        proc = procstat_getprocs( pstat, KERN_PROC_PID, map[i].unix_pid, &proc_count );
-        if (!proc || proc_count < 1) continue;
-
-        fds = procstat_getfiles( pstat, proc, 0 );
-        if (!fds)
-        {
-            procstat_freeprocs( pstat, proc );
-            continue;
-        }
-
-        STAILQ_FOREACH( fd, fds, next )
-        {
-            char errbuf[_POSIX2_LINE_MAX];
-
-            if (fd->fs_type != PS_FST_TYPE_SOCKET) continue;
-
-            procstat_get_socket_info( pstat, fd, &sock, errbuf );
-
-            if (sock.so_pcb == inode)
-            {
-                procstat_freefiles( pstat, fds );
-                procstat_freeprocs( pstat, proc );
-                procstat_close( pstat );
-                return map[i].pid;
-            }
-        }
-
-        procstat_freefiles( pstat, fds );
-        procstat_freeprocs( pstat, proc );
-    }
-
-    procstat_close( pstat );
-    return 0;
-#elif defined(HAVE_PROC_PIDINFO)
-    struct proc_fdinfo *fds;
-    struct socket_fdinfo sock;
-    unsigned int i, j, n;
-
-    for (i = 0; i < num_entries; i++)
-    {
-        int fd_len = proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, NULL, 0 );
-        if (fd_len <= 0) continue;
-
-        fds = HeapAlloc( GetProcessHeap(), 0, fd_len );
-        if (!fds) continue;
-
-        proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, fds, fd_len );
-        n = fd_len / sizeof(struct proc_fdinfo);
-        for (j = 0; j < n; j++)
-        {
-            if (fds[j].proc_fdtype != PROX_FDTYPE_SOCKET) continue;
-
-            proc_pidfdinfo( map[i].unix_pid, fds[j].proc_fd, PROC_PIDFDSOCKETINFO, &sock, sizeof(sock) );
-            if (sock.psi.soi_pcb == inode)
-            {
-                HeapFree( GetProcessHeap(), 0, fds );
-                return map[i].pid;
-            }
-        }
-
-        HeapFree( GetProcessHeap(), 0, fds );
-    }
-    return 0;
-#else
-    FIXME( "not implemented\n" );
-    return 0;
-#endif
-}
-
-static DWORD get_udp_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
-{
-    DWORD table_size;
-
-    switch (class)
-    {
-    case UDP_TABLE_BASIC:
-    {
-        table_size = FIELD_OFFSET(MIB_UDPTABLE, table[row_count]);
-        if (row_size) *row_size = sizeof(MIB_UDPROW);
-        break;
-    }
-    case UDP_TABLE_OWNER_PID:
-    {
-        table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]);
-        if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_PID);
-        break;
-    }
-    case UDP_TABLE_OWNER_MODULE:
-    {
-        table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table[row_count]);
-        if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_MODULE);
-        break;
-    }
-    default:
-        ERR("unhandled class %u\n", class);
-        return 0;
-    }
-    return table_size;
-}
-
-static int compare_udp_rows(const void *a, const void *b)
-{
-    const MIB_UDPROW *rowA = a;
-    const MIB_UDPROW *rowB = b;
-    int ret;
-
-    if ((ret = rowA->dwLocalAddr - rowB->dwLocalAddr) != 0) return ret;
-    return rowA->dwLocalPort - rowB->dwLocalPort;
-}
-
-DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
-                       DWORD *size )
-{
-    MIB_UDPTABLE *table;
-    MIB_UDPROW_OWNER_MODULE row;
-    DWORD ret = NO_ERROR, count = 16, table_size, row_size;
-
-    if (!(table_size = get_udp_table_sizes( class, count, &row_size )))
-        return ERROR_INVALID_PARAMETER;
-
-    if (!(table = HeapAlloc( heap, flags, table_size )))
-         return ERROR_OUTOFMEMORY;
-
-    table->dwNumEntries = 0;
-    memset( &row, 0, sizeof(row) );
-
-#ifdef __linux__
-    {
-        FILE *fp;
-
-        if ((fp = fopen( "/proc/net/udp", "r" )))
-        {
-            char buf[512], *ptr;
-            struct pid_map *map = NULL;
-            unsigned int num_entries = 0;
-            int inode;
-
-            if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
-            /* skip header line */
-            ptr = fgets( buf, sizeof(buf), fp );
-            while ((ptr = fgets( buf, sizeof(buf), fp )))
-            {
-                if (sscanf( ptr, "%*u: %x:%x %*s %*s %*s %*s %*s %*s %*s %d",
-                    &row.dwLocalAddr, &row.dwLocalPort, &inode ) != 3)
-                    continue;
-                row.dwLocalPort = htons( row.dwLocalPort );
-
-                if (class >= UDP_TABLE_OWNER_PID)
-                    row.dwOwningPid = find_owning_pid( map, num_entries, inode );
-                if (class >= UDP_TABLE_OWNER_MODULE)
-                {
-                    row.liCreateTimestamp.QuadPart = 0; /* FIXME */
-                    row.dwFlags = 0;
-                    memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
-                }
-                if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
-                    break;
-            }
-            HeapFree( GetProcessHeap(), 0, map );
-            fclose( fp );
-        }
-        else ret = ERROR_NOT_SUPPORTED;
-    }
-#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
-    {
-        void *data;
-        int fd, len;
-        mib2_udpEntry_t *entry;
-
-        if ((fd = open_streams_mib( "udp" )) != -1)
-        {
-            if ((data = read_mib_entry( fd, MIB2_UDP, MIB2_UDP_ENTRY, &len )))
-            {
-                for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
-                {
-                    row.dwLocalAddr = entry->udpLocalAddress;
-                    row.dwLocalPort = htons( entry->udpLocalPort );
-                    if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
-                        break;
-                }
-                HeapFree( GetProcessHeap(), 0, data );
-            }
-            close( fd );
-        }
-        else ret = ERROR_NOT_SUPPORTED;
-    }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
-    {
-        size_t Len = 0;
-        char *Buf = NULL;
-        struct xinpgen *pXIG, *pOrigXIG;
-        struct pid_map *pMap = NULL;
-        unsigned NumEntries;
-
-        if (sysctlbyname ("net.inet.udp.pcblist", NULL, &Len, NULL, 0) < 0)
-        {
-            ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
-            ret = ERROR_NOT_SUPPORTED;
-            goto done;
-        }
-
-        Buf = HeapAlloc (GetProcessHeap (), 0, Len);
-        if (!Buf)
-        {
-            ret = ERROR_OUTOFMEMORY;
-            goto done;
-        }
-
-        if (sysctlbyname ("net.inet.udp.pcblist", Buf, &Len, NULL, 0) < 0)
-        {
-            ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
-            ret = ERROR_NOT_SUPPORTED;
-            goto done;
-        }
-
-        if (class >= UDP_TABLE_OWNER_PID)
-            pMap = get_pid_map( &NumEntries );
-
-        /* Might be nothing here; first entry is just a header it seems */
-        if (Len <= sizeof (struct xinpgen)) goto done;
-
-        pOrigXIG = (struct xinpgen *)Buf;
-        pXIG = pOrigXIG;
-
-        for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
-             pXIG->xig_len > sizeof (struct xinpgen);
-             pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
-        {
-#if __FreeBSD_version >= 1200026
-            struct xinpcb *pINData = (struct xinpcb *)pXIG;
-            struct xsocket *pSockData = &pINData->xi_socket;
-#else
-            struct inpcb *pINData = &((struct xinpcb *)pXIG)->xi_inp;
-            struct xsocket *pSockData = &((struct xinpcb *)pXIG)->xi_socket;
-#endif
-
-            /* Ignore sockets for other protocols */
-            if (pSockData->xso_protocol != IPPROTO_UDP)
-                continue;
-
-            /* Ignore PCBs that were freed while generating the data */
-            if (pINData->inp_gencnt > pOrigXIG->xig_gen)
-                continue;
-
-            /* we're only interested in IPv4 addresses */
-            if (!(pINData->inp_vflag & INP_IPV4) ||
-                (pINData->inp_vflag & INP_IPV6))
-                continue;
-
-            /* If all 0's, skip it */
-            if (!pINData->inp_laddr.s_addr &&
-                !pINData->inp_lport)
-                continue;
-
-            /* Fill in structure details */
-            row.dwLocalAddr = pINData->inp_laddr.s_addr;
-            row.dwLocalPort = pINData->inp_lport;
-            if (class >= UDP_TABLE_OWNER_PID)
-                row.dwOwningPid = find_owning_pid( pMap, NumEntries, (UINT_PTR)pSockData->so_pcb );
-            if (class >= UDP_TABLE_OWNER_MODULE)
-            {
-                row.liCreateTimestamp.QuadPart = 0; /* FIXME */
-                row.dwFlags = 0;
-                row.SpecificPortBind = !(pINData->inp_flags & INP_ANONPORT);
-                memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
-            }
-            if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
-                break;
-        }
-
-    done:
-        HeapFree( GetProcessHeap(), 0, pMap );
-        HeapFree (GetProcessHeap (), 0, Buf);
-    }
-#else
-    FIXME( "not implemented\n" );
-    ret = ERROR_NOT_SUPPORTED;
-#endif
-
-    if (!table) return ERROR_OUTOFMEMORY;
-    if (!ret)
-    {
-        if (order && table->dwNumEntries)
-            qsort( table->table, table->dwNumEntries, row_size, compare_udp_rows );
-        *tablep = table;
-    }
-    else HeapFree( heap, flags, table );
-    if (size) *size = get_udp_table_sizes( class, count, NULL );
-    TRACE( "returning ret %u table %p\n", ret, table );
-    return ret;
-}
-
-/******************************************************************
- *    AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
- *
- * Get the UDP listener table.
- * Like GetUdpTable(), but allocate the returned table from heap.
- *
- * PARAMS
- *  ppUdpTable [Out] pointer into which the MIB_UDPTABLE is
- *                   allocated and returned.
- *  bOrder     [In]  whether to sort the table
- *  heap       [In]  heap from which the table is allocated
- *  flags      [In]  flags to HeapAlloc
- *
- * RETURNS
- *  ERROR_INVALID_PARAMETER if ppUdpTable is NULL, whatever GetUdpTable()
- *  returns otherwise.
- */
-DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, BOOL bOrder,
-                                             HANDLE heap, DWORD flags)
-{
-    TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppUdpTable, bOrder, heap, flags);
-
-    if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
-    return build_udp_table( UDP_TABLE_BASIC, (void **)ppUdpTable, bOrder, heap, flags, NULL );
-}
-- 
2.23.0




More information about the wine-devel mailing list