summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/kernel/qnetworkinterface.cpp70
-rw-r--r--src/network/kernel/qnetworkinterface.h23
-rw-r--r--src/network/kernel/qnetworkinterface_linux.cpp64
-rw-r--r--src/network/kernel/qnetworkinterface_p.h2
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp64
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp46
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp1
7 files changed, 266 insertions, 4 deletions
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 2b83dc2a74..92525d2c86 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -391,6 +391,57 @@ void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast)
*/
/*!
+ \enum QNetworkInterface::InterfaceType
+
+ Specifies the type of hardware (PHY layer, OSI level 1) this interface is,
+ if it could be determined. Interface types that are not among those listed
+ below will generally be listed as Unknown, though future versions of Qt may
+ add new enumeration values.
+
+ The possible values are:
+
+ \value Unknown The interface type could not be determined or is not
+ one of the other listed types.
+ \value Loopback The virtual loopback interface, which is assigned
+ the loopback IP addresses (127.0.0.1, ::1).
+ \value Virtual A type of interface determined to be virtual, but
+ not any of the other possible types. For example,
+ tunnel interfaces are (currently) detected as
+ virtual ones.
+ \value Ethernet IEEE 802.3 Ethernet interfaces, though on many
+ systems other types of IEEE 802 interfaces may also
+ be detected as Ethernet (especially Wi-Fi).
+ \value WiFi IEEE 802.11 Wi-Fi interfaces. Note that on some
+ systems, QNetworkInterface may be unable to
+ distinguish regular Ethernet from Wi-Fi and will
+ not return this enum value.
+ \value Ieee80211 An alias for WiFi.
+ \value CanBus ISO 11898 Controller Area Network bus interfaces,
+ usually found on automotive systems.
+ \value Fddi ANSI X3T12 Fiber Distributed Data Interface, a local area
+ network over optical fibers.
+ \value Ppp Point-to-Point Protocol interfaces, establishing a
+ direct connection between two nodes over a lower
+ transport layer (often serial over radio or physical
+ line).
+ \value Slip Serial Line Internet Protocol interfaces.
+ \value Phonet Interfaces using the Linux Phonet socket family, for
+ communication with cellular modems. See the
+ \l {https://www.kernel.org/doc/Documentation/networking/phonet.txt}{Linux kernel documentation}
+ for more information.
+ \value Ieee802154 IEEE 802.15.4 Personal Area Network interfaces, other
+ than 6LoWPAN (see below).
+ \value SixLoWPAN 6LoWPAN (IPv6 over Low-power Wireless Personal Area
+ Networks) interfaces, which operate on IEEE 802.15.4
+ PHY, but have specific header compression schemes
+ for IPv6 and UDP. This type of interface is often
+ used for mesh networking.
+ \value Ieee80216 IEEE 802.16 Wireless Metropolitan Area Network, also
+ known under the commercial name "WiMAX".
+ \value Ieee1394 IEEE 1394 interfaces (a.k.a. "FireWire").
+*/
+
+/*!
Constructs an empty network interface object.
*/
QNetworkInterface::QNetworkInterface()
@@ -494,6 +545,19 @@ QNetworkInterface::InterfaceFlags QNetworkInterface::flags() const
}
/*!
+ \since 5.11
+
+ Returns the type of this interface, if it could be determined. If it could
+ not be determined, this function returns QNetworkInterface::Unknown.
+
+ \sa hardwareAddress()
+*/
+QNetworkInterface::InterfaceType QNetworkInterface::type() const
+{
+ return d ? d->type : Unknown;
+}
+
+/*!
Returns the low-level hardware address for this interface. On
Ethernet interfaces, this will be a MAC address in string
representation, separated by colons.
@@ -501,6 +565,8 @@ QNetworkInterface::InterfaceFlags QNetworkInterface::flags() const
Other interface types may have other types of hardware
addresses. Implementations should not depend on this function
returning a valid MAC address.
+
+ \sa type()
*/
QString QNetworkInterface::hardwareAddress() const
{
@@ -686,4 +752,6 @@ QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface)
QT_END_NAMESPACE
+#include "moc_qnetworkinterface.cpp"
+
#endif // QT_NO_NETWORKINTERFACE
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index c31621c3cb..7036117e2d 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -90,6 +90,7 @@ Q_DECLARE_SHARED(QNetworkAddressEntry)
class QNetworkInterfacePrivate;
class Q_NETWORK_EXPORT QNetworkInterface
{
+ Q_GADGET
public:
enum InterfaceFlag {
IsUp = 0x1,
@@ -100,6 +101,27 @@ public:
CanMulticast = 0x20
};
Q_DECLARE_FLAGS(InterfaceFlags, InterfaceFlag)
+ Q_FLAG(InterfaceFlags)
+
+ enum InterfaceType {
+ Loopback = 1,
+ Virtual,
+ Ethernet,
+ Slip,
+ CanBus,
+ Ppp,
+ Fddi,
+ Wifi,
+ Ieee80211 = Wifi, // alias
+ Phonet,
+ Ieee802154,
+ SixLoWPAN, // 6LoWPAN, but we can't start with a digit
+ Ieee80216,
+ Ieee1394,
+
+ Unknown = 0
+ };
+ Q_ENUM(InterfaceType)
QNetworkInterface();
QNetworkInterface(const QNetworkInterface &other);
@@ -117,6 +139,7 @@ public:
QString name() const;
QString humanReadableName() const;
InterfaceFlags flags() const;
+ InterfaceType type() const;
QString hardwareAddress() const;
QList<QNetworkAddressEntry> addressEntries() const;
diff --git a/src/network/kernel/qnetworkinterface_linux.cpp b/src/network/kernel/qnetworkinterface_linux.cpp
index 8d77d288cd..a985342286 100644
--- a/src/network/kernel/qnetworkinterface_linux.cpp
+++ b/src/network/kernel/qnetworkinterface_linux.cpp
@@ -48,16 +48,76 @@
// accordding to rtnetlink(7)
#include <asm/types.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
#include <sys/socket.h>
+/* in case these aren't defined in linux/if_arp.h (added since 2.6.28) */
+#define ARPHRD_PHONET 820 /* v2.6.29: PhoNet media type */
+#define ARPHRD_PHONET_PIPE 821 /* v2.6.29: PhoNet pipe header */
+#define ARPHRD_IEEE802154 804 /* v2.6.31 */
+#define ARPHRD_6LOWPAN 825 /* v3.14: IPv6 over LoWPAN */
+
QT_BEGIN_NAMESPACE
enum {
BufferSize = 8192
};
+static QNetworkInterface::InterfaceType probeIfType(int socket, struct ifreq *req, short arptype)
+{
+ switch (ushort(arptype)) {
+ case ARPHRD_LOOPBACK:
+ return QNetworkInterface::Loopback;
+
+ case ARPHRD_ETHER:
+ // check if it's a WiFi interface
+ if (qt_safe_ioctl(socket, SIOCGIWMODE, req) >= 0)
+ return QNetworkInterface::Wifi;
+ return QNetworkInterface::Ethernet;
+
+ case ARPHRD_SLIP:
+ case ARPHRD_CSLIP:
+ case ARPHRD_SLIP6:
+ case ARPHRD_CSLIP6:
+ return QNetworkInterface::Slip;
+
+ case ARPHRD_CAN:
+ return QNetworkInterface::CanBus;
+
+ case ARPHRD_PPP:
+ return QNetworkInterface::Ppp;
+
+ case ARPHRD_FDDI:
+ return QNetworkInterface::Fddi;
+
+ case ARPHRD_IEEE80211:
+ case ARPHRD_IEEE80211_PRISM:
+ case ARPHRD_IEEE80211_RADIOTAP:
+ return QNetworkInterface::Ieee80211;
+
+ case ARPHRD_IEEE802154:
+ return QNetworkInterface::Ieee802154;
+
+ case ARPHRD_PHONET:
+ case ARPHRD_PHONET_PIPE:
+ return QNetworkInterface::Phonet;
+
+ case ARPHRD_6LOWPAN:
+ return QNetworkInterface::SixLoWPAN;
+
+ case ARPHRD_TUNNEL:
+ case ARPHRD_TUNNEL6:
+ case ARPHRD_NONE:
+ case ARPHRD_VOID:
+ return QNetworkInterface::Virtual;
+ }
+ return QNetworkInterface::Unknown;
+}
+
+
namespace {
struct NetlinkSocket
{
@@ -195,6 +255,7 @@ QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
static QList<QNetworkInterfacePrivate *> getInterfaces(int sock, char *buf)
{
QList<QNetworkInterfacePrivate *> result;
+ struct ifreq req;
// request all links
struct {
@@ -227,6 +288,8 @@ static QList<QNetworkInterfacePrivate *> getInterfaces(int sock, char *buf)
break;
case IFLA_IFNAME: // interface name
+ Q_ASSERT(payloadLen <= int(sizeof(req.ifr_name)));
+ memcpy(req.ifr_name, payloadPtr, payloadLen); // including terminating NUL
iface->name = QString::fromLatin1(payloadPtr, payloadLen - 1);
break;
@@ -245,6 +308,7 @@ static QList<QNetworkInterfacePrivate *> getInterfaces(int sock, char *buf)
qWarning("QNetworkInterface: found interface %d with no name", iface->index);
delete iface;
} else {
+ iface->type = probeIfType(sock, &req, ifi->ifi_type);
result.append(iface);
}
});
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index 51901eeda8..44b9b013bc 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -52,6 +52,7 @@
//
#include <QtNetwork/private/qtnetworkglobal_p.h>
+#include <QtNetwork/qnetworkinterface.h>
#include <QtCore/qatomic.h>
#include <QtCore/qlist.h>
#include <QtCore/qreadwritelock.h>
@@ -82,6 +83,7 @@ public:
int index; // interface index, if know
QNetworkInterface::InterfaceFlags flags;
+ QNetworkInterface::InterfaceType type = QNetworkInterface::Unknown;
QString name;
QString friendlyName;
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index 0b361810e8..fb94a2185d 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -384,11 +384,70 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
# elif defined(Q_OS_BSD4)
QT_BEGIN_INCLUDE_NAMESPACE
# include <net/if_dl.h>
+# include <net/if_media.h>
+# include <net/if_types.h>
QT_END_INCLUDE_NAMESPACE
+static int openSocket(int &socket)
+{
+ if (socket == -1)
+ socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
+ return socket;
+}
+
+static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, struct ifmediareq *req)
+{
+ // Determine the interface type.
+
+ // On Darwin, these are #defines, but on FreeBSD they're just an
+ // enum, so we can't #ifdef them. Use the authoritative list from
+ // https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5
+ switch (iftype) {
+ case IFT_PPP:
+ return QNetworkInterface::Ppp;
+
+ case IFT_LOOP:
+ return QNetworkInterface::Loopback;
+
+ case IFT_SLIP:
+ return QNetworkInterface::Slip;
+
+ case 0x47: // IFT_IEEE80211
+ return QNetworkInterface::Ieee80211;
+
+ case IFT_IEEE1394:
+ return QNetworkInterface::Ieee1394;
+
+ case IFT_GIF:
+ case IFT_STF:
+ return QNetworkInterface::Virtual;
+ }
+
+ // For the remainder (including Ethernet), let's try SIOGIFMEDIA
+ req->ifm_count = 0;
+ if (qt_safe_ioctl(socket, SIOCGIFMEDIA, req) == 0) {
+ // see https://man.openbsd.org/ifmedia.4
+
+ switch (IFM_TYPE(req->ifm_current)) {
+ case IFM_ETHER:
+ return QNetworkInterface::Ethernet;
+
+ case IFM_FDDI:
+ return QNetworkInterface::Fddi;
+
+ case IFM_IEEE80211:
+ return QNetworkInterface::Ieee80211;
+ }
+ }
+
+ return QNetworkInterface::Unknown;
+}
+
static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
QList<QNetworkInterfacePrivate *> interfaces;
+ struct ifmediareq mediareq;
+ int socket = -1;
// on NetBSD we use AF_LINK and sockaddr_dl
// scan the list for that family
@@ -402,8 +461,13 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
iface->name = QString::fromLatin1(ptr->ifa_name);
iface->flags = convertFlags(ptr->ifa_flags);
iface->hardwareAddress = iface->makeHwAddress(sdl->sdl_alen, (uchar*)LLADDR(sdl));
+
+ strlcpy(mediareq.ifm_name, ptr->ifa_name, sizeof(mediareq.ifm_name));
+ iface->type = probeIfType(openSocket(socket), sdl->sdl_type, &mediareq);
}
+ if (socket != -1)
+ qt_safe_close(socket);
return interfaces;
}
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 64c3fa6f83..f0c0ba2126 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -62,6 +62,10 @@
#include <qt_windows.h>
+// In case these aren't defined
+#define IF_TYPE_IEEE80216_WMAN 237
+#define IF_TYPE_IEEE802154 259
+
QT_BEGIN_NAMESPACE
static QHostAddress addressFromSockaddr(sockaddr *sa)
@@ -155,6 +159,45 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
if (ptr->IfType == IF_TYPE_PPP)
iface->flags |= QNetworkInterface::IsPointToPoint;
+ switch (ptr->IfType) {
+ case IF_TYPE_ETHERNET_CSMACD:
+ iface->type = QNetworkInterface::Ethernet;
+ break;
+
+ case IF_TYPE_FDDI:
+ iface->type = QNetworkInterface::Fddi;
+ break;
+
+ case IF_TYPE_PPP:
+ iface->type = QNetworkInterface::Ppp;
+ break;
+
+ case IF_TYPE_SLIP:
+ iface->type = QNetworkInterface::Slip;
+ break;
+
+ case IF_TYPE_SOFTWARE_LOOPBACK:
+ iface->type = QNetworkInterface::Loopback;
+ iface->flags |= QNetworkInterface::IsLoopBack;
+ break;
+
+ case IF_TYPE_IEEE80211:
+ iface->type = QNetworkInterface::Ieee80211;
+ break;
+
+ case IF_TYPE_IEEE1394:
+ iface->type = QNetworkInterface::Ieee1394;
+ break;
+
+ case IF_TYPE_IEEE80216_WMAN:
+ iface->type = QNetworkInterface::Ieee80216;
+ break;
+
+ case IF_TYPE_IEEE802154:
+ iface->type = QNetworkInterface::Ieee802154;
+ break;
+ }
+
// use ConvertInterfaceLuidToNameW because that returns a friendlier name, though not
// as "friendly" as FriendlyName below
WCHAR buf[IF_MAX_STRING_SIZE + 1];
@@ -167,9 +210,6 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
if (ptr->PhysicalAddressLength)
iface->hardwareAddress = iface->makeHwAddress(ptr->PhysicalAddressLength,
ptr->PhysicalAddress);
- else
- // loopback if it has no address
- iface->flags |= QNetworkInterface::IsLoopBack;
// parse the IP (unicast) addresses
for (PIP_ADAPTER_UNICAST_ADDRESS addr = ptr->FirstUnicastAddress; addr; addr = addr->Next) {
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 36dcec0a82..0a15da71f8 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -138,6 +138,7 @@ void tst_QNetworkInterface::dump()
qDebug() << " index: " << i.index();
qDebug() << " flags: " << qPrintable(flags);
+ qDebug() << " type: " << i.type();
qDebug() << " hw address:" << qPrintable(i.hardwareAddress());
int count = 0;