/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtNetwork module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "qnetworkinterface.h" | |
#include "qnetworkinterface_p.h" | |
#include "qdebug.h" | |
#include "qendian.h" | |
#ifndef QT_NO_NETWORKINTERFACE | |
QT_BEGIN_NAMESPACE | |
static QList<QNetworkInterfacePrivate *> postProcess(QList<QNetworkInterfacePrivate *> list) | |
{ | |
// Some platforms report a netmask but don't report a broadcast address | |
// Go through all available addresses and calculate the broadcast address | |
// from the IP and the netmask | |
// | |
// This is an IPv4-only thing -- IPv6 has no concept of broadcasts | |
// The math is: | |
// broadcast = IP | ~netmask | |
QList<QNetworkInterfacePrivate *>::Iterator it = list.begin(); | |
const QList<QNetworkInterfacePrivate *>::Iterator end = list.end(); | |
for ( ; it != end; ++it) { | |
QList<QNetworkAddressEntry>::Iterator addr_it = (*it)->addressEntries.begin(); | |
const QList<QNetworkAddressEntry>::Iterator addr_end = (*it)->addressEntries.end(); | |
for ( ; addr_it != addr_end; ++addr_it) { | |
if (addr_it->ip().protocol() != QAbstractSocket::IPv4Protocol) | |
continue; | |
if (!addr_it->netmask().isNull() && addr_it->broadcast().isNull()) { | |
QHostAddress bcast = addr_it->ip(); | |
bcast = QHostAddress(bcast.toIPv4Address() | ~addr_it->netmask().toIPv4Address()); | |
addr_it->setBroadcast(bcast); | |
} | |
} | |
} | |
return list; | |
} | |
Q_GLOBAL_STATIC(QNetworkInterfaceManager, manager) | |
QNetworkInterfaceManager::QNetworkInterfaceManager() | |
{ | |
} | |
QNetworkInterfaceManager::~QNetworkInterfaceManager() | |
{ | |
} | |
QSharedDataPointer<QNetworkInterfacePrivate> QNetworkInterfaceManager::interfaceFromName(const QString &name) | |
{ | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > interfaceList = allInterfaces(); | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> >::ConstIterator it = interfaceList.constBegin(); | |
for ( ; it != interfaceList.constEnd(); ++it) | |
if ((*it)->name == name) | |
return *it; | |
return empty; | |
} | |
QSharedDataPointer<QNetworkInterfacePrivate> QNetworkInterfaceManager::interfaceFromIndex(int index) | |
{ | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > interfaceList = allInterfaces(); | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> >::ConstIterator it = interfaceList.constBegin(); | |
for ( ; it != interfaceList.constEnd(); ++it) | |
if ((*it)->index == index) | |
return *it; | |
return empty; | |
} | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > QNetworkInterfaceManager::allInterfaces() | |
{ | |
QList<QNetworkInterfacePrivate *> list = postProcess(scan()); | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > result; | |
foreach (QNetworkInterfacePrivate *ptr, list) | |
result << QSharedDataPointer<QNetworkInterfacePrivate>(ptr); | |
return result; | |
} | |
QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data) | |
{ | |
QString result; | |
for (int i = 0; i < len; ++i) { | |
if (i) | |
result += QLatin1Char(':'); | |
char buf[3]; | |
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 | |
sprintf_s(buf, 3, "%02hX", ushort(data[i])); | |
#else | |
sprintf(buf, "%02hX", ushort(data[i])); | |
#endif | |
result += QLatin1String(buf); | |
} | |
return result; | |
} | |
/*! | |
\class QNetworkAddressEntry | |
\brief The QNetworkAddressEntry class stores one IP address | |
supported by a network interface, along with its associated | |
netmask and broadcast address. | |
\since 4.2 | |
\reentrant | |
\ingroup network | |
Each network interface can contain zero or more IP addresses, which | |
in turn can be associated with a netmask and/or a broadcast | |
address (depending on support from the operating system). | |
This class represents one such group. | |
*/ | |
/*! | |
Constructs an empty QNetworkAddressEntry object. | |
*/ | |
QNetworkAddressEntry::QNetworkAddressEntry() | |
: d(new QNetworkAddressEntryPrivate) | |
{ | |
} | |
/*! | |
Constructs a QNetworkAddressEntry object that is a copy of the | |
object \a other. | |
*/ | |
QNetworkAddressEntry::QNetworkAddressEntry(const QNetworkAddressEntry &other) | |
: d(new QNetworkAddressEntryPrivate(*other.d.data())) | |
{ | |
} | |
/*! | |
Makes a copy of the QNetworkAddressEntry object \a other. | |
*/ | |
QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry &other) | |
{ | |
*d.data() = *other.d.data(); | |
return *this; | |
} | |
/*! | |
Destroys this QNetworkAddressEntry object. | |
*/ | |
QNetworkAddressEntry::~QNetworkAddressEntry() | |
{ | |
} | |
/*! | |
Returns true if this network address entry is the same as \a | |
other. | |
*/ | |
bool QNetworkAddressEntry::operator==(const QNetworkAddressEntry &other) const | |
{ | |
if (d == other.d) return true; | |
if (!d || !other.d) return false; | |
return d->address == other.d->address && | |
d->netmask == other.d->netmask && | |
d->broadcast == other.d->broadcast; | |
} | |
/*! | |
\fn bool QNetworkAddressEntry::operator!=(const QNetworkAddressEntry &other) const | |
Returns true if this network address entry is different from \a | |
other. | |
*/ | |
/*! | |
This function returns one IPv4 or IPv6 address found, that was | |
found in a network interface. | |
*/ | |
QHostAddress QNetworkAddressEntry::ip() const | |
{ | |
return d->address; | |
} | |
/*! | |
Sets the IP address the QNetworkAddressEntry object contains to \a | |
newIp. | |
*/ | |
void QNetworkAddressEntry::setIp(const QHostAddress &newIp) | |
{ | |
d->address = newIp; | |
} | |
/*! | |
Returns the netmask associated with the IP address. The | |
netmask is expressed in the form of an IP address, such as | |
255.255.0.0. | |
For IPv6 addresses, the prefix length is converted to an address | |
where the number of bits set to 1 is equal to the prefix | |
length. For a prefix length of 64 bits (the most common value), | |
the netmask will be expressed as a QHostAddress holding the | |
address FFFF:FFFF:FFFF:FFFF:: | |
\sa prefixLength() | |
*/ | |
QHostAddress QNetworkAddressEntry::netmask() const | |
{ | |
return d->netmask; | |
} | |
/*! | |
Sets the netmask that this QNetworkAddressEntry object contains to | |
\a newNetmask. Setting the netmask also sets the prefix length to | |
match the new netmask. | |
\sa setPrefixLength() | |
*/ | |
void QNetworkAddressEntry::setNetmask(const QHostAddress &newNetmask) | |
{ | |
if (newNetmask.protocol() != ip().protocol()) { | |
d->netmask = QNetmaskAddress(); | |
return; | |
} | |
d->netmask.setAddress(newNetmask); | |
} | |
/*! | |
\since 4.5 | |
Returns the prefix length of this IP address. The prefix length | |
matches the number of bits set to 1 in the netmask (see | |
netmask()). For IPv4 addresses, the value is between 0 and 32. For | |
IPv6 addresses, it's contained between 0 and 128 and is the | |
preferred form of representing addresses. | |
This function returns -1 if the prefix length could not be | |
determined (i.e., netmask() returns a null QHostAddress()). | |
\sa netmask() | |
*/ | |
int QNetworkAddressEntry::prefixLength() const | |
{ | |
return d->netmask.prefixLength(); | |
} | |
/*! | |
\since 4.5 | |
Sets the prefix length of this IP address to \a length. The value | |
of \a length must be valid for this type of IP address: between 0 | |
and 32 for IPv4 addresses, between 0 and 128 for IPv6 | |
addresses. Setting to any invalid value is equivalent to setting | |
to -1, which means "no prefix length". | |
Setting the prefix length also sets the netmask (see netmask()). | |
\sa setNetmask() | |
*/ | |
void QNetworkAddressEntry::setPrefixLength(int length) | |
{ | |
d->netmask.setPrefixLength(d->address.protocol(), length); | |
} | |
/*! | |
Returns the broadcast address associated with the IPv4 | |
address and netmask. It can usually be derived from those two by | |
setting to 1 the bits of the IP address where the netmask contains | |
a 0. (In other words, by bitwise-OR'ing the IP address with the | |
inverse of the netmask) | |
This member is always empty for IPv6 addresses, since the concept | |
of broadcast has been abandoned in that system in favor of | |
multicast. In particular, the group of hosts corresponding to all | |
the nodes in the local network can be reached by the "all-nodes" | |
special multicast group (address FF02::1). | |
*/ | |
QHostAddress QNetworkAddressEntry::broadcast() const | |
{ | |
return d->broadcast; | |
} | |
/*! | |
Sets the broadcast IP address of this QNetworkAddressEntry object | |
to \a newBroadcast. | |
*/ | |
void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast) | |
{ | |
d->broadcast = newBroadcast; | |
} | |
/*! | |
\class QNetworkInterface | |
\brief The QNetworkInterface class provides a listing of the host's IP | |
addresses and network interfaces. | |
\since 4.2 | |
\reentrant | |
\ingroup network | |
QNetworkInterface represents one network interface attached to the | |
host where the program is being run. Each network interface may | |
contain zero or more IP addresses, each of which is optionally | |
associated with a netmask and/or a broadcast address. The list of | |
such trios can be obtained with addressEntries(). Alternatively, | |
when the netmask or the broadcast addresses aren't necessary, use | |
the allAddresses() convenience function to obtain just the IP | |
addresses. | |
QNetworkInterface also reports the interface's hardware address with | |
hardwareAddress(). | |
Not all operating systems support reporting all features. Only the | |
IPv4 addresses are guaranteed to be listed by this class in all | |
platforms. In particular, IPv6 address listing is only supported | |
on Windows XP and more recent versions, Linux, MacOS X and the | |
BSDs. | |
\sa QNetworkAddressEntry | |
*/ | |
/*! | |
\enum QNetworkInterface::InterfaceFlag | |
Specifies the flags associated with this network interface. The | |
possible values are: | |
\value IsUp the network interface is active | |
\value IsRunning the network interface has resources | |
allocated | |
\value CanBroadcast the network interface works in | |
broadcast mode | |
\value IsLoopBack the network interface is a loopback | |
interface: that is, it's a virtual | |
interface whose destination is the | |
host computer itself | |
\value IsPointToPoint the network interface is a | |
point-to-point interface: that is, | |
there is one, single other address | |
that can be directly reached by it. | |
\value CanMulticast the network interface supports | |
multicasting | |
Note that one network interface cannot be both broadcast-based and | |
point-to-point. | |
*/ | |
/*! | |
Constructs an empty network interface object. | |
*/ | |
QNetworkInterface::QNetworkInterface() | |
: d(0) | |
{ | |
} | |
/*! | |
Frees the resources associated with the QNetworkInterface object. | |
*/ | |
QNetworkInterface::~QNetworkInterface() | |
{ | |
} | |
/*! | |
Creates a copy of the QNetworkInterface object contained in \a | |
other. | |
*/ | |
QNetworkInterface::QNetworkInterface(const QNetworkInterface &other) | |
: d(other.d) | |
{ | |
} | |
/*! | |
Copies the contents of the QNetworkInterface object contained in \a | |
other into this one. | |
*/ | |
QNetworkInterface &QNetworkInterface::operator=(const QNetworkInterface &other) | |
{ | |
d = other.d; | |
return *this; | |
} | |
/*! | |
Returns true if this QNetworkInterface object contains valid | |
information about a network interface. | |
*/ | |
bool QNetworkInterface::isValid() const | |
{ | |
return !name().isEmpty(); | |
} | |
/*! | |
\since 4.5 | |
Returns the interface system index, if known. This is an integer | |
assigned by the operating system to identify this interface and it | |
generally doesn't change. It matches the scope ID field in IPv6 | |
addresses. | |
If the index isn't known, this function returns 0. | |
*/ | |
int QNetworkInterface::index() const | |
{ | |
return d ? d->index : 0; | |
} | |
/*! | |
Returns the name of this network interface. On Unix systems, this | |
is a string containing the type of the interface and optionally a | |
sequence number, such as "eth0", "lo" or "pcn0". On Windows, it's | |
an internal ID that cannot be changed by the user. | |
*/ | |
QString QNetworkInterface::name() const | |
{ | |
return d ? d->name : QString(); | |
} | |
/*! | |
\since 4.5 | |
Returns the human-readable name of this network interface on | |
Windows, such as "Local Area Connection", if the name could be | |
determined. If it couldn't, this function returns the same as | |
name(). The human-readable name is a name that the user can modify | |
in the Windows Control Panel, so it may change during the | |
execution of the program. | |
On Unix, this function currently always returns the same as | |
name(), since Unix systems don't store a configuration for | |
human-readable names. | |
*/ | |
QString QNetworkInterface::humanReadableName() const | |
{ | |
return d ? !d->friendlyName.isEmpty() ? d->friendlyName : name() : QString(); | |
} | |
/*! | |
Returns the flags associated with this network interface. | |
*/ | |
QNetworkInterface::InterfaceFlags QNetworkInterface::flags() const | |
{ | |
return d ? d->flags : InterfaceFlags(0); | |
} | |
/*! | |
Returns the low-level hardware address for this interface. On | |
Ethernet interfaces, this will be a MAC address in string | |
representation, separated by colons. | |
Other interface types may have other types of hardware | |
addresses. Implementations should not depend on this function | |
returning a valid MAC address. | |
*/ | |
QString QNetworkInterface::hardwareAddress() const | |
{ | |
return d ? d->hardwareAddress : QString(); | |
} | |
/*! | |
Returns the list of IP addresses that this interface possesses | |
along with their associated netmasks and broadcast addresses. | |
If the netmask or broadcast address information is not necessary, | |
you can call the allAddresses() function to obtain just the IP | |
addresses. | |
*/ | |
QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const | |
{ | |
return d ? d->addressEntries : QList<QNetworkAddressEntry>(); | |
} | |
/*! | |
Returns a QNetworkInterface object for the interface named \a | |
name. If no such interface exists, this function returns an | |
invalid QNetworkInterface object. | |
\sa name(), isValid() | |
*/ | |
QNetworkInterface QNetworkInterface::interfaceFromName(const QString &name) | |
{ | |
QNetworkInterface result; | |
result.d = manager()->interfaceFromName(name); | |
return result; | |
} | |
/*! | |
Returns a QNetworkInterface object for the interface whose internal | |
ID is \a index. Network interfaces have a unique identifier called | |
the "interface index" to distinguish it from other interfaces on | |
the system. Often, this value is assigned progressively and | |
interfaces being removed and then added again get a different | |
value every time. | |
This index is also found in the IPv6 address' scope ID field. | |
*/ | |
QNetworkInterface QNetworkInterface::interfaceFromIndex(int index) | |
{ | |
QNetworkInterface result; | |
result.d = manager()->interfaceFromIndex(index); | |
return result; | |
} | |
/*! | |
Returns a listing of all the network interfaces found on the host | |
machine. | |
*/ | |
QList<QNetworkInterface> QNetworkInterface::allInterfaces() | |
{ | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces(); | |
QList<QNetworkInterface> result; | |
foreach (const QSharedDataPointer<QNetworkInterfacePrivate> &p, privs) { | |
QNetworkInterface item; | |
item.d = p; | |
result << item; | |
} | |
return result; | |
} | |
/*! | |
This convenience function returns all IP addresses found on the | |
host machine. It is equivalent to calling addressEntries() on all the | |
objects returned by allInterfaces() to obtain lists of QHostAddress | |
objects then calling QHostAddress::ip() on each of these. | |
*/ | |
QList<QHostAddress> QNetworkInterface::allAddresses() | |
{ | |
QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces(); | |
QList<QHostAddress> result; | |
foreach (const QSharedDataPointer<QNetworkInterfacePrivate> &p, privs) { | |
foreach (const QNetworkAddressEntry &entry, p->addressEntries) | |
result += entry.ip(); | |
} | |
return result; | |
} | |
#ifndef QT_NO_DEBUG_STREAM | |
static inline QDebug flagsDebug(QDebug debug, QNetworkInterface::InterfaceFlags flags) | |
{ | |
if (flags & QNetworkInterface::IsUp) | |
debug.nospace() << "IsUp "; | |
if (flags & QNetworkInterface::IsRunning) | |
debug.nospace() << "IsRunning "; | |
if (flags & QNetworkInterface::CanBroadcast) | |
debug.nospace() << "CanBroadcast "; | |
if (flags & QNetworkInterface::IsLoopBack) | |
debug.nospace() << "IsLoopBack "; | |
if (flags & QNetworkInterface::IsPointToPoint) | |
debug.nospace() << "IsPointToPoint "; | |
if (flags & QNetworkInterface::CanMulticast) | |
debug.nospace() << "CanMulticast "; | |
return debug.nospace(); | |
} | |
static inline QDebug operator<<(QDebug debug, const QNetworkAddressEntry &entry) | |
{ | |
debug.nospace() << "(address = " << entry.ip(); | |
if (!entry.netmask().isNull()) | |
debug.nospace() << ", netmask = " << entry.netmask(); | |
if (!entry.broadcast().isNull()) | |
debug.nospace() << ", broadcast = " << entry.broadcast(); | |
debug.nospace() << ')'; | |
return debug.space(); | |
} | |
QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface) | |
{ | |
debug.nospace() << "QNetworkInterface(name = " << networkInterface.name() | |
<< ", hardware address = " << networkInterface.hardwareAddress() | |
<< ", flags = "; | |
flagsDebug(debug, networkInterface.flags()); | |
#if defined(Q_CC_RVCT) | |
// RVCT gets confused with << networkInterface.addressEntries(), reason unknown. | |
debug.nospace() << ")\n"; | |
#else | |
debug.nospace() << ", entries = " << networkInterface.addressEntries() | |
<< ")\n"; | |
#endif | |
return debug.space(); | |
} | |
#endif | |
QT_END_NAMESPACE | |
#endif // QT_NO_NETWORKINTERFACE |