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
This commit is contained in:
Juan Lang 2006-01-25 13:14:12 +01:00 committed by Alexandre Julliard
parent b825b8ba3c
commit 201cdcc462
5 changed files with 171 additions and 187 deletions

View File

@ -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 @@ InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void)
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 @@ DWORD getInterfaceBCastAddrByName(const char *name)
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 @@ DWORD getInterfaceMaskByName(const char *name)
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 @@ DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
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 @@ DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
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 @@ DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
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 @@ DWORD getInterfaceStatusByName(const char *name, PDWORD status)
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 @@ DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
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 @@ DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
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;
}

View File

@ -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 @@ const char *getInterfaceNameByIndex(DWORD index);
*/
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 getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
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 getInterfaceMtuByIndex(DWORD index, PDWORD mtu);
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

View File

@ -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 FlushIpNetTable(DWORD dwIfIndex)
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 WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
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 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
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 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
}
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 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
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 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
}
else
ret = ERROR_OUTOFMEMORY;
if (ipAddrTable)
HeapFree(GetProcessHeap(), 0, ipAddrTable);
}
}
else
@ -1038,6 +1074,7 @@ DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
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 SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAdd
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). */

View File

@ -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

View File

@ -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