diff --git a/configure b/configure index 2d77fe12998..e32cb692faa 100755 --- a/configure +++ b/configure @@ -6072,6 +6072,9 @@ done + + + @@ -6098,6 +6101,7 @@ for ac_header in \ getopt.h \ grp.h \ ieeefp.h \ + inet/mib2.h \ io.h \ jack/jack.h \ jpeglib.h \ @@ -6146,6 +6150,7 @@ for ac_header in \ soundcard.h \ stdint.h \ strings.h \ + stropts.h \ sys/asoundlib.h \ sys/cdio.h \ sys/elf32.h \ @@ -6180,6 +6185,7 @@ for ac_header in \ sys/statvfs.h \ sys/strtio.h \ sys/syscall.h \ + sys/tihdr.h \ sys/time.h \ sys/timeout.h \ sys/times.h \ diff --git a/configure.ac b/configure.ac index f70222f6550..274d60abc6e 100644 --- a/configure.ac +++ b/configure.ac @@ -279,6 +279,7 @@ AC_CHECK_HEADERS(\ getopt.h \ grp.h \ ieeefp.h \ + inet/mib2.h \ io.h \ jack/jack.h \ jpeglib.h \ @@ -327,6 +328,7 @@ AC_CHECK_HEADERS(\ soundcard.h \ stdint.h \ strings.h \ + stropts.h \ sys/asoundlib.h \ sys/cdio.h \ sys/elf32.h \ @@ -361,6 +363,7 @@ AC_CHECK_HEADERS(\ sys/statvfs.h \ sys/strtio.h \ sys/syscall.h \ + sys/tihdr.h \ sys/time.h \ sys/timeout.h \ sys/times.h \ diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index a1b99818962..c92f0e4e5cd 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef HAVE_ALIAS_H #include @@ -110,6 +111,15 @@ #ifdef HAVE_KSTAT_H #include #endif +#ifdef HAVE_INET_MIB2_H +#include +#endif +#ifdef HAVE_STROPTS_H +#include +#endif +#ifdef HAVE_SYS_TIHDR_H +#include +#endif #ifndef ROUNDUP #define ROUNDUP(a) \ @@ -173,6 +183,81 @@ static ULONGLONG kstat_get_ui64( 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 */ + DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry) { DWORD ret = ERROR_NOT_SUPPORTED; @@ -1398,7 +1483,7 @@ static MIB_TCPTABLE *append_tcp_row( HANDLE heap, DWORD flags, MIB_TCPTABLE *tab /* Why not a lookup table? Because the TCPS_* constants are different on different platforms */ -static DWORD TCPStateToMIBState (int state) +static inline DWORD TCPStateToMIBState (int state) { switch (state) { @@ -1491,6 +1576,31 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack( PMIB_TCPTABLE *ppTcpTable, BOOL bO } else ret = ERROR_NOT_SUPPORTED; } +#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK) + { + void *data; + int fd, len; + mib2_tcpConnEntry_t *entry; + + if ((fd = open_streams_mib( "tcp" )) != -1) + { + if ((data = read_mib_entry( fd, MIB2_TCP, MIB2_TCP_CONN, &len ))) + { + for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++) + { + row.dwLocalAddr = entry->tcpConnLocalAddress; + row.dwLocalPort = htons( entry->tcpConnLocalPort ); + row.dwRemoteAddr = entry->tcpConnRemAddress; + row.dwRemotePort = htons( entry->tcpConnRemPort ); + row.dwState = entry->tcpConnState; + if (!(table = append_tcp_row( heap, flags, table, &count, &row ))) 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; diff --git a/include/config.h.in b/include/config.h.in index f3bd7757dee..2b7c655e4a9 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -240,6 +240,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IEEEFP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_INET_MIB2_H + /* Define to 1 if you have the `inet_network' function. */ #undef HAVE_INET_NETWORK @@ -708,6 +711,9 @@ /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP +/* Define to 1 if you have the header file. */ +#undef HAVE_STROPTS_H + /* Define to 1 if you have the `strtold' function. */ #undef HAVE_STRTOLD @@ -906,6 +912,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_THR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIHDR_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMEOUT_H