[PATCH 4/4] iphlpapi: Implement AllocateAndGetIpForwardTable() on top of GetIpForwardTable().

Huw Davies huw at codeweavers.com
Mon Aug 2 03:19:07 CDT 2021


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

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 7637553780a..4b13b42fc6a 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -2278,6 +2278,43 @@ err:
     return err;
 }
 
+/******************************************************************
+ *    AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
+ *
+ * Get the route table.
+ * Like GetIpForwardTable(), but allocate the returned table from heap.
+ *
+ * PARAMS
+ *  table            [Out] pointer into which the MIB_IPFORWARDTABLE is
+ *                         allocated and returned.
+ *  sort             [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 ppIfTable is NULL, other error codes
+ *  on failure, NO_ERROR on success.
+ */
+DWORD WINAPI AllocateAndGetIpForwardTableFromStack( MIB_IPFORWARDTABLE **table, BOOL sort, HANDLE heap, DWORD flags )
+{
+    DWORD err, size = FIELD_OFFSET(MIB_IPFORWARDTABLE, table[2]), attempt;
+
+    TRACE( "table %p, sort %d, heap %p, flags 0x%08x\n", table, sort, heap, flags );
+
+    for (attempt = 0; attempt < 5; attempt++)
+    {
+        *table = HeapAlloc( heap, flags, size );
+        if (!*table) return ERROR_NOT_ENOUGH_MEMORY;
+
+        err = GetIpForwardTable( *table, &size, sort );
+        if (!err) break;
+        HeapFree( heap, flags, *table );
+        if (err != ERROR_INSUFFICIENT_BUFFER) break;
+    }
+
+    return err;
+}
+
 static void forward_row2_fill( MIB_IPFORWARD_ROW2 *row, USHORT fam, void *key, struct nsi_ip_forward_rw *rw,
                                void *dyn, struct nsi_ip_forward_static *stat )
 {
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 43c481c749f..7bb4ff0603e 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -1220,271 +1220,6 @@ static void *append_table_row( HANDLE heap, DWORD flags, void *table, DWORD *tab
     return table;
 }
 
-static int compare_ipforward_rows(const void *a, const void *b)
-{
-    const MIB_IPFORWARDROW *rowA = a;
-    const MIB_IPFORWARDROW *rowB = b;
-    int ret;
-
-    if ((ret = rowA->dwForwardDest - rowB->dwForwardDest) != 0) return ret;
-    if ((ret = rowA->u2.dwForwardProto - rowB->u2.dwForwardProto) != 0) return ret;
-    if ((ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy) != 0) return ret;
-    return rowA->dwForwardNextHop - rowB->dwForwardNextHop;
-}
-
-/******************************************************************
- *    AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
- *
- * Get the route table.
- * Like GetIpForwardTable(), but allocate the returned table from heap.
- *
- * PARAMS
- *  ppIpForwardTable [Out] pointer into which the MIB_IPFORWARDTABLE 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 ppIfTable is NULL, other error codes
- *  on failure, NO_ERROR on success.
- */
-DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *ppIpForwardTable, BOOL bOrder,
-                                                   HANDLE heap, DWORD flags)
-{
-    MIB_IPFORWARDTABLE *table;
-    MIB_IPFORWARDROW row;
-    DWORD ret = NO_ERROR, count = 16, table_size = FIELD_OFFSET( MIB_IPFORWARDTABLE, table[count] );
-
-    TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppIpForwardTable, bOrder, heap, flags);
-
-    if (!ppIpForwardTable) return ERROR_INVALID_PARAMETER;
-
-    if (!(table = HeapAlloc( heap, flags, table_size )))
-        return ERROR_OUTOFMEMORY;
-
-    table->dwNumEntries = 0;
-
-#ifdef __linux__
-    {
-        FILE *fp;
-
-        if ((fp = fopen("/proc/net/route", "r")))
-        {
-            char buf[512], *ptr;
-            DWORD rtf_flags;
-
-            /* skip header line */
-            ptr = fgets(buf, sizeof(buf), fp);
-            while ((ptr = fgets(buf, sizeof(buf), fp)))
-            {
-                memset( &row, 0, sizeof(row) );
-
-                while (!isspace(*ptr)) ptr++;
-                *ptr++ = 0;
-                if (getInterfaceIndexByName(buf, &row.dwForwardIfIndex) != NO_ERROR)
-                    continue;
-
-                row.dwForwardDest = strtoul(ptr, &ptr, 16);
-                row.dwForwardNextHop = strtoul(ptr + 1, &ptr, 16);
-                rtf_flags = strtoul(ptr + 1, &ptr, 16);
-
-                if (!(rtf_flags & RTF_UP)) row.u1.ForwardType = MIB_IPROUTE_TYPE_INVALID;
-                else if (rtf_flags & RTF_GATEWAY) row.u1.ForwardType = MIB_IPROUTE_TYPE_INDIRECT;
-                else row.u1.ForwardType = MIB_IPROUTE_TYPE_DIRECT;
-
-                strtoul(ptr + 1, &ptr, 16); /* refcount, skip */
-                strtoul(ptr + 1, &ptr, 16); /* use, skip */
-                row.dwForwardMetric1 = strtoul(ptr + 1, &ptr, 16);
-                row.dwForwardMask = strtoul(ptr + 1, &ptr, 16);
-                /* FIXME: other protos might be appropriate, e.g. the default
-                 * route is typically set with MIB_IPPROTO_NETMGMT instead */
-                row.u2.ForwardProto = MIB_IPPROTO_LOCAL;
-
-                if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) )))
-                    break;
-            }
-            fclose(fp);
-        }
-        else ret = ERROR_NOT_SUPPORTED;
-    }
-#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
-    {
-        void *data;
-        int fd, len, namelen;
-        mib2_ipRouteEntry_t *entry;
-        char name[64];
-
-        if ((fd = open_streams_mib( NULL )) != -1)
-        {
-            if ((data = read_mib_entry( fd, MIB2_IP, MIB2_IP_ROUTE, &len )))
-            {
-                for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
-                {
-                    row.dwForwardDest      = entry->ipRouteDest;
-                    row.dwForwardMask      = entry->ipRouteMask;
-                    row.dwForwardPolicy    = 0;
-                    row.dwForwardNextHop   = entry->ipRouteNextHop;
-                    row.u1.dwForwardType   = entry->ipRouteType;
-                    row.u2.dwForwardProto  = entry->ipRouteProto;
-                    row.dwForwardAge       = entry->ipRouteAge;
-                    row.dwForwardNextHopAS = 0;
-                    row.dwForwardMetric1   = entry->ipRouteMetric1;
-                    row.dwForwardMetric2   = entry->ipRouteMetric2;
-                    row.dwForwardMetric3   = entry->ipRouteMetric3;
-                    row.dwForwardMetric4   = entry->ipRouteMetric4;
-                    row.dwForwardMetric5   = entry->ipRouteMetric5;
-                    namelen = min( sizeof(name) - 1, entry->ipRouteIfIndex.o_length );
-                    memcpy( name, entry->ipRouteIfIndex.o_bytes, namelen );
-                    name[namelen] = 0;
-                    getInterfaceIndexByName( name, &row.dwForwardIfIndex );
-                    if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) )))
-                        break;
-                }
-                HeapFree( GetProcessHeap(), 0, data );
-            }
-            close( fd );
-        }
-        else ret = ERROR_NOT_SUPPORTED;
-    }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
-    {
-       int mib[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
-       size_t needed;
-       char *buf = NULL, *lim, *next, *addrPtr;
-       struct rt_msghdr *rtm;
-
-       if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
-       {
-          ERR ("sysctl 1 failed!\n");
-          ret = ERROR_NOT_SUPPORTED;
-          goto done;
-       }
-
-       buf = HeapAlloc (GetProcessHeap (), 0, needed);
-       if (!buf)
-       {
-          ret = ERROR_OUTOFMEMORY;
-          goto done;
-       }
-
-       if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
-       {
-          ret = ERROR_NOT_SUPPORTED;
-          goto done;
-       }
-
-       lim = buf + needed;
-       for (next = buf; next < lim; next += rtm->rtm_msglen)
-       {
-          int i;
-          sa_family_t dst_family = AF_UNSPEC;
-
-          rtm = (struct rt_msghdr *)next;
-
-          if (rtm->rtm_type != RTM_GET)
-          {
-             WARN ("Got unexpected message type 0x%x!\n",
-                   rtm->rtm_type);
-             continue;
-          }
-
-          /* Ignore gateway routes which are multicast */
-          if ((rtm->rtm_flags & RTF_GATEWAY) && (rtm->rtm_flags & RTF_MULTICAST))
-             continue;
-
-          memset( &row, 0, sizeof(row) );
-          row.dwForwardIfIndex = rtm->rtm_index;
-          row.u1.ForwardType = (rtm->rtm_flags & RTF_GATEWAY) ? MIB_IPROUTE_TYPE_INDIRECT : MIB_IPROUTE_TYPE_DIRECT;
-          row.dwForwardMetric1 = rtm->rtm_rmx.rmx_hopcount;
-          row.u2.ForwardProto = MIB_IPPROTO_LOCAL;
-
-          addrPtr = (char *)(rtm + 1);
-
-          for (i = 1; i; i <<= 1)
-          {
-             struct sockaddr *sa;
-             DWORD addr;
-
-             if (!(i & rtm->rtm_addrs))
-                continue;
-
-             sa = (struct sockaddr *)addrPtr;
-             if (addrPtr + sa->sa_len > next + rtm->rtm_msglen)
-             {
-                ERR ("struct sockaddr extends beyond the route message, %p > %p\n",
-                   addrPtr + sa->sa_len, next + rtm->rtm_msglen );
-             }
-
-             ADVANCE (addrPtr, sa);
-
-             /* Apple's netstat prints the netmask together with the destination
-              * and only looks at the destination's address family. The netmask's
-              * sa_family sometimes contains the non-existent value 0xff. */
-             switch(i == RTA_NETMASK ? dst_family : sa->sa_family) {
-             case AF_INET: {
-                 /* Netmasks (and possibly other addresses) have only enough size
-                  * to represent the non-zero bits, e.g. a netmask of 255.0.0.0 has
-                  * 5 bytes (1 sa_len, 1 sa_family, 2 sa_port and 1 for the first
-                  * byte of sin_addr). Due to the alignment constraint we can de
-                  * facto read the full 4 bytes of sin_addr (except for the case of
-                  * netmask 0). Don't assume though that the extra bytes are zeroed. */
-                 struct sockaddr_in sin = {0};
-                 memcpy(&sin, sa, sa->sa_len);
-                 addr = sin.sin_addr.s_addr;
-                 break;
-             }
-#ifdef AF_LINK
-             case AF_LINK:
-                 if(i == RTA_GATEWAY && row.u1.ForwardType == MIB_IPROUTE_TYPE_DIRECT) {
-                     /* For direct route we may simply use dest addr as next hop */
-                     C_ASSERT(RTA_DST < RTA_GATEWAY);
-                     addr = row.dwForwardDest;
-                     break;
-                 }
-             /* fallthrough */
-#endif
-             default:
-                 WARN ("Received unsupported sockaddr family 0x%x\n", sa->sa_family);
-                 addr = 0;
-             }
-
-             switch (i)
-             {
-                case RTA_DST:
-                   row.dwForwardDest = addr;
-                   dst_family = sa->sa_family;
-                   break;
-                case RTA_GATEWAY: row.dwForwardNextHop = addr; break;
-                case RTA_NETMASK: row.dwForwardMask = addr; break;
-                default:
-                   WARN ("Unexpected address type 0x%x\n", i);
-             }
-          }
-
-          if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, sizeof(row) )))
-              break;
-       }
-done:
-      HeapFree( GetProcessHeap (), 0, buf );
-    }
-#else
-    FIXME( "not implemented\n" );
-    ret = ERROR_NOT_SUPPORTED;
-#endif
-
-    if (!table) return ERROR_OUTOFMEMORY;
-    if (!ret)
-    {
-        if (bOrder && table->dwNumEntries)
-            qsort( table->table, table->dwNumEntries, sizeof(row), compare_ipforward_rows );
-        *ppIpForwardTable = table;
-    }
-    else HeapFree( heap, flags, table );
-    TRACE( "returning ret %u table %p\n", ret, table );
-    return ret;
-}
-
 static int compare_ipnet_rows(const void *a, const void *b)
 {
     const MIB_IPNETROW *rowA = a;
-- 
2.23.0




More information about the wine-devel mailing list