summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/configure.json28
-rw-r--r--src/network/kernel/kernel.pri6
-rw-r--r--src/network/kernel/qnetworkinterface_linux.cpp359
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp38
-rw-r--r--src/network/kernel/qnetworkinterface_unix_p.h102
5 files changed, 495 insertions, 38 deletions
diff --git a/src/network/configure.json b/src/network/configure.json
index d46fbfc101..9d99605df0 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -116,6 +116,24 @@
},
"use": "network"
},
+ "linux-netlink": {
+ "label": "Linux AF_NETLINK sockets",
+ "type": "compile",
+ "test": {
+ "include": [ "asm/types.h", "linux/netlink.h", "linux/rtnetlink.h", "sys/socket.h" ],
+ "main": [
+ "struct rtattr rta = { };",
+ "struct ifinfomsg ifi = {};",
+ "struct ifaddrmsg ifa = {};",
+ "struct ifa_cacheinfo ci;",
+ "ci.ifa_prefered = ci.ifa_valid = 0;",
+ "(void)RTM_NEWLINK; (void)RTM_NEWADDR;",
+ "(void)IFLA_ADDRESS; (void)IFLA_IFNAME;",
+ "(void)IFA_ADDRESS; (void)IFA_LABEL; (void)IFA_CACHEINFO;",
+ "(void)(IFA_F_SECONDARY | IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_MANAGETEMPADDR);"
+ ]
+ }
+ },
"sctp": {
"label": "SCTP support",
"type": "compile",
@@ -161,6 +179,11 @@
"condition": "libs.libproxy",
"output": [ "privateFeature" ]
},
+ "linux-netlink": {
+ "label": "Linux AF_NETLINK",
+ "condition": "config.linux && tests.linux-netlink",
+ "output": [ "privateFeature" ]
+ },
"openssl": {
"label": "OpenSSL",
"enable": "input.openssl == 'yes' || input.openssl == 'linked' || input.openssl == 'runtime'",
@@ -310,6 +333,11 @@ For example:
"getifaddrs", "ipv6ifname", "libproxy",
{
"type": "feature",
+ "args": "linux-netlink",
+ "condition": "config.linux"
+ },
+ {
+ "type": "feature",
"args": "securetransport",
"condition": "config.darwin"
},
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 54b61f3ad3..806cdc85cf 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -17,6 +17,7 @@ HEADERS += kernel/qtnetworkglobal.h \
kernel/qnetworkdatagram_p.h \
kernel/qnetworkinterface.h \
kernel/qnetworkinterface_p.h \
+ kernel/qnetworkinterface_unix_p.h \
kernel/qnetworkproxy.h
SOURCES += kernel/qauthenticator.cpp \
@@ -34,7 +35,10 @@ qtConfig(ftp) {
unix {
!integrity: SOURCES += kernel/qdnslookup_unix.cpp
- SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
+ SOURCES += kernel/qhostinfo_unix.cpp
+
+ qtConfig(linux-netlink): SOURCES += kernel/qnetworkinterface_linux.cpp
+ else: SOURCES += kernel/qnetworkinterface_unix.cpp
}
android {
diff --git a/src/network/kernel/qnetworkinterface_linux.cpp b/src/network/kernel/qnetworkinterface_linux.cpp
new file mode 100644
index 0000000000..8d77d288cd
--- /dev/null
+++ b/src/network/kernel/qnetworkinterface_linux.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkinterface.h"
+#include "qnetworkinterface_p.h"
+#include "qnetworkinterface_unix_p.h"
+
+#include <qendian.h>
+#include <qobjectdefs.h>
+#include <qvarlengtharray.h>
+
+// accordding to rtnetlink(7)
+#include <asm/types.h>
+#include <linux/if.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ BufferSize = 8192
+};
+
+namespace {
+struct NetlinkSocket
+{
+ int sock;
+ NetlinkSocket(int bufferSize)
+ {
+ sock = qt_safe_socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ if (Q_UNLIKELY(sock == -1))
+ qErrnoWarning("Could not create AF_NETLINK socket");
+
+ // set buffer length
+ socklen_t len = sizeof(bufferSize);
+ setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufferSize, len);
+ }
+
+ ~NetlinkSocket()
+ {
+ if (sock != -1)
+ qt_safe_close(sock);
+ }
+
+ operator int() const { return sock; }
+};
+
+template <typename Lambda> struct ProcessNetlinkRequest
+{
+ using FunctionTraits = QtPrivate::FunctionPointer<decltype(&Lambda::operator())>;
+ using FirstArgument = typename FunctionTraits::Arguments::Car;
+
+ static int expectedTypeForRequest(int rtype)
+ {
+ Q_STATIC_ASSERT(RTM_NEWADDR == RTM_GETADDR - 2);
+ Q_STATIC_ASSERT(RTM_NEWLINK == RTM_GETLINK - 2);
+ Q_ASSERT(rtype == RTM_GETADDR || rtype == RTM_GETLINK);
+ return rtype - 2;
+ }
+
+ void operator()(int sock, nlmsghdr *hdr, char *buf, size_t bufsize, Lambda &&func)
+ {
+ // send the request
+ if (send(sock, hdr, hdr->nlmsg_len, 0) != hdr->nlmsg_len)
+ return;
+
+ // receive and parse the request
+ int expectedType = expectedTypeForRequest(hdr->nlmsg_type);
+ const bool isDump = hdr->nlmsg_flags & NLM_F_DUMP;
+ forever {
+ qssize_t len = recv(sock, buf, bufsize, 0);
+ hdr = reinterpret_cast<struct nlmsghdr *>(buf);
+ if (!NLMSG_OK(hdr, len))
+ return;
+
+ auto arg = reinterpret_cast<FirstArgument>(NLMSG_DATA(hdr));
+ size_t payloadLen = NLMSG_PAYLOAD(hdr, 0);
+
+ // is this a multipart message?
+ Q_ASSERT(isDump == !!(hdr->nlmsg_flags & NLM_F_MULTI));
+ if (!isDump) {
+ // no, single message
+ if (hdr->nlmsg_type == expectedType && payloadLen >= sizeof(FirstArgument))
+ return void(func(arg, payloadLen));
+ } else {
+ // multipart, parse until done
+ do {
+ if (hdr->nlmsg_type == NLMSG_DONE)
+ return;
+ if (hdr->nlmsg_type != expectedType || payloadLen < sizeof(FirstArgument))
+ break;
+ func(arg, payloadLen);
+
+ // NLMSG_NEXT also updates the len variable
+ hdr = NLMSG_NEXT(hdr, len);
+ arg = reinterpret_cast<FirstArgument>(NLMSG_DATA(hdr));
+ payloadLen = NLMSG_PAYLOAD(hdr, 0);
+ } while (NLMSG_OK(hdr, len));
+
+ if (len == 0)
+ continue; // get new datagram
+ }
+
+#ifndef QT_NO_DEBUG
+ if (NLMSG_OK(hdr, len))
+ qWarning("QNetworkInterface/AF_NETLINK: received unknown packet type (%d) or too short (%u)",
+ hdr->nlmsg_type, hdr->nlmsg_len);
+ else
+ qWarning("QNetworkInterface/AF_NETLINK: received invalid packet with size %d", int(len));
+#endif
+ return;
+ }
+ }
+};
+
+template <typename Lambda>
+void processNetlinkRequest(int sock, struct nlmsghdr *hdr, char *buf, size_t bufsize, Lambda &&l)
+{
+ ProcessNetlinkRequest<Lambda>()(sock, hdr, buf, bufsize, std::forward<Lambda>(l));
+}
+}
+
+uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
+{
+ uint index = 0;
+ if (name.length() >= IFNAMSIZ)
+ return index;
+
+ int socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
+ if (socket >= 0) {
+ struct ifreq req;
+ req.ifr_ifindex = 0;
+ strcpy(req.ifr_name, name.toLatin1().constData());
+
+ if (qt_safe_ioctl(socket, SIOCGIFINDEX, &req) >= 0)
+ index = req.ifr_ifindex;
+ qt_safe_close(socket);
+ }
+ return index;
+}
+
+QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
+{
+ int socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
+ if (socket >= 0) {
+ struct ifreq req;
+ 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);
+ }
+ return QString();
+}
+
+static QList<QNetworkInterfacePrivate *> getInterfaces(int sock, char *buf)
+{
+ QList<QNetworkInterfacePrivate *> result;
+
+ // request all links
+ struct {
+ struct nlmsghdr req;
+ struct ifinfomsg ifi;
+ } ifi_req;
+ memset(&ifi_req, 0, sizeof(ifi_req));
+
+ ifi_req.req.nlmsg_len = sizeof(ifi_req);
+ ifi_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ ifi_req.req.nlmsg_type = RTM_GETLINK;
+
+ // parse the interfaces
+ processNetlinkRequest(sock, &ifi_req.req, buf, BufferSize, [&](ifinfomsg *ifi, size_t len) {
+ auto iface = new QNetworkInterfacePrivate;
+ iface->index = ifi->ifi_index;
+ iface->flags = convertFlags(ifi->ifi_flags);
+
+ // read attributes
+ auto rta = reinterpret_cast<struct rtattr *>(ifi + 1);
+ len -= sizeof(*ifi);
+ for ( ; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+ int payloadLen = RTA_PAYLOAD(rta);
+ auto payloadPtr = reinterpret_cast<char *>(RTA_DATA(rta));
+
+ switch (rta->rta_type) {
+ case IFLA_ADDRESS: // link-level address
+ iface->hardwareAddress =
+ iface->makeHwAddress(payloadLen, reinterpret_cast<uchar *>(payloadPtr));
+ break;
+
+ case IFLA_IFNAME: // interface name
+ iface->name = QString::fromLatin1(payloadPtr, payloadLen - 1);
+ break;
+
+ case IFLA_OPERSTATE: // operational state
+ if (*payloadPtr != IF_OPER_UNKNOWN) {
+ // override the flag
+ iface->flags &= ~QNetworkInterface::IsUp;
+ if (*payloadPtr == IF_OPER_UP)
+ iface->flags |= QNetworkInterface::IsUp;
+ }
+ break;
+ }
+ }
+
+ if (Q_UNLIKELY(iface->name.isEmpty())) {
+ qWarning("QNetworkInterface: found interface %d with no name", iface->index);
+ delete iface;
+ } else {
+ result.append(iface);
+ }
+ });
+ return result;
+}
+
+static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *> &result)
+{
+ // request all addresses
+ struct {
+ struct nlmsghdr req;
+ struct ifaddrmsg ifa;
+ } ifa_req;
+ memset(&ifa_req, 0, sizeof(ifa_req));
+
+ ifa_req.req.nlmsg_len = sizeof(ifa_req);
+ ifa_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ ifa_req.req.nlmsg_type = RTM_GETADDR;
+ ifa_req.req.nlmsg_seq = 1;
+
+ // parse the addresses
+ processNetlinkRequest(sock, &ifa_req.req, buf, BufferSize, [&](ifaddrmsg *ifa, size_t len) {
+ if (Q_UNLIKELY(ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)) {
+ // unknown address types
+ return;
+ }
+
+ // find the interface this is relevant to
+ QNetworkInterfacePrivate *iface = nullptr;
+ for (auto candidate : qAsConst(result)) {
+ if (candidate->index != int(ifa->ifa_index))
+ continue;
+ iface = candidate;
+ break;
+ }
+
+ if (Q_UNLIKELY(!iface)) {
+ qWarning("QNetworkInterface/AF_NETLINK: found unknown interface with index %d", ifa->ifa_index);
+ return;
+ }
+
+ QNetworkAddressEntry entry;
+ quint32 flags = ifa->ifa_flags; // may be overwritten by IFA_FLAGS
+
+ auto makeAddress = [=](uchar *ptr, int len) {
+ QHostAddress addr;
+ if (ifa->ifa_family == AF_INET) {
+ Q_ASSERT(len == 4);
+ addr.setAddress(qFromBigEndian<quint32>(ptr));
+ } else {
+ Q_ASSERT(len == 16);
+ addr.setAddress(ptr);
+
+ // do we need a scope ID?
+ if (addr.isLinkLocal())
+ addr.setScopeId(iface->name);
+ }
+ return addr;
+ };
+
+ // read attributes
+ auto rta = reinterpret_cast<struct rtattr *>(ifa + 1);
+ len -= sizeof(*ifa);
+ for ( ; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+ int payloadLen = RTA_PAYLOAD(rta);
+ auto payloadPtr = reinterpret_cast<uchar *>(RTA_DATA(rta));
+
+ switch (rta->rta_type) {
+ case IFA_ADDRESS: // address
+ entry.setIp(makeAddress(payloadPtr, payloadLen));
+ break;
+
+ case IFA_BROADCAST:
+ Q_ASSERT(ifa->ifa_family == AF_INET);
+ entry.setBroadcast(makeAddress(payloadPtr, payloadLen));
+ break;
+
+ case IFA_FLAGS:
+ Q_ASSERT(payloadLen == 4);
+ flags = qFromUnaligned<quint32>(payloadPtr);
+ break;
+ }
+ }
+
+ // now handle flags
+ Q_UNUSED(flags);
+
+ if (!entry.ip().isNull()) {
+ entry.setPrefixLength(ifa->ifa_prefixlen);
+ iface->addressEntries.append(entry);
+ }
+ });
+}
+
+QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
+{
+ // open netlink socket
+ QList<QNetworkInterfacePrivate *> result;
+ NetlinkSocket sock(BufferSize);
+ if (Q_UNLIKELY(sock == -1))
+ return result;
+
+ QByteArray buffer(BufferSize, Qt::Uninitialized);
+ char *buf = buffer.data();
+
+ result = getInterfaces(sock, buf);
+ getAddresses(sock, buf, result);
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index f8a33c395e..0b361810e8 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -41,34 +41,15 @@
#include "qset.h"
#include "qnetworkinterface.h"
#include "qnetworkinterface_p.h"
+#include "qnetworkinterface_unix_p.h"
#include "qalgorithms.h"
-#include "private/qnet_unix_p.h"
#ifndef QT_NO_NETWORKINTERFACE
-#define IP_MULTICAST // make AIX happy and define IFF_MULTICAST
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifdef Q_OS_SOLARIS
-# include <sys/sockio.h>
-#endif
-#include <net/if.h>
-
-#ifndef QT_NO_IPV6IFNAME
-#include <net/if.h>
-#endif
-
#if defined(QT_LINUXBASE)
# define QT_NO_GETIFADDRS
#endif
-#ifdef Q_OS_HAIKU
-# include <sys/sockio.h>
-# define IFF_RUNNING 0x0001
-#endif
-
#ifndef QT_NO_GETIFADDRS
# include <ifaddrs.h>
#endif
@@ -107,23 +88,6 @@ static QHostAddress addressFromSockaddr(sockaddr *sa, int ifindex = 0, const QSt
}
-static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
-{
- QNetworkInterface::InterfaceFlags flags = 0;
- flags |= (rawFlags & IFF_UP) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
- flags |= (rawFlags & IFF_RUNNING) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
- flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
- flags |= (rawFlags & IFF_LOOPBACK) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0);
-#ifdef IFF_POINTOPOINT //cygwin doesn't define IFF_POINTOPOINT
- flags |= (rawFlags & IFF_POINTOPOINT) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0);
-#endif
-
-#ifdef IFF_MULTICAST
- flags |= (rawFlags & IFF_MULTICAST) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0);
-#endif
- return flags;
-}
-
uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
{
#ifndef QT_NO_IPV6IFNAME
diff --git a/src/network/kernel/qnetworkinterface_unix_p.h b/src/network/kernel/qnetworkinterface_unix_p.h
new file mode 100644
index 0000000000..c085194e3c
--- /dev/null
+++ b/src/network/kernel/qnetworkinterface_unix_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKINTERFACE_UNIX_P_H
+#define QNETWORKINTERFACE_UNIX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkinterface_p.h"
+#include "private/qnet_unix_p.h"
+
+#ifndef QT_NO_NETWORKINTERFACE
+
+#define IP_MULTICAST // make AIX happy and define IFF_MULTICAST
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef Q_OS_SOLARIS
+# include <sys/sockio.h>
+#endif
+#ifdef Q_OS_HAIKU
+# include <sys/sockio.h>
+# define IFF_RUNNING 0x0001
+#endif
+#if QT_CONFIG(linux_netlink)
+// Same as net/if.h but contains other things we need in
+// qnetworkinterface_linux.cpp.
+# include <linux/if.h>
+#else
+# include <net/if.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
+{
+ QNetworkInterface::InterfaceFlags flags = 0;
+ flags |= (rawFlags & IFF_UP) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
+ flags |= (rawFlags & IFF_RUNNING) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
+ flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
+ flags |= (rawFlags & IFF_LOOPBACK) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0);
+#ifdef IFF_POINTOPOINT //cygwin doesn't define IFF_POINTOPOINT
+ flags |= (rawFlags & IFF_POINTOPOINT) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0);
+#endif
+
+#ifdef IFF_MULTICAST
+ flags |= (rawFlags & IFF_MULTICAST) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0);
+#endif
+ return flags;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKINTERFACE
+
+#endif // QNETWORKINTERFACE_UNIX_P_H