summaryrefslogtreecommitdiffstats
path: root/src/network/kernel/qnetworkinterface_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/kernel/qnetworkinterface_win.cpp')
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp144
1 files changed, 30 insertions, 114 deletions
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 3002b2497b..64c3fa6f83 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -56,6 +56,7 @@
// (http://sourceforge.net/p/mingw-w64/mailman/message/32935366/)
#include <winsock2.h>
#include <ws2ipdef.h>
+#include <wincrypt.h>
#include <iphlpapi.h>
#include <ws2tcpip.h>
@@ -63,33 +64,6 @@
QT_BEGIN_NAMESPACE
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceIndexToLuid)(NET_IFINDEX, PNET_LUID);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToName)(const NET_LUID *, PWSTR, SIZE_T);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToIndex)(const NET_LUID *, PNET_IFINDEX);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceNameToLuid)(const WCHAR *, PNET_LUID);
-static PtrConvertInterfaceIndexToLuid ptrConvertInterfaceIndexToLuid = 0;
-static PtrConvertInterfaceLuidToName ptrConvertInterfaceLuidToName = 0;
-static PtrConvertInterfaceLuidToIndex ptrConvertInterfaceLuidToIndex = 0;
-static PtrConvertInterfaceNameToLuid ptrConvertInterfaceNameToLuid = 0;
-
-static void resolveLibs()
-{
- // try to find the functions we need from Iphlpapi.dll
- static bool done = false;
-
- if (!done) {
- HINSTANCE iphlpapiHnd = GetModuleHandle(L"iphlpapi");
- Q_ASSERT(iphlpapiHnd);
-
- // since Windows Vista
- ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceIndexToLuid");
- ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW");
- ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToIndex");
- ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceNameToLuidW");
- done = true;
- }
-}
-
static QHostAddress addressFromSockaddr(sockaddr *sa)
{
QHostAddress address;
@@ -111,80 +85,32 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
{
- resolveLibs();
- if (!ptrConvertInterfaceNameToLuid || !ptrConvertInterfaceLuidToIndex)
- return 0;
-
NET_IFINDEX id;
NET_LUID luid;
- if (ptrConvertInterfaceNameToLuid(reinterpret_cast<const wchar_t *>(name.constData()), &luid) == NO_ERROR
- && ptrConvertInterfaceLuidToIndex(&luid, &id) == NO_ERROR)
+ if (ConvertInterfaceNameToLuidW(reinterpret_cast<const wchar_t *>(name.constData()), &luid) == NO_ERROR
+ && ConvertInterfaceLuidToIndex(&luid, &id) == NO_ERROR)
return uint(id);
return 0;
}
QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
{
- resolveLibs();
- if (ptrConvertInterfaceIndexToLuid && ptrConvertInterfaceLuidToName) {
- NET_LUID luid;
- if (ptrConvertInterfaceIndexToLuid(index, &luid) == NO_ERROR) {
- WCHAR buf[IF_MAX_STRING_SIZE + 1];
- if (ptrConvertInterfaceLuidToName(&luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
- return QString::fromWCharArray(buf);
- }
+ NET_LUID luid;
+ if (ConvertInterfaceIndexToLuid(index, &luid) == NO_ERROR) {
+ WCHAR buf[IF_MAX_STRING_SIZE + 1];
+ if (ConvertInterfaceLuidToNameW(&luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
+ return QString::fromWCharArray(buf);
}
-
return QString::number(index);
}
-static QHash<QHostAddress, QHostAddress> ipv4Netmasks()
-{
- //Retrieve all the IPV4 addresses & netmasks
- IP_ADAPTER_INFO staticBuf[2]; // 2 is arbitrary
- PIP_ADAPTER_INFO pAdapter = staticBuf;
- ULONG bufSize = sizeof staticBuf;
- QHash<QHostAddress, QHostAddress> ipv4netmasks;
-
- DWORD retval = GetAdaptersInfo(pAdapter, &bufSize);
- if (retval == ERROR_BUFFER_OVERFLOW) {
- // need more memory
- pAdapter = (IP_ADAPTER_INFO *)malloc(bufSize);
- if (!pAdapter)
- return ipv4netmasks;
- // try again
- if (GetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
- free(pAdapter);
- return ipv4netmasks;
- }
- } else if (retval != ERROR_SUCCESS) {
- // error
- return ipv4netmasks;
- }
-
- // iterate over the list and add the entries to our listing
- for (PIP_ADAPTER_INFO ptr = pAdapter; ptr; ptr = ptr->Next) {
- for (PIP_ADDR_STRING addr = &ptr->IpAddressList; addr; addr = addr->Next) {
- QHostAddress address(QLatin1String(addr->IpAddress.String));
- QHostAddress mask(QLatin1String(addr->IpMask.String));
- ipv4netmasks[address] = mask;
- }
- }
- if (pAdapter != staticBuf)
- free(pAdapter);
-
- return ipv4netmasks;
-
-}
-
-static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
+static QList<QNetworkInterfacePrivate *> interfaceListing()
{
QList<QNetworkInterfacePrivate *> interfaces;
IP_ADAPTER_ADDRESSES staticBuf[2]; // 2 is arbitrary
PIP_ADAPTER_ADDRESSES pAdapter = staticBuf;
ULONG bufSize = sizeof staticBuf;
- const QHash<QHostAddress, QHostAddress> &ipv4netmasks = ipv4Netmasks();
ULONG flags = GAA_FLAG_INCLUDE_PREFIX |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_MULTICAST;
@@ -206,11 +132,17 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
// iterate over the list and add the entries to our listing
for (PIP_ADAPTER_ADDRESSES ptr = pAdapter; ptr; ptr = ptr->Next) {
+ // the structure grows over time, so let's make sure the fields
+ // introduced in Windows Vista are present (Luid is the furthest
+ // field we access from IP_ADAPTER_ADDRESSES_LH)
+ Q_ASSERT(ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid));
+ Q_ASSERT(ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Ipv6IfIndex));
+
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
iface->index = 0;
- if (ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Ipv6IfIndex) && ptr->Ipv6IfIndex != 0)
+ if (ptr->Ipv6IfIndex != 0)
iface->index = ptr->Ipv6IfIndex;
else if (ptr->IfIndex != 0)
iface->index = ptr->IfIndex;
@@ -223,13 +155,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
if (ptr->IfType == IF_TYPE_PPP)
iface->flags |= QNetworkInterface::IsPointToPoint;
- if (ptrConvertInterfaceLuidToName && ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid)) {
- // use ConvertInterfaceLuidToName because that returns a friendlier name, though not
- // as friendly as FriendlyName below
- WCHAR buf[IF_MAX_STRING_SIZE + 1];
- if (ptrConvertInterfaceLuidToName(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
- iface->name = QString::fromWCharArray(buf);
- }
+ // use ConvertInterfaceLuidToNameW because that returns a friendlier name, though not
+ // as "friendly" as FriendlyName below
+ WCHAR buf[IF_MAX_STRING_SIZE + 1];
+ if (ConvertInterfaceLuidToNameW(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
+ iface->name = QString::fromWCharArray(buf);
if (iface->name.isEmpty())
iface->name = QString::fromLocal8Bit(ptr->AdapterName);
@@ -241,28 +171,17 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
// loopback if it has no address
iface->flags |= QNetworkInterface::IsLoopBack;
- // The GetAdaptersAddresses call has an interesting semantic:
- // It can return a number N of addresses and a number M of prefixes.
- // But if you have IPv6 addresses, generally N > M.
- // I cannot find a way to relate the Address to the Prefix, aside from stopping
- // the iteration at the last Prefix entry and assume that it applies to all addresses
- // from that point on.
- PIP_ADAPTER_PREFIX pprefix = 0;
- if (ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, FirstPrefix))
- pprefix = ptr->FirstPrefix;
+ // parse the IP (unicast) addresses
for (PIP_ADAPTER_UNICAST_ADDRESS addr = ptr->FirstUnicastAddress; addr; addr = addr->Next) {
+ Q_ASSERT(addr->Length >= offsetof(IP_ADAPTER_UNICAST_ADDRESS, OnLinkPrefixLength));
+
+ // skip addresses in invalid state
+ if (addr->DadState == IpDadStateInvalid)
+ continue;
+
QNetworkAddressEntry entry;
entry.setIp(addressFromSockaddr(addr->Address.lpSockaddr));
- if (pprefix) {
- if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
- entry.setNetmask(ipv4netmasks[entry.ip()]);
-
- // broadcast address is set on postProcess()
- } else { //IPV6
- entry.setPrefixLength(pprefix->PrefixLength);
- }
- pprefix = pprefix->Next ? pprefix->Next : pprefix;
- }
+ entry.setPrefixLength(addr->OnLinkPrefixLength);
iface->addressEntries << entry;
}
}
@@ -275,14 +194,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
{
- resolveLibs();
- return interfaceListingWinXP();
+ return interfaceListing();
}
QString QHostInfo::localDomainName()
{
- resolveLibs();
-
FIXED_INFO info, *pinfo;
ULONG bufSize = sizeof info;
pinfo = &info;