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