summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2013-07-09 00:10:35 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-24 00:06:07 +0200
commit64a1448d87727878d9789906b2f4f5b9e3d74e38 (patch)
tree493abf633b59aad89d25783e55a22bdaba35ac3e
parent362ea2dedeeca351ae36fcf860cc47b2f12830cf (diff)
Update Linux interface getting to make fewer syscalls
Each time we call if_nametoindex, if_indextoname or somesuch, the libc needs to open a socket, make an ioctl, and close the socket. Since we've got most of the information we need anyway in the data from getifaddrs(3), let's just use it Change-Id: I572c212a27c4b9ffe57980b36f75bb04e6d5cf29 Reviewed-by: Jonas Gastal <gastal@intel.com> Reviewed-by: Richard J. Moore <rich@kde.org>
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp58
1 files changed, 29 insertions, 29 deletions
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index b090213861..01c082059f 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -312,38 +312,38 @@ QT_END_INCLUDE_NAMESPACE
static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
QList<QNetworkInterfacePrivate *> interfaces;
+ QSet<QString> seenInterfaces;
+ // on Linux, AF_PACKET addresses carry the hardware address and interface index;
+ // scan for them first (they're usually first, but we have no guarantee this
+ // will be the case forever)
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
- if ( !ptr->ifa_addr )
- continue;
-
- // Get the interface index
- int ifindex = if_nametoindex(ptr->ifa_name);
+ if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
+ sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
+ QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
+ interfaces << iface;
+ iface->index = sll->sll_ifindex;
+ iface->name = QString::fromLatin1(ptr->ifa_name);
+ iface->flags = convertFlags(ptr->ifa_flags);
+ iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
- // on Linux we use AF_PACKET and sockaddr_ll to obtain hHwAddress
- QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
- for ( ; if_it != interfaces.end(); ++if_it)
- if ((*if_it)->index == ifindex) {
- // this one has been added already
- if ( ptr->ifa_addr->sa_family == AF_PACKET
- && (*if_it)->hardwareAddress.isEmpty()) {
- sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
- (*if_it)->hardwareAddress = (*if_it)->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
- }
- break;
- }
- if ( if_it != interfaces.end() )
- continue;
+ seenInterfaces.insert(iface->name);
+ }
+ }
- QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
- interfaces << iface;
- iface->index = ifindex;
- iface->name = QString::fromLatin1(ptr->ifa_name);
- iface->flags = convertFlags(ptr->ifa_flags);
+ // see if we missed anything:
+ // virtual interfaces with no HW address have no AF_PACKET
+ for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
+ if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
+ QString name = QString::fromLatin1(ptr->ifa_name);
+ if (seenInterfaces.contains(name))
+ continue;
- if ( ptr->ifa_addr->sa_family == AF_PACKET ) {
- sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
- iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
+ QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
+ interfaces << iface;
+ iface->name = name;
+ iface->flags = convertFlags(ptr->ifa_flags);
+ iface->index = if_nametoindex(ptr->ifa_name);
}
}
@@ -423,11 +423,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
interfaces = createInterfaces(interfaceListing);
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
// Get the interface index
- int ifindex = if_nametoindex(ptr->ifa_name);
+ QString name = QString::fromLatin1(ptr->ifa_name);
QNetworkInterfacePrivate *iface = 0;
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
for ( ; if_it != interfaces.end(); ++if_it)
- if ((*if_it)->index == ifindex) {
+ if ((*if_it)->name == name) {
// found this interface already
iface = *if_it;
break;