summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/kernel/qnetworkinterface.cpp46
-rw-r--r--src/network/kernel/qnetworkinterface.h2
-rw-r--r--src/network/kernel/qnetworkinterface_p.h3
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp58
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp43
-rw-r--r--src/network/kernel/qnetworkinterface_winrt.cpp14
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp26
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp6
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp5
10 files changed, 167 insertions, 40 deletions
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 4a527052d1..81906edc47 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -519,6 +519,31 @@ QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const
}
/*!
+ \since 5.7
+
+ Returns the index of the interface whose name is \a name or 0 if there is
+ no interface with that name. This function should produce the same result
+ as the following code, but will probably execute faster.
+
+ \code
+ QNetworkInterface::interfaceFromName(name).index()
+ \endcode
+
+ \sa interfaceFromName(), interfaceNameFromIndex(), QUdpDatagram::interfaceIndex()
+*/
+int QNetworkInterface::interfaceIndexFromName(const QString &name)
+{
+ if (name.isEmpty())
+ return 0;
+
+ bool ok;
+ uint id = name.toUInt(&ok);
+ if (!ok)
+ id = QNetworkInterfaceManager::interfaceIndexFromName(name);
+ return int(id);
+}
+
+/*!
Returns a QNetworkInterface object for the interface named \a
name. If no such interface exists, this function returns an
invalid QNetworkInterface object.
@@ -553,6 +578,27 @@ QNetworkInterface QNetworkInterface::interfaceFromIndex(int index)
}
/*!
+ \since 5.7
+
+ Returns the name of the interface whose index is \a index or an empty
+ string if there is no interface with that index. This function should
+ produce the same result as the following code, but will probably execute
+ faster.
+
+ \code
+ QNetworkInterface::interfaceFromIndex(index).name()
+ \endcode
+
+ \sa interfaceFromIndex(), interfaceIndexFromName(), QUdpDatagram::interfaceIndex()
+*/
+QString QNetworkInterface::interfaceNameFromIndex(int index)
+{
+ if (!index)
+ return QString();
+ return QNetworkInterfaceManager::interfaceNameFromIndex(index);
+}
+
+/*!
Returns a listing of all the network interfaces found on the host
machine. In case of failure it returns a list with zero elements.
*/
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index b3daa3d4a0..bd57aea1cb 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -113,8 +113,10 @@ public:
QString hardwareAddress() const;
QList<QNetworkAddressEntry> addressEntries() const;
+ static int interfaceIndexFromName(const QString &name);
static QNetworkInterface interfaceFromName(const QString &name);
static QNetworkInterface interfaceFromIndex(int index);
+ static QString interfaceNameFromIndex(int index);
static QList<QNetworkInterface> allInterfaces();
static QList<QHostAddress> allAddresses();
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index 140a28c536..146ba7820c 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -100,6 +100,9 @@ public:
QSharedDataPointer<QNetworkInterfacePrivate> interfaceFromIndex(int index);
QList<QSharedDataPointer<QNetworkInterfacePrivate> > allInterfaces();
+ static uint interfaceIndexFromName(const QString &name);
+ static QString interfaceNameFromIndex(uint index);
+
// convenience:
QSharedDataPointer<QNetworkInterfacePrivate> empty;
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index cc53087024..541c78d838 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -93,14 +94,8 @@ static QHostAddress addressFromSockaddr(sockaddr *sa, int ifindex = 0, const QSt
// this is the most likely scenario:
// a scope ID in a socket is that of the interface this address came from
address.setScopeId(ifname);
- } else if (scope) {
-#ifndef QT_NO_IPV6IFNAME
- char scopeid[IFNAMSIZ];
- if (::if_indextoname(scope, scopeid)) {
- address.setScopeId(QLatin1String(scopeid));
- } else
-#endif
- address.setScopeId(QString::number(uint(scope)));
+ } else if (scope) {
+ address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(scope));
}
}
return address;
@@ -124,6 +119,53 @@ static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
return flags;
}
+uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
+{
+#ifndef QT_NO_IPV6IFNAME
+ return ::if_nametoindex(name.toLatin1());
+#elif defined(SIOCGIFINDEX)
+ struct ifreq req;
+ int socket = qt_safe_socket(AF_INET, SOCK_STREAM, 0);
+ if (socket < 0)
+ return 0;
+
+ QByteArray name8bit = name.toLatin1();
+ memset(&req, 0, sizeof(ifreq));
+ memcpy(req.ifr_name, name8bit, qMin<int>(name8bit.length() + 1, sizeof(req.ifr_name) - 1));
+
+ uint id = 0;
+ if (qt_safe_ioctl(socket, SIOCGIFINDEX, &req) >= 0)
+ id = req.ifr_ifindex;
+ qt_safe_close(socket);
+ return id;
+#else
+ return 0;
+#endif
+}
+
+QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
+{
+#ifndef QT_NO_IPV6IFNAME
+ char buf[IF_NAMESIZE];
+ if (::if_indextoname(index, buf))
+ return QString::fromLatin1(buf);
+#elif defined(SIOCGIFNAME)
+ struct ifreq req;
+ int socket = qt_safe_socket(AF_INET, SOCK_STREAM, 0);
+ if (socket >= 0) {
+ memset(&req, 0, sizeof(ifreq));
+ req.ifr_ifindex = index;
+
+ if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) {
+ qt_safe_close(socket);
+ return QString::fromLatin1(req.ifr_name);
+ }
+ qt_safe_close(socket);
+ }
+#endif
+ return QString::number(uint(index));
+}
+
#ifdef QT_NO_GETIFADDRS
// getifaddrs not available
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 907638f73e..238f913846 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -57,8 +57,14 @@
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()
{
@@ -71,10 +77,16 @@ static void resolveLibs()
#if defined(Q_OS_WINCE)
// since Windows Embedded Compact 7
+ ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceIndexToLuid");
ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToNameW");
+ ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToIndex");
+ ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceNameToLuidW");
#else
// since Windows Vista
+ ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceIndexToLuid");
ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW");
+ ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToIndex");
+ ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceNameToLuidW");
#endif
done = true;
}
@@ -92,13 +104,42 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
int scope = ((sockaddr_in6 *)sa)->sin6_scope_id;
if (scope)
- address.setScopeId(QString::number(scope));
+ address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(scope));
} else
qWarning("Got unknown socket family %d", sa->sa_family);
return address;
}
+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)
+ 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);
+ }
+ }
+
+ return QString::number(index);
+}
+
static QHash<QHostAddress, QHostAddress> ipv4Netmasks()
{
//Retrieve all the IPV4 addresses & netmasks
diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp
index 0234154427..88c0eae2f7 100644
--- a/src/network/kernel/qnetworkinterface_winrt.cpp
+++ b/src/network/kernel/qnetworkinterface_winrt.cpp
@@ -59,6 +59,20 @@ struct HostNameInfo {
QString address;
};
+uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
+{
+ // TBD - may not be possible
+ Q_UNUSED(name);
+ return 0;
+}
+
+QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
+{
+ // TBD - may not be possible
+ return QString::number(index);
+}
+
+
static QList<QNetworkInterfacePrivate *> interfaceListing()
{
QList<QNetworkInterfacePrivate *> interfaces;
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 0fa1d8f96e..5cc5e529fc 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -45,6 +45,7 @@
// We mean it.
//
#include "QtNetwork/qhostaddress.h"
+#include "QtNetwork/qnetworkinterface.h"
#include "private/qabstractsocketengine_p.h"
#ifndef Q_OS_WIN
# include "qplatformdefs.h"
@@ -264,7 +265,8 @@ public:
bool checkProxy(const QHostAddress &address);
bool fetchConnectionParameters();
- static uint scopeIdFromString(const QString &scopeid);
+ static uint scopeIdFromString(const QString &scopeid)
+ { return QNetworkInterface::interfaceIndexFromName(scopeid); }
/*! \internal
Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize.
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index c40eef769e..fab4d1c532 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -107,15 +107,8 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
QHostAddress tmpAddress;
tmpAddress.setAddress(tmp);
*addr = tmpAddress;
- if (s->a6.sin6_scope_id) {
-#ifndef QT_NO_IPV6IFNAME
- char scopeid[IFNAMSIZ];
- if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
- addr->setScopeId(QLatin1String(scopeid));
- } else
-#endif
- addr->setScopeId(QString::number(s->a6.sin6_scope_id));
- }
+ if (s->a6.sin6_scope_id)
+ addr->setScopeId(QNetworkInterface::interfaceNameFromIndex(s->a6.sin6_scope_id));
}
if (port)
*port = ntohs(s->a6.sin6_port);
@@ -131,21 +124,6 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
}
}
-// inline on purpose
-inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
-{
- if (scopeid.isEmpty())
- return 0;
-
- bool ok;
- uint id = scopeid.toUInt(&ok);
-#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- id = ::if_nametoindex(scopeid.toLatin1());
-#endif
- return id;
-}
-
static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n)
{
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 9aed0caa25..a7fb5f5502 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -322,12 +322,6 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
-// inline on purpose
-inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
-{
- return scopeid.toUInt();
-}
-
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 64623df960..2a0552b770 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -203,6 +203,11 @@ void tst_QNetworkInterface::interfaceFromXXX()
QFETCH(QNetworkInterface, iface);
QVERIFY(QNetworkInterface::interfaceFromName(iface.name()).isValid());
+ if (int idx = iface.index()) {
+ QVERIFY(QNetworkInterface::interfaceFromIndex(idx).isValid());
+ QCOMPARE(QNetworkInterface::interfaceNameFromIndex(idx), iface.name());
+ QCOMPARE(QNetworkInterface::interfaceIndexFromName(iface.name()), idx);
+ }
foreach (QNetworkAddressEntry entry, iface.addressEntries()) {
QVERIFY(!entry.ip().isNull());