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