From 64a1448d87727878d9789906b2f4f5b9e3d74e38 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 9 Jul 2013 00:10:35 -0700 Subject: 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 Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_unix.cpp | 58 +++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'src/network/kernel/qnetworkinterface_unix.cpp') diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index b0902138610..01c082059fd 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 createInterfaces(ifaddrs *rawList) { QList interfaces; + QSet 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::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 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::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; -- cgit v1.2.3