Juan Lang : iphlpapi: Implement retrieving IPv4 addresses using getifaddrs, when available.

Alexandre Julliard julliard at winehq.org
Mon Nov 14 13:33:58 CST 2011


Module: wine
Branch: master
Commit: 25b014b6e73138db8087ee290c1b9a65fa15db15
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=25b014b6e73138db8087ee290c1b9a65fa15db15

Author: Juan Lang <juan.lang at gmail.com>
Date:   Sun Nov 13 12:37:43 2011 -0800

iphlpapi: Implement retrieving IPv4 addresses using getifaddrs, when available.

---

 dlls/iphlpapi/ifenum.c |  120 ++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 101 insertions(+), 19 deletions(-)

diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c
index a0d7577..d84caed 100644
--- a/dlls/iphlpapi/ifenum.c
+++ b/dlls/iphlpapi/ifenum.c
@@ -670,6 +670,102 @@ DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
   return ret;
 }
 
+static DWORD getIPAddrRowByName(PMIB_IPADDRROW ipAddrRow, const char *ifName,
+ const struct sockaddr *sa)
+{
+  DWORD ret, bcast;
+
+  ret = getInterfaceIndexByName(ifName, &ipAddrRow->dwIndex);
+  memcpy(&ipAddrRow->dwAddr, sa->sa_data + 2, sizeof(DWORD));
+  ipAddrRow->dwMask = getInterfaceMaskByName(ifName);
+  /* the dwBCastAddr member isn't the broadcast address, it indicates whether
+   * the interface uses the 1's broadcast address (1) or the 0's broadcast
+   * address (0).
+   */
+  bcast = getInterfaceBCastAddrByName(ifName);
+  ipAddrRow->dwBCastAddr = (bcast & ipAddrRow->dwMask) ? 1 : 0;
+  /* FIXME: hardcoded reasm size, not sure where to get it */
+  ipAddrRow->dwReasmSize = 65535;
+  ipAddrRow->unused1 = 0;
+  ipAddrRow->wType = 0;
+  return ret;
+}
+
+#ifdef HAVE_IFADDRS_H
+
+/* Counts the IPv4 addresses in the system using the return value from
+ * getifaddrs, returning the count.
+ */
+static DWORD countIPv4Addresses(struct ifaddrs *ifa)
+{
+  DWORD numAddresses = 0;
+
+  for (; ifa; ifa = ifa->ifa_next)
+    if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET)
+      numAddresses++;
+  return numAddresses;
+}
+
+DWORD getNumIPAddresses(void)
+{
+  DWORD numAddresses = 0;
+  struct ifaddrs *ifa;
+
+  if (!getifaddrs(&ifa))
+  {
+    numAddresses = countIPv4Addresses(ifa);
+    freeifaddrs(ifa);
+  }
+  return numAddresses;
+}
+
+DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
+{
+  DWORD ret;
+
+  if (!ppIpAddrTable)
+    ret = ERROR_INVALID_PARAMETER;
+  else
+  {
+    struct ifaddrs *ifa;
+
+    if (!getifaddrs(&ifa))
+    {
+      DWORD size = sizeof(MIB_IPADDRTABLE);
+      DWORD numAddresses = countIPv4Addresses(ifa);
+
+      if (numAddresses > 1)
+        size += (numAddresses - 1) * sizeof(MIB_IPADDRROW);
+      *ppIpAddrTable = HeapAlloc(heap, flags, size);
+      if (*ppIpAddrTable)
+      {
+        DWORD i = 0;
+        struct ifaddrs *ifp;
+
+        ret = NO_ERROR;
+        (*ppIpAddrTable)->dwNumEntries = numAddresses;
+        for (ifp = ifa; !ret && ifp; ifp = ifp->ifa_next)
+        {
+          if (!ifp->ifa_addr || ifp->ifa_addr->sa_family != AF_INET)
+            continue;
+
+          ret = getIPAddrRowByName(&(*ppIpAddrTable)->table[i], ifp->ifa_name,
+           ifp->ifa_addr);
+          i++;
+        }
+      }
+      else
+        ret = ERROR_OUTOFMEMORY;
+      freeifaddrs(ifa);
+    }
+    else
+      ret = ERROR_INVALID_PARAMETER;
+  }
+  return ret;
+}
+
+#else
+
 /* Enumerates the IP addresses in the system using SIOCGIFCONF, returning
  * the count to you in *pcAddresses.  It also returns to you the struct ifconf
  * used by the call to ioctl, so that you may process the addresses further.
@@ -763,7 +859,7 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
         size += (numAddresses - 1) * sizeof(MIB_IPADDRROW);
       *ppIpAddrTable = HeapAlloc(heap, flags, size);
       if (*ppIpAddrTable) {
-        DWORD i = 0, bcast;
+        DWORD i = 0;
         caddr_t ifPtr;
 
         ret = NO_ERROR;
@@ -777,24 +873,8 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
           if (ifr->ifr_addr.sa_family != AF_INET)
              continue;
 
-          ret = getInterfaceIndexByName(ifr->ifr_name,
-           &(*ppIpAddrTable)->table[i].dwIndex);
-          memcpy(&(*ppIpAddrTable)->table[i].dwAddr, ifr->ifr_addr.sa_data + 2,
-           sizeof(DWORD));
-          (*ppIpAddrTable)->table[i].dwMask =
-           getInterfaceMaskByName(ifr->ifr_name);
-          /* the dwBCastAddr member isn't the broadcast address, it indicates
-           * whether the interface uses the 1's broadcast address (1) or the
-           * 0's broadcast address (0).
-           */
-          bcast = getInterfaceBCastAddrByName(ifr->ifr_name);
-          (*ppIpAddrTable)->table[i].dwBCastAddr =
-           (bcast & (*ppIpAddrTable)->table[i].dwMask) ? 1 : 0;
-          /* FIXME: hardcoded reasm size, not sure where to get it */
-          (*ppIpAddrTable)->table[i].dwReasmSize = 65535;
-
-          (*ppIpAddrTable)->table[i].unused1 = 0;
-          (*ppIpAddrTable)->table[i].wType = 0;
+          ret = getIPAddrRowByName(&(*ppIpAddrTable)->table[i], ifr->ifr_name,
+           &ifr->ifr_addr);
           i++;
         }
       }
@@ -806,6 +886,8 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
   return ret;
 }
 
+#endif
+
 #ifdef HAVE_IFADDRS_H
 ULONG v6addressesFromIndex(DWORD index, SOCKET_ADDRESS **addrs, ULONG *num_addrs)
 {




More information about the wine-cvs mailing list