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>
bb10
Thiago Macieira 2013-07-09 00:10:35 -07:00 committed by The Qt Project
parent 362ea2dede
commit 64a1448d87
1 changed files with 30 additions and 30 deletions

View File

@ -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);
// 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;
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
iface->index = ifindex;
iface->name = QString::fromLatin1(ptr->ifa_name);
iface->flags = convertFlags(ptr->ifa_flags);
if ( ptr->ifa_addr->sa_family == AF_PACKET ) {
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);
seenInterfaces.insert(iface->name);
}
}
// 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;
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;