iphlpapi: Remove one IP address per interface restriction.
- remove restriction of one IP address per interface
- remove dead code, and make static functions that can be
- update comments and copyright notice
diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c
index 0283d36..31b0532 100644
--- a/dlls/iphlpapi/ifenum.c
+++ b/dlls/iphlpapi/ifenum.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Juan Lang
+/* Copyright (C) 2003,2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -455,38 +455,7 @@
return ret;
}
-DWORD getInterfaceIPAddrByName(const char *name)
-{
- DWORD ret = INADDR_ANY;
-
- if (name) {
- int fd = socket(PF_INET, SOCK_DGRAM, 0);
-
- if (fd != -1) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if (ioctl(fd, SIOCGIFADDR, &ifr) == 0)
- memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
- close(fd);
- }
- }
- return ret;
-}
-
-DWORD getInterfaceIPAddrByIndex(DWORD index)
-{
- DWORD ret;
- const char *name = getInterfaceNameByIndex(index);
-
- if (name)
- ret = getInterfaceIPAddrByName(name);
- else
- ret = INADDR_ANY;
- return ret;
-}
-
-DWORD getInterfaceBCastAddrByName(const char *name)
+static DWORD getInterfaceBCastAddrByName(const char *name)
{
DWORD ret = INADDR_ANY;
@@ -505,19 +474,7 @@
return ret;
}
-DWORD getInterfaceBCastAddrByIndex(DWORD index)
-{
- DWORD ret;
- const char *name = getInterfaceNameByIndex(index);
-
- if (name)
- ret = getInterfaceBCastAddrByName(name);
- else
- ret = INADDR_ANY;
- return ret;
-}
-
-DWORD getInterfaceMaskByName(const char *name)
+static DWORD getInterfaceMaskByName(const char *name)
{
DWORD ret = INADDR_NONE;
@@ -536,18 +493,6 @@
return ret;
}
-DWORD getInterfaceMaskByIndex(DWORD index)
-{
- DWORD ret;
- const char *name = getInterfaceNameByIndex(index);
-
- if (name)
- ret = getInterfaceMaskByName(name);
- else
- ret = INADDR_NONE;
- return ret;
-}
-
#if defined (SIOCGIFHWADDR)
DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
PDWORD type)
@@ -657,12 +602,16 @@
else {
struct arpreq arp;
struct sockaddr_in *saddr;
+ struct ifreq ifr;
+ /* get IP addr */
+ lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
+ ioctl(fd, SIOCGIFADDR, &ifr);
memset(&arp, 0, sizeof(struct arpreq));
arp.arp_pa.sa_family = AF_INET;
saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */
saddr->sin_family = AF_INET;
- saddr->sin_addr.s_addr = getInterfaceIPAddrByName(name);
+ memcpy(&saddr->sin_addr.s_addr, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
if ((ioctl(fd, SIOCGARP, &arp)))
ret = ERROR_INVALID_DATA;
else {
@@ -793,7 +742,7 @@
return ERROR_INVALID_DATA;
}
-DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
+static DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
{
DWORD ret;
int fd;
@@ -825,17 +774,7 @@
return ret;
}
-DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu)
-{
- const char *name = getInterfaceNameByIndex(index);
-
- if (name)
- return getInterfaceMtuByName(name, mtu);
- else
- return ERROR_INVALID_DATA;
-}
-
-DWORD getInterfaceStatusByName(const char *name, PDWORD status)
+static DWORD getInterfaceStatusByName(const char *name, PDWORD status)
{
DWORD ret;
int fd;
@@ -866,16 +805,6 @@
return ret;
}
-DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status)
-{
- const char *name = getInterfaceNameByIndex(index);
-
- if (name)
- return getInterfaceStatusByName(name, status);
- else
- return ERROR_INVALID_DATA;
-}
-
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
{
BYTE addr[MAX_INTERFACE_PHYSADDR];
@@ -927,6 +856,74 @@
return ERROR_INVALID_DATA;
}
+/* 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.
+ * Free ifc->ifc_buf using HeapFree.
+ * Returns NO_ERROR on success, something else on failure.
+ */
+static DWORD enumIPAddresses(PDWORD pcAddresses, struct ifconf *ifc)
+{
+ DWORD ret;
+ int fd;
+
+ fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (fd != -1) {
+ int ioctlRet = 0;
+ DWORD guessedNumAddresses = 0, numAddresses = 0;
+ caddr_t ifPtr;
+
+ ret = NO_ERROR;
+ ifc->ifc_len = 0;
+ ifc->ifc_buf = NULL;
+ /* there is no way to know the interface count beforehand,
+ so we need to loop again and again upping our max each time
+ until returned < max */
+ do {
+ HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
+ if (guessedNumAddresses == 0)
+ guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
+ else
+ guessedNumAddresses *= 2;
+ ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
+ ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len);
+ ioctlRet = ioctl(fd, SIOCGIFCONF, ifc);
+ } while (ioctlRet == 0 &&
+ ifc->ifc_len == (sizeof(struct ifreq) * guessedNumAddresses));
+
+ if (ioctlRet == 0) {
+ ifPtr = ifc->ifc_buf;
+ while (ifPtr && ifPtr < ifc->ifc_buf + ifc->ifc_len) {
+ numAddresses++;
+ ifPtr += ifreq_len((struct ifreq *)ifPtr);
+ }
+ }
+ else
+ ret = ERROR_INVALID_PARAMETER; /* FIXME: map from errno to Win32 */
+ if (!ret)
+ *pcAddresses = numAddresses;
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
+ ifc->ifc_buf = NULL;
+ }
+ close(fd);
+ }
+ else
+ ret = ERROR_NO_SYSTEM_RESOURCES;
+ return ret;
+}
+
+DWORD getNumIPAddresses(void)
+{
+ DWORD numAddresses = 0;
+ struct ifconf ifc;
+
+ if (!enumIPAddresses(&numAddresses, &ifc))
+ HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
+ return numAddresses;
+}
+
DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
{
DWORD ret;
@@ -935,84 +932,50 @@
ret = ERROR_INVALID_PARAMETER;
else
{
- int fd;
+ DWORD numAddresses = 0;
+ struct ifconf ifc;
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- int ioctlRet;
- DWORD guessedNumAddresses, numAddresses;
- struct ifconf ifc;
- caddr_t ifPtr;
+ ret = enumIPAddresses(&numAddresses, &ifc);
+ if (!ret)
+ {
+ *ppIpAddrTable = HeapAlloc(heap, flags, sizeof(MIB_IPADDRTABLE) +
+ (numAddresses - 1) * sizeof(MIB_IPADDRROW));
+ if (*ppIpAddrTable) {
+ DWORD i = 0, bcast;
+ caddr_t ifPtr;
- guessedNumAddresses = 0;
- ioctlRet = 0;
- memset(&ifc, 0, sizeof(ifc));
- /* there is no way to know the interface count beforehand,
- so we need to loop again and again upping our max each time
- until returned < max */
- do {
- if (guessedNumAddresses == 0)
- guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
- else
- guessedNumAddresses *= 2;
- HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
- ifc.ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
- ifc.ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc.ifc_len);
- ioctlRet = ioctl(fd, SIOCGIFCONF, &ifc);
- } while (ioctlRet == 0 &&
- ifc.ifc_len == (sizeof(struct ifreq) * guessedNumAddresses));
-
- if (ioctlRet == 0) {
- numAddresses = 0;
+ ret = NO_ERROR;
+ (*ppIpAddrTable)->dwNumEntries = numAddresses;
ifPtr = ifc.ifc_buf;
- while (ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
- numAddresses++;
- ifPtr += ifreq_len((struct ifreq *)ifPtr);
+ while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
+ struct ifreq *ifr = (struct ifreq *)ifPtr;
+
+ 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;
+ ifPtr += ifreq_len(ifr);
+ i++;
}
- *ppIpAddrTable = HeapAlloc(heap, flags, sizeof(MIB_IPADDRTABLE) +
- (numAddresses - 1) * sizeof(MIB_IPADDRROW));
- if (*ppIpAddrTable) {
- DWORD i = 0, bcast;
-
- ret = NO_ERROR;
- (*ppIpAddrTable)->dwNumEntries = numAddresses;
- ifPtr = ifc.ifc_buf;
- while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) {
- struct ifreq *ifr = (struct ifreq *)ifPtr;
-
- ret = getInterfaceIndexByName(ifr->ifr_name,
- &(*ppIpAddrTable)->table[i].dwIndex);
- (*ppIpAddrTable)->table[i].dwAddr =
- getInterfaceIPAddrByIndex((*ppIpAddrTable)->table[i].dwIndex);
- (*ppIpAddrTable)->table[i].dwMask =
- getInterfaceMaskByIndex((*ppIpAddrTable)->table[i].dwIndex);
- /* 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 = getInterfaceBCastAddrByIndex(
- (*ppIpAddrTable)->table[i].dwIndex);
- (*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;
- ifPtr += ifreq_len(ifr);
- i++;
- }
- }
- else
- ret = ERROR_OUTOFMEMORY;
}
else
- ret = ERROR_INVALID_PARAMETER;
+ ret = ERROR_OUTOFMEMORY;
HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
- close(fd);
}
- else
- ret = ERROR_NO_SYSTEM_RESOURCES;
}
return ret;
}
diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h
index 3dd9135..75a2ad4 100644
--- a/dlls/iphlpapi/ifenum.h
+++ b/dlls/iphlpapi/ifenum.h
@@ -1,5 +1,5 @@
/* ifenum.h
- * Copyright (C) 2003 Juan Lang
+ * Copyright (C) 2003,2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -81,16 +81,6 @@
*/
DWORD getInterfaceIndexByName(const char *name, PDWORD index);
-/* This bunch returns IP addresses, and INADDR_ANY or INADDR_NONE if not found,
- * appropriately depending on the f/n.
- */
-DWORD getInterfaceIPAddrByName(const char *name);
-DWORD getInterfaceIPAddrByIndex(DWORD index);
-DWORD getInterfaceMaskByName(const char *name);
-DWORD getInterfaceMaskByIndex(DWORD index);
-DWORD getInterfaceBCastAddrByName(const char *name);
-DWORD getInterfaceBCastAddrByIndex(DWORD index);
-
/* Gets a few physical charactersistics of a device: MAC addr len, MAC addr,
* and type as one of the MIB_IF_TYPEs.
* len's in-out: on in, needs to say how many bytes are available in addr,
@@ -109,14 +99,6 @@
DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
PDWORD type);
-/* Get the operational status as a (MIB_)IF_OPER_STATUS type.
- */
-DWORD getInterfaceStatusByName(const char *name, PDWORD status);
-DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status);
-
-DWORD getInterfaceMtuByName(const char *name, PDWORD mtu);
-DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu);
-
/* Fills in the MIB_IFROW by name/index. Doesn't fill in interface statistics,
* see ipstats.h for that.
* Returns ERROR_INVALID_PARAMETER if name or entry is NULL, ERROR_INVALID_DATA
@@ -125,6 +107,8 @@
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry);
DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry);
+DWORD getNumIPAddresses(void);
+
/* Gets the configured IP addresses for the system, and sets *ppIpAddrTable to
* a table of them allocated from heap, or NULL if out of memory. Returns
* NO_ERROR on success, something else on failure. Note there may be more than
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index df90fd6..9e43db0 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -1,7 +1,7 @@
/*
* iphlpapi dll implementation
*
- * Copyright (C) 2003 Juan Lang
+ * Copyright (C) 2003,2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -618,6 +618,7 @@
DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
{
FIXME("(AdapterName %p, IfIndex %p): stub\n", AdapterName, IfIndex);
+ /* FIXME: implement using getInterfaceIndexByName */
return ERROR_NOT_SUPPORTED;
}
@@ -646,22 +647,34 @@
DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
if (numNonLoopbackInterfaces > 0) {
- /* this calculation assumes only one address in the IP_ADDR_STRING lists.
- that's okay, because:
- - we don't get multiple addresses per adapter anyway
- - we don't know about per-adapter gateways
- - DHCP and WINS servers can have max one entry per list */
- ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
+ DWORD numIPAddresses = getNumIPAddresses();
+ ULONG size;
+ /* This may slightly overestimate the amount of space needed, because
+ * the IP addresses include the loopback address, but it's easier
+ * to make sure there's more than enough space than to make sure there's
+ * precisely enough space.
+ */
+ size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
+ if (numIPAddresses > numNonLoopbackInterfaces)
+ size += (numIPAddresses - numNonLoopbackInterfaces) *
+ sizeof(IP_ADDR_STRING);
if (!pAdapterInfo || *pOutBufLen < size) {
*pOutBufLen = size;
ret = ERROR_BUFFER_OVERFLOW;
}
else {
- InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
+ InterfaceIndexTable *table = NULL;
+ PMIB_IPADDRTABLE ipAddrTable = NULL;
+ ret = getIPAddrTable(&ipAddrTable, GetProcessHeap(), 0);
+ if (!ret)
+ table = getNonLoopbackInterfaceIndexTable();
if (table) {
size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
+ if (ipAddrTable->dwNumEntries > numNonLoopbackInterfaces)
+ size += (ipAddrTable->dwNumEntries - numNonLoopbackInterfaces) *
+ sizeof(IP_ADDR_STRING);
if (*pOutBufLen < size) {
*pOutBufLen = size;
ret = ERROR_INSUFFICIENT_BUFFER;
@@ -671,10 +684,13 @@
HKEY hKey;
BOOL winsEnabled = FALSE;
IP_ADDRESS_STRING primaryWINS, secondaryWINS;
+ PIP_ADDR_STRING nextIPAddr = (PIP_ADDR_STRING)((LPBYTE)pAdapterInfo
+ + numNonLoopbackInterfaces * sizeof(IP_ADAPTER_INFO));
memset(pAdapterInfo, 0, size);
/* @@ Wine registry key: HKCU\Software\Wine\Network */
- if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Network", &hKey) == ERROR_SUCCESS) {
+ if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Network",
+ &hKey) == ERROR_SUCCESS) {
DWORD size = sizeof(primaryWINS.String);
unsigned long addr;
@@ -693,7 +709,9 @@
}
for (ndx = 0; ndx < table->numIndexes; ndx++) {
PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
- DWORD addrLen = sizeof(ptr->Address), type;
+ DWORD addrLen = sizeof(ptr->Address), type, i;
+ PIP_ADDR_STRING currentIPAddr = &ptr->IpAddressList;
+ BOOL firstIPAddr = TRUE;
/* on Win98 this is left empty, but whatever */
lstrcpynA(ptr->AdapterName,
@@ -707,10 +725,26 @@
ptr->AddressLength = addrLen;
ptr->Type = type;
ptr->Index = table->indexes[ndx];
- toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
- ptr->IpAddressList.IpAddress.String);
- toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
- ptr->IpAddressList.IpMask.String);
+ for (i = 0; i < ipAddrTable->dwNumEntries; i++) {
+ if (ipAddrTable->table[i].dwIndex == ptr->Index) {
+ if (firstIPAddr) {
+ toIPAddressString(ipAddrTable->table[i].dwAddr,
+ ptr->IpAddressList.IpAddress.String);
+ toIPAddressString(ipAddrTable->table[i].dwBCastAddr,
+ ptr->IpAddressList.IpMask.String);
+ firstIPAddr = FALSE;
+ }
+ else {
+ currentIPAddr->Next = nextIPAddr;
+ currentIPAddr = nextIPAddr;
+ toIPAddressString(ipAddrTable->table[i].dwAddr,
+ currentIPAddr->IpAddress.String);
+ toIPAddressString(ipAddrTable->table[i].dwBCastAddr,
+ currentIPAddr->IpMask.String);
+ nextIPAddr++;
+ }
+ }
+ }
if (winsEnabled) {
ptr->HaveWins = TRUE;
memcpy(ptr->PrimaryWinsServer.IpAddress.String,
@@ -729,6 +763,8 @@
}
else
ret = ERROR_OUTOFMEMORY;
+ if (ipAddrTable)
+ HeapFree(GetProcessHeap(), 0, ipAddrTable);
}
}
else
@@ -1038,6 +1074,7 @@
else {
DWORD ndx;
+ *dwOutBufLen = size;
pIfTable->NumAdapters = 0;
for (ndx = 0; ndx < table->numIndexes; ndx++) {
const char *walker, *name;
@@ -1791,7 +1828,7 @@
DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
{
FIXME("(pIfRow %p): stub\n", pIfRow);
- /* this is supposed to set an administratively interface up or down.
+ /* this is supposed to set an interface administratively up or down.
Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
this sort of down is indistinguishable from other sorts of down (e.g. no
link). */
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 8a6d8d6..f49a7cd 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Juan Lang
+/* Copyright (C) 2003,2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h
index 7055d2b..15ce8bb 100644
--- a/dlls/iphlpapi/ipstats.h
+++ b/dlls/iphlpapi/ipstats.h
@@ -1,5 +1,5 @@
/* ipstats.h
- * Copyright (C) 2003 Juan Lang
+ * Copyright (C) 2003,2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public