QNetworkInterface: Add the DNS eligibility
[ChangeLog][QtNetwork][QNetworkInterface] Added dnsEligibility() to QNetworkAddressEntry to indicate whether the address is eligible or not for publication in DNS or similar mechanisms. Change-Id: Id3ae5f853d964358ac1ab19b525334a426e0e052 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
a93437342b
commit
18ec85a80c
@ -64,33 +64,6 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QHostAddressPrivate : public QSharedData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QHostAddressPrivate();
|
|
||||||
|
|
||||||
void setAddress(quint32 a_ = 0);
|
|
||||||
void setAddress(const quint8 *a_);
|
|
||||||
void setAddress(const Q_IPV6ADDR &a_);
|
|
||||||
|
|
||||||
bool parse(const QString &ipString);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
QString scopeId;
|
|
||||||
|
|
||||||
union {
|
|
||||||
Q_IPV6ADDR a6; // IPv6 address
|
|
||||||
struct { quint64 c[2]; } a6_64;
|
|
||||||
struct { quint32 c[4]; } a6_32;
|
|
||||||
};
|
|
||||||
quint32 a; // IPv4 address
|
|
||||||
qint8 protocol;
|
|
||||||
|
|
||||||
AddressClassification classify() const;
|
|
||||||
|
|
||||||
friend class QHostAddress;
|
|
||||||
};
|
|
||||||
|
|
||||||
QHostAddressPrivate::QHostAddressPrivate()
|
QHostAddressPrivate::QHostAddressPrivate()
|
||||||
: a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
|
: a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
|
||||||
{
|
{
|
||||||
|
@ -159,6 +159,7 @@ public:
|
|||||||
|
|
||||||
friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW;
|
friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW;
|
||||||
protected:
|
protected:
|
||||||
|
friend class QHostAddressPrivate;
|
||||||
QExplicitlySharedDataPointer<QHostAddressPrivate> d;
|
QExplicitlySharedDataPointer<QHostAddressPrivate> d;
|
||||||
};
|
};
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QHostAddress::ConversionMode)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QHostAddress::ConversionMode)
|
||||||
|
@ -101,6 +101,35 @@ public:
|
|||||||
{ return n1.length == n2.length; }
|
{ return n1.length == n2.length; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QHostAddressPrivate : public QSharedData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QHostAddressPrivate();
|
||||||
|
|
||||||
|
void setAddress(quint32 a_ = 0);
|
||||||
|
void setAddress(const quint8 *a_);
|
||||||
|
void setAddress(const Q_IPV6ADDR &a_);
|
||||||
|
|
||||||
|
bool parse(const QString &ipString);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
QString scopeId;
|
||||||
|
|
||||||
|
union {
|
||||||
|
Q_IPV6ADDR a6; // IPv6 address
|
||||||
|
struct { quint64 c[2]; } a6_64;
|
||||||
|
struct { quint32 c[4]; } a6_32;
|
||||||
|
};
|
||||||
|
quint32 a; // IPv4 address
|
||||||
|
qint8 protocol;
|
||||||
|
|
||||||
|
AddressClassification classify() const;
|
||||||
|
static AddressClassification classify(const QHostAddress &address)
|
||||||
|
{ return address.d->classify(); }
|
||||||
|
|
||||||
|
friend class QHostAddress;
|
||||||
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -119,8 +119,15 @@ QList<QSharedDataPointer<QNetworkInterfacePrivate> > QNetworkInterfaceManager::a
|
|||||||
QList<QSharedDataPointer<QNetworkInterfacePrivate> > result;
|
QList<QSharedDataPointer<QNetworkInterfacePrivate> > result;
|
||||||
result.reserve(list.size());
|
result.reserve(list.size());
|
||||||
|
|
||||||
for (QNetworkInterfacePrivate *ptr : list)
|
for (QNetworkInterfacePrivate *ptr : list) {
|
||||||
|
if ((ptr->flags & QNetworkInterface::IsUp) == 0) {
|
||||||
|
// if the network interface isn't UP, the addresses are ineligible for DNS
|
||||||
|
for (auto &addr : ptr->addressEntries)
|
||||||
|
addr.setDnsEligibility(QNetworkAddressEntry::DnsIneligible);
|
||||||
|
}
|
||||||
|
|
||||||
result << QSharedDataPointer<QNetworkInterfacePrivate>(ptr);
|
result << QSharedDataPointer<QNetworkInterfacePrivate>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -158,6 +165,32 @@ QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data)
|
|||||||
This class represents one such group.
|
This class represents one such group.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum QNetworkAddressEntry::DnsEligilibilityStatus
|
||||||
|
\since 5.11
|
||||||
|
|
||||||
|
This enum indicates whether a given host address is eligible to be
|
||||||
|
published in the Domain Name System (DNS) or other similar name resolution
|
||||||
|
mechanisms. In general, an address is suitable for publication if it is an
|
||||||
|
address this machine will be reached at for an indeterminate amount of
|
||||||
|
time, though it need not be permanent. For example, addresses obtained via
|
||||||
|
DHCP are often eligible, but cryptographically-generated temporary IPv6
|
||||||
|
addresses are not.
|
||||||
|
|
||||||
|
\value DnsEligibilityUnknown Qt and the operating system could not determine
|
||||||
|
whether this address should be published or not.
|
||||||
|
The application may need to apply further
|
||||||
|
heuristics if it cannot find any eligible
|
||||||
|
addresses.
|
||||||
|
\value DnsEligible This address is eligible for publication in DNS.
|
||||||
|
\value DnsIneligible This address should not be published in DNS and
|
||||||
|
should not be transmitted to other parties,
|
||||||
|
except maybe as the source address of an outgoing
|
||||||
|
packet.
|
||||||
|
|
||||||
|
\sa dnsEligibility(), setDnsEligibility()
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs an empty QNetworkAddressEntry object.
|
Constructs an empty QNetworkAddressEntry object.
|
||||||
*/
|
*/
|
||||||
@ -212,6 +245,39 @@ bool QNetworkAddressEntry::operator==(const QNetworkAddressEntry &other) const
|
|||||||
d->broadcast == other.d->broadcast;
|
d->broadcast == other.d->broadcast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 5.11
|
||||||
|
|
||||||
|
Returns whether this address is eligible for publication in the Domain Name
|
||||||
|
System (DNS) or similar name resolution mechanisms.
|
||||||
|
|
||||||
|
In general, an address is suitable for publication if it is an address this
|
||||||
|
machine will be reached at for an indeterminate amount of time, though it
|
||||||
|
need not be permanent. For example, addresses obtained via DHCP are often
|
||||||
|
eligible, but cryptographically-generated temporary IPv6 addresses are not.
|
||||||
|
|
||||||
|
On some systems, QNetworkInterface will need to heuristically determine
|
||||||
|
which addresses are eligible.
|
||||||
|
|
||||||
|
\sa isLifetimeKnown(), isPermanent(), setDnsEligibility()
|
||||||
|
*/
|
||||||
|
QNetworkAddressEntry::DnsEligibilityStatus QNetworkAddressEntry::dnsEligibility() const
|
||||||
|
{
|
||||||
|
return d->dnsEligibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 5.11
|
||||||
|
|
||||||
|
Sets the DNS eligibility flag for this address to \a status.
|
||||||
|
|
||||||
|
\sa dnsEligibility()
|
||||||
|
*/
|
||||||
|
void QNetworkAddressEntry::setDnsEligibility(DnsEligibilityStatus status)
|
||||||
|
{
|
||||||
|
d->dnsEligibility = status;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool QNetworkAddressEntry::operator!=(const QNetworkAddressEntry &other) const
|
\fn bool QNetworkAddressEntry::operator!=(const QNetworkAddressEntry &other) const
|
||||||
|
|
||||||
|
@ -56,6 +56,12 @@ class QNetworkAddressEntryPrivate;
|
|||||||
class Q_NETWORK_EXPORT QNetworkAddressEntry
|
class Q_NETWORK_EXPORT QNetworkAddressEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum DnsEligibilityStatus : qint8 {
|
||||||
|
DnsEligibilityUnknown = -1,
|
||||||
|
DnsIneligible = 0,
|
||||||
|
DnsEligible = 1
|
||||||
|
};
|
||||||
|
|
||||||
QNetworkAddressEntry();
|
QNetworkAddressEntry();
|
||||||
QNetworkAddressEntry(const QNetworkAddressEntry &other);
|
QNetworkAddressEntry(const QNetworkAddressEntry &other);
|
||||||
#ifdef Q_COMPILER_RVALUE_REFS
|
#ifdef Q_COMPILER_RVALUE_REFS
|
||||||
@ -70,6 +76,9 @@ public:
|
|||||||
inline bool operator!=(const QNetworkAddressEntry &other) const
|
inline bool operator!=(const QNetworkAddressEntry &other) const
|
||||||
{ return !(*this == other); }
|
{ return !(*this == other); }
|
||||||
|
|
||||||
|
DnsEligibilityStatus dnsEligibility() const;
|
||||||
|
void setDnsEligibility(DnsEligibilityStatus status);
|
||||||
|
|
||||||
QHostAddress ip() const;
|
QHostAddress ip() const;
|
||||||
void setIp(const QHostAddress &newIp);
|
void setIp(const QHostAddress &newIp);
|
||||||
|
|
||||||
|
@ -406,7 +406,10 @@ static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now handle flags
|
// now handle flags
|
||||||
Q_UNUSED(flags);
|
QNetworkInterfacePrivate::calculateDnsEligibility(&entry,
|
||||||
|
flags & IFA_F_TEMPORARY,
|
||||||
|
flags & IFA_F_DEPRECATED);
|
||||||
|
|
||||||
|
|
||||||
if (!entry.ip().isNull()) {
|
if (!entry.ip().isNull()) {
|
||||||
entry.setPrefixLength(ifa->ifa_prefixlen);
|
entry.setPrefixLength(ifa->ifa_prefixlen);
|
||||||
|
@ -76,6 +76,7 @@ public:
|
|||||||
|
|
||||||
QNetmask netmask;
|
QNetmask netmask;
|
||||||
bool lifetimeKnown = false;
|
bool lifetimeKnown = false;
|
||||||
|
QNetworkAddressEntry::DnsEligibilityStatus dnsEligibility = QNetworkAddressEntry::DnsEligibilityUnknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QNetworkInterfacePrivate: public QSharedData
|
class QNetworkInterfacePrivate: public QSharedData
|
||||||
@ -97,6 +98,20 @@ public:
|
|||||||
QList<QNetworkAddressEntry> addressEntries;
|
QList<QNetworkAddressEntry> addressEntries;
|
||||||
|
|
||||||
static QString makeHwAddress(int len, uchar *data);
|
static QString makeHwAddress(int len, uchar *data);
|
||||||
|
static void calculateDnsEligibility(QNetworkAddressEntry *entry, bool isTemporary,
|
||||||
|
bool isDeprecated)
|
||||||
|
{
|
||||||
|
// this implements an algorithm that yields the same results as Windows
|
||||||
|
// produces, for the same input (as far as I can test)
|
||||||
|
if (isTemporary || isDeprecated)
|
||||||
|
entry->setDnsEligibility(QNetworkAddressEntry::DnsIneligible);
|
||||||
|
|
||||||
|
AddressClassification cl = QHostAddressPrivate::classify(entry->ip());
|
||||||
|
if (cl == LoopbackAddress || cl == LinkLocalAddress)
|
||||||
|
entry->setDnsEligibility(QNetworkAddressEntry::DnsIneligible);
|
||||||
|
else
|
||||||
|
entry->setDnsEligibility(QNetworkAddressEntry::DnsEligible);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disallow copying -- avoid detaching
|
// disallow copying -- avoid detaching
|
||||||
|
@ -499,6 +499,17 @@ static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa
|
|||||||
|
|
||||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||||
|
|
||||||
|
// get flags
|
||||||
|
ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
|
||||||
|
if (qt_safe_ioctl(s6, SIOCGIFAFLAG_IN6, &ifr) < 0) {
|
||||||
|
qt_safe_close(s6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int flags = ifr.ifr_ifru.ifru_flags6;
|
||||||
|
QNetworkInterfacePrivate::calculateDnsEligibility(entry,
|
||||||
|
flags & IN6_IFF_TEMPORARY,
|
||||||
|
flags & IN6_IFF_DEPRECATED);
|
||||||
|
|
||||||
// get lifetimes
|
// get lifetimes
|
||||||
ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
|
ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
|
||||||
if (qt_safe_ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr) < 0) {
|
if (qt_safe_ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr) < 0) {
|
||||||
|
@ -229,6 +229,9 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
|
|||||||
return QDeadlineTimer(lifetime * 1000);
|
return QDeadlineTimer(lifetime * 1000);
|
||||||
};
|
};
|
||||||
entry.setAddressLifetime(toDeadline(addr->ValidLifetime), toDeadline(addr->PreferredLifetime));
|
entry.setAddressLifetime(toDeadline(addr->ValidLifetime), toDeadline(addr->PreferredLifetime));
|
||||||
|
entry.setDnsEligibility(addr->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE ?
|
||||||
|
QNetworkAddressEntry::DnsEligible :
|
||||||
|
QNetworkAddressEntry::DnsIneligible);
|
||||||
|
|
||||||
iface->addressEntries << entry;
|
iface->addressEntries << entry;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,10 @@ void tst_QNetworkInterface::dump()
|
|||||||
<< " (" << qPrintable(e.netmask().toString()) << ')';
|
<< " (" << qPrintable(e.netmask().toString()) << ')';
|
||||||
if (!e.broadcast().isNull())
|
if (!e.broadcast().isNull())
|
||||||
s.nospace() << " broadcast " << qPrintable(e.broadcast().toString());
|
s.nospace() << " broadcast " << qPrintable(e.broadcast().toString());
|
||||||
|
if (e.dnsEligibility() == QNetworkAddressEntry::DnsEligible)
|
||||||
|
s.nospace() << " dns-eligible";
|
||||||
|
else if (e.dnsEligibility() == QNetworkAddressEntry::DnsIneligible)
|
||||||
|
s.nospace() << " dns-ineligible";
|
||||||
if (e.isLifetimeKnown()) {
|
if (e.isLifetimeKnown()) {
|
||||||
#define printable(l) qPrintable(l.isForever() ? "forever" : QString::fromLatin1("%1ms").arg(l.remainingTime()))
|
#define printable(l) qPrintable(l.isForever() ? "forever" : QString::fromLatin1("%1ms").arg(l.remainingTime()))
|
||||||
s.nospace() << " preferred:" << printable(e.preferredLifetime())
|
s.nospace() << " preferred:" << printable(e.preferredLifetime())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user