CVS: winex/dlls/iphlpapi iphlpapi_main.c, 1.12, 1.13 ipstats.c, 1.6, 1.7 ipstats.h, 1.3, 1.4

[email protected]
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/dlls/iphlpapi iphlpapi_main.c,1.12,1.13 ipstats.c,1.6,1.7 ipstats.h,1.3,1.4Update of /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi
In directory agravaine:/tmp/cvs-serv21475/dlls/iphlpapi

Modified Files:
	iphlpapi_main.c ipstats.c ipstats.h 
Log Message:
- add support for GetTcpTable on Mac OS X
(change by Mark)


Index: iphlpapi_main.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/iphlpapi_main.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- iphlpapi_main.c	27 Apr 2007 13:08:30 -0000	1.12
+++ iphlpapi_main.c	27 Jun 2007 11:45:04 -0000	1.13
@@ -336,7 +336,9 @@
 
   TRACE("ppTcpTable %p, bOrder %d, heap %p, flags 0x%08x\n",
    ppTcpTable, bOrder, heap, flags);
-  ret = getTcpTable(ppTcpTable, heap, flags);
+
+  *ppTcpTable = NULL;
+  ret = getTcpTable(ppTcpTable, 0, heap, flags);
   if (!ret && bOrder)
     qsort((*ppTcpTable)->table, (*ppTcpTable)->dwNumEntries,
      sizeof(MIB_TCPROW), TcpTableSorter);
@@ -1545,25 +1547,16 @@
       ret = ERROR_INSUFFICIENT_BUFFER;
     }
     else {
-      PMIB_TCPTABLE table;
-
-      ret = getTcpTable(&table, GetProcessHeap(), 0);
+      ret = getTcpTable(&pTcpTable, numEntries, 0, 0);
       if (!ret) {
-        size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
+        size = sizeof(MIB_TCPTABLE) + (pTcpTable->dwNumEntries - 1) *
          sizeof(MIB_TCPROW);
-        if (*pdwSize < size) {
-          *pdwSize = size;
-          ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else {
-          *pdwSize = size;
-          memcpy(pTcpTable, table, size);
+        *pdwSize = size;
+
           if (bOrder)
-            qsort(pTcpTable->table, pTcpTable->dwNumEntries,
-             sizeof(MIB_TCPROW), TcpTableSorter);
+             qsort(pTcpTable->table, pTcpTable->dwNumEntries,
+                   sizeof(MIB_TCPROW), TcpTableSorter);
           ret = NO_ERROR;
-        }
-        HeapFree(GetProcessHeap(), 0, table);
       }
       else
         ret = ERROR_OUTOFMEMORY;

Index: ipstats.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/ipstats.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ipstats.c	30 Mar 2007 20:25:44 -0000	1.6
+++ ipstats.c	27 Jun 2007 11:45:04 -0000	1.7
@@ -1,4 +1,5 @@
 /* Copyright (C) 2003,2006 Juan Lang
+ * Copyright (C) 2007 TransGaming Technologies Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,6 +31,9 @@
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
+#ifdef HAVE_SYS_SOCKETVAR_H
+#include <sys/socketvar.h>
+#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -51,12 +55,25 @@
 #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_VAR_H
+#include <netinet/tcp_var.h>
+#endif
+#ifdef HAVE_NETINET_IP_VAR_H
+#include <netinet/ip_var.h>
+#endif
 
-#ifdef __APPLE__
+#ifdef HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
+#endif
 
+#ifndef ROUNDUP
 #define ROUNDUP(a) \
 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#endif
+#ifndef ADVANCE
 #define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
 #endif
 
@@ -66,7 +83,7 @@
 #include "ifenum.h"
 #include "ipstats.h"
 
-#ifdef linux
+#ifndef HAVE_NETINET_TCP_FSM_H
 #define TCPS_ESTABLISHED  1
 #define TCPS_SYN_SENT     2
 #define TCPS_SYN_RECEIVED 3
@@ -564,6 +581,100 @@
 
 static DWORD getNumWithOneHeader(const char *filename)
 {
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+   size_t Len = 0;
+   char *Buf;
+   struct xinpgen *pXIG, *pOrigXIG;
+   int Protocol;
+   DWORD NumEntries = 0;
+
+   if (!strcmp (filename, "net.inet.tcp.pcblist"))
+      Protocol = IPPROTO_TCP;
+   else if (!strcmp (filename, "net.inet.udp.pcblist"))
+      Protocol = IPPROTO_UDP;
+   else
+   {
+      ERR ("Unsupported mib '%s', needs protocol mapping\n",
+           filename);
+      return 0;
+   }
+
+   if (sysctlbyname (filename, NULL, &Len, NULL, 0) < 0)
+   {
+      WARN ("Unable to read '%s' via sysctlbyname\n", filename);
+      return 0;
+   }
+
+   Buf = HeapAlloc (GetProcessHeap (), 0, Len);
+   if (!Buf)
+   {
+      ERR ("Out of memory!\n");
+      return 0;
+   }
+
+   if (sysctlbyname (filename, Buf, &Len, NULL, 0) < 0)
+   {
+      ERR ("Failure to read '%s' via sysctlbyname!\n", filename);
+      HeapFree (GetProcessHeap (), 0, Buf);
+      return 0;
+   }
+
+   /* Might be nothing here; first entry is just a header it seems */
+   if (Len <= sizeof (struct xinpgen))
+   {
+      HeapFree (GetProcessHeap (), 0, Buf);
+      return 0;
+   }
+
+   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))
+   {
+      struct tcpcb *pTCPData = NULL;
+      struct inpcb *pINData;
+      struct xsocket *pSockData;
+
+      if (Protocol == IPPROTO_TCP)
+      {
+         pTCPData = &((struct xtcpcb *)pXIG)->xt_tp;
+         pINData = &((struct xtcpcb *)pXIG)->xt_inp;
+         pSockData = &((struct xtcpcb *)pXIG)->xt_socket;
+      }
+      else
+      {
+         pINData = &((struct xinpcb *)pXIG)->xi_inp;
+         pSockData = &((struct xinpcb *)pXIG)->xi_socket;
+      }
+
+      /* Ignore sockets for other protocols */
+      if (pSockData->xso_protocol != Protocol)
+         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 &&
+          !pINData->inp_faddr.s_addr &&
+          !pINData->inp_fport)
+         continue;
+
+      NumEntries++;
+   }
+
+   HeapFree (GetProcessHeap (), 0, Buf);
+   return NumEntries;
+#else
   FILE *fp;
   int ret = 0;
 
@@ -586,6 +697,7 @@
      ERR ("Unable to open '%s' to count entries!\n", filename);
 
   return ret;
+#endif
 }
 
 DWORD getNumRoutes(void)
@@ -1026,132 +1138,209 @@
   return ret;
 }
 
+
 DWORD getNumTcpEntries(void)
 {
-  return getNumWithOneHeader("/proc/net/tcp");
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+   return getNumWithOneHeader ("net.inet.tcp.pcblist");
+#else
+   return getNumWithOneHeader ("/proc/net/tcp");
+#endif
 }
 
-DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
+
+/* Why not a lookup table? Because the TCPS_* constants are different
+   on different platforms */
+static DWORD TCPStateToMIBState (int state)
 {
-  DWORD ret;
+   switch (state)
+   {
+      case TCPS_ESTABLISHED: return MIB_TCP_STATE_ESTAB;
+      case TCPS_SYN_SENT: return MIB_TCP_STATE_SYN_SENT;
+      case TCPS_SYN_RECEIVED: return MIB_TCP_STATE_SYN_RCVD;
+      case TCPS_FIN_WAIT_1: return MIB_TCP_STATE_FIN_WAIT1;
+      case TCPS_FIN_WAIT_2: return MIB_TCP_STATE_FIN_WAIT2;
+      case TCPS_TIME_WAIT: return MIB_TCP_STATE_TIME_WAIT;
+      case TCPS_CLOSE_WAIT: return MIB_TCP_STATE_CLOSE_WAIT;
+      case TCPS_LAST_ACK: return MIB_TCP_STATE_LAST_ACK;
+      case TCPS_LISTEN: return MIB_TCP_STATE_LISTEN;
+      case TCPS_CLOSING: return MIB_TCP_STATE_CLOSING;
+      default:
+      case TCPS_CLOSED: return MIB_TCP_STATE_CLOSED;
+   }
+}
 
-#ifdef __APPLE__
-  ERR ("unimplemented!\n");
-  return ERROR_INVALID_PARAMETER;
+
+DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, DWORD maxEntries, HANDLE heap,
+                  DWORD flags)
+{
+   DWORD numEntries;
+   PMIB_TCPTABLE table;
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
+   size_t Len = 0;
+   char *Buf;
+   struct xinpgen *pXIG, *pOrigXIG;
+#else
+   FILE *fp;
+   char buf[512] = { 0 }, *ptr;
 #endif
 
-  if (!ppTcpTable)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numEntries = getNumTcpEntries();
-    PMIB_TCPTABLE table = HeapAlloc(heap, flags,
-     sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
+   if (!ppTcpTable)
+      return ERROR_INVALID_PARAMETER;
 
-    if (table) {
-      FILE *fp;
+   numEntries = getNumTcpEntries ();
 
-      ret = NO_ERROR;
-      *ppTcpTable = table;
-      table->dwNumEntries = 0;
-      /* get from /proc/net/tcp, no error if can't */
-      fp = fopen("/proc/net/tcp", "r");
-      if (fp) {
-        char buf[512] = { 0 }, *ptr;
+   if (!*ppTcpTable)
+   {
+      *ppTcpTable = HeapAlloc (heap, flags,
+                               sizeof (MIB_TCPTABLE) +
+                               (numEntries - 1) * sizeof (MIB_TCPROW));
+      if (!*ppTcpTable)
+      {
+         ERR ("Out of memory!\n");
+         return ERROR_OUTOFMEMORY;
+      }
+      maxEntries = numEntries;
+   }
 
-        /* skip header line */
-        ptr = fgets(buf, sizeof(buf), fp);
-        while (ptr && table->dwNumEntries < numEntries) {
-          memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_TCPROW));
-          ptr = fgets(buf, sizeof(buf), fp);
-          if (ptr) {
-            char *endPtr;
+   table = *ppTcpTable;
+   table->dwNumEntries = 0;
+   if (!numEntries)
+      return NO_ERROR;
 
-            while (ptr && *ptr && *ptr != ':')
-              ptr++;
-            if (ptr && *ptr)
-              ptr++;
-            if (ptr && *ptr) {
-              table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              ptr++;
-              table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              table->table[table->dwNumEntries].dwRemoteAddr = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              ptr++;
-              table->table[table->dwNumEntries].dwRemotePort = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              DWORD state = strtoul(ptr, &endPtr, 16);
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H)
 
-              switch (state)
-              {
-                case TCPS_ESTABLISHED:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_ESTAB;
-                  break;
-                case TCPS_SYN_SENT:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_SYN_SENT;
-                  break;
-                case TCPS_SYN_RECEIVED:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_SYN_RCVD;
-                  break;
-                case TCPS_FIN_WAIT_1:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_FIN_WAIT1;
-                  break;
-                case TCPS_FIN_WAIT_2:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_FIN_WAIT2;
-                  break;
-                case TCPS_TIME_WAIT:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_TIME_WAIT;
-                  break;
-                case TCPS_CLOSED:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_CLOSED;
-                  break;
-                case TCPS_CLOSE_WAIT:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_CLOSE_WAIT;
-                  break;
-                case TCPS_LAST_ACK:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_LAST_ACK;
-                  break;
-                case TCPS_LISTEN:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_LISTEN;
-                  break;
-                case TCPS_CLOSING:
-                  table->table[table->dwNumEntries].dwState =
-                   MIB_TCP_STATE_CLOSING;
-                  break;
-              }
-              ptr = endPtr;
-            }
-            table->dwNumEntries++;
-          }
-        }
-        fclose(fp);
+   if (sysctlbyname ("net.inet.tcp.pcblist", NULL, &Len, NULL, 0) < 0)
+   {
+      ERR ("Failure to read net.inet.tcp.pcblist via sysctlbyname!\n");
+      return ERROR_OUTOFMEMORY;
+   }
+
+   Buf = HeapAlloc (GetProcessHeap (), 0, Len);
+   if (!Buf)
+   {
+      ERR ("Out of memory!\n");
+      return ERROR_OUTOFMEMORY;
+   }
+
+   if (sysctlbyname ("net.inet.tcp.pcblist", Buf, &Len, NULL, 0) < 0)
+   { 
+      ERR ("Failure to read net.inet.tcp.pcblist via sysctlbyname!\n");
+      HeapFree (GetProcessHeap (), 0, Buf);
+      return ERROR_OUTOFMEMORY;
+   }
+
+   /* Might be nothing here; first entry is just a header it seems */
+   if (Len <= sizeof (struct xinpgen))
+   {
+      HeapFree (GetProcessHeap (), 0, Buf);
+      return NO_ERROR;
+   }
+
+   pOrigXIG = (struct xinpgen *)Buf;
+   pXIG = pOrigXIG;
+
+   for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
+        (pXIG->xig_len > sizeof (struct xinpgen)) &&
+           (table->dwNumEntries < maxEntries);
+        pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
+   {
+      struct tcpcb *pTCPData = NULL;
+      struct inpcb *pINData;
+      struct xsocket *pSockData;
+
+      pTCPData = &((struct xtcpcb *)pXIG)->xt_tp;
+      pINData = &((struct xtcpcb *)pXIG)->xt_inp;
+      pSockData = &((struct xtcpcb *)pXIG)->xt_socket;
+
+      /* Ignore sockets for other protocols */
+      if (pSockData->xso_protocol != IPPROTO_TCP)
+         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 &&
+          !pINData->inp_faddr.s_addr &&
+          !pINData->inp_fport)
+         continue;
+
+      /* Fill in structure details */
+      table->table[table->dwNumEntries].dwLocalAddr =
+         pINData->inp_laddr.s_addr;
+      table->table[table->dwNumEntries].dwLocalPort =
+         pINData->inp_lport;
+      table->table[table->dwNumEntries].dwRemoteAddr =
+         pINData->inp_faddr.s_addr;
+      table->table[table->dwNumEntries].dwRemotePort =
+         pINData->inp_fport;
+      table->table[table->dwNumEntries].dwState =
+         TCPStateToMIBState (pTCPData->t_state);
+
+      table->dwNumEntries++;
+   }
+
+   HeapFree (GetProcessHeap (), 0, Buf);
+#else
+   /* get from /proc/net/tcp, no error if can't */
+   fp = fopen("/proc/net/tcp", "r");
+   if (!fp)
+      return NO_ERROR;
+
+   /* skip header line */
+   ptr = fgets(buf, sizeof(buf), fp);
+   while (ptr && table->dwNumEntries < maxEntries) {
+      memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_TCPROW));
+      ptr = fgets(buf, sizeof(buf), fp);
+      if (ptr) {
+         char *endPtr;
+
+         while (ptr && *ptr && *ptr != ':')
+            ptr++;
+         if (ptr && *ptr)
+            ptr++;
+         if (ptr && *ptr) {
+            table->table[table->dwNumEntries].dwLocalAddr =
+               strtoul(ptr, &endPtr, 16);
+            ptr = endPtr;
+         }
+         if (ptr && *ptr) {
+            ptr++;
+            table->table[table->dwNumEntries].dwLocalPort =
+               strtoul(ptr, &endPtr, 16);
+            ptr = endPtr;
+         }
+         if (ptr && *ptr) {
+            table->table[table->dwNumEntries].dwRemoteAddr =
+               strtoul(ptr, &endPtr, 16);
+            ptr = endPtr;
+         }
+         if (ptr && *ptr) {
+            ptr++;
+            table->table[table->dwNumEntries].dwRemotePort =
+               strtoul(ptr, &endPtr, 16);
+            ptr = endPtr;
+         }
+         if (ptr && *ptr) {
+            DWORD state = strtoul(ptr, &endPtr, 16);
+
+            table->table[table->dwNumEntries].dwState =
+               TCPStateToMIBState (state);
+            ptr = endPtr;
+         }
+         table->dwNumEntries++;
       }
-    }
-    else
-      ret = ERROR_OUTOFMEMORY;
-  }
-  return ret;
+   }
+   fclose(fp);
+#endif
+
+   return NO_ERROR;
 }

Index: ipstats.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/iphlpapi/ipstats.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ipstats.h	30 Mar 2007 20:11:02 -0000	1.3
+++ ipstats.h	27 Jun 2007 11:45:04 -0000	1.4
@@ -83,6 +83,7 @@
 /* Allocates the TCP state table from heap and returns it to you in *ppTcpTable.
  * Returns NO_ERROR on success, something else on failure.
  */
-DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags);
+DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, DWORD maxEntries, HANDLE heap,
+                  DWORD flags);
 
 #endif /* ndef WINE_IPSTATS_H_ */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.