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
|
||||
|
||||
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()
|
||||
: a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
|
||||
{
|
||||
|
@ -159,6 +159,7 @@ public:
|
||||
|
||||
friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW;
|
||||
protected:
|
||||
friend class QHostAddressPrivate;
|
||||
QExplicitlySharedDataPointer<QHostAddressPrivate> d;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QHostAddress::ConversionMode)
|
||||
|
@ -101,6 +101,35 @@ public:
|
||||
{ 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
|
||||
|
||||
#endif
|
||||
|
@ -119,8 +119,15 @@ QList<QSharedDataPointer<QNetworkInterfacePrivate> > QNetworkInterfaceManager::a
|
||||
QList<QSharedDataPointer<QNetworkInterfacePrivate> > result;
|
||||
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);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -158,6 +165,32 @@ QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data)
|
||||
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.
|
||||
*/
|
||||
@ -212,6 +245,39 @@ bool QNetworkAddressEntry::operator==(const QNetworkAddressEntry &other) const
|
||||
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
|
||||
|
||||
|
@ -56,6 +56,12 @@ class QNetworkAddressEntryPrivate;
|
||||
class Q_NETWORK_EXPORT QNetworkAddressEntry
|
||||
{
|
||||
public:
|
||||
enum DnsEligibilityStatus : qint8 {
|
||||
DnsEligibilityUnknown = -1,
|
||||
DnsIneligible = 0,
|
||||
DnsEligible = 1
|
||||
};
|
||||
|
||||
QNetworkAddressEntry();
|
||||
QNetworkAddressEntry(const QNetworkAddressEntry &other);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
@ -70,6 +76,9 @@ public:
|
||||
inline bool operator!=(const QNetworkAddressEntry &other) const
|
||||
{ return !(*this == other); }
|
||||
|
||||
DnsEligibilityStatus dnsEligibility() const;
|
||||
void setDnsEligibility(DnsEligibilityStatus status);
|
||||
|
||||
QHostAddress ip() const;
|
||||
void setIp(const QHostAddress &newIp);
|
||||
|
||||
|
@ -406,7 +406,10 @@ static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *>
|
||||
}
|
||||
|
||||
// now handle flags
|
||||
Q_UNUSED(flags);
|
||||
QNetworkInterfacePrivate::calculateDnsEligibility(&entry,
|
||||
flags & IFA_F_TEMPORARY,
|
||||
flags & IFA_F_DEPRECATED);
|
||||
|
||||
|
||||
if (!entry.ip().isNull()) {
|
||||
entry.setPrefixLength(ifa->ifa_prefixlen);
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
|
||||
QNetmask netmask;
|
||||
bool lifetimeKnown = false;
|
||||
QNetworkAddressEntry::DnsEligibilityStatus dnsEligibility = QNetworkAddressEntry::DnsEligibilityUnknown;
|
||||
};
|
||||
|
||||
class QNetworkInterfacePrivate: public QSharedData
|
||||
@ -97,6 +98,20 @@ public:
|
||||
QList<QNetworkAddressEntry> addressEntries;
|
||||
|
||||
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:
|
||||
// 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));
|
||||
|
||||
// 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
|
||||
ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
|
||||
if (qt_safe_ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr) < 0) {
|
||||
|
@ -229,6 +229,9 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
|
||||
return QDeadlineTimer(lifetime * 1000);
|
||||
};
|
||||
entry.setAddressLifetime(toDeadline(addr->ValidLifetime), toDeadline(addr->PreferredLifetime));
|
||||
entry.setDnsEligibility(addr->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE ?
|
||||
QNetworkAddressEntry::DnsEligible :
|
||||
QNetworkAddressEntry::DnsIneligible);
|
||||
|
||||
iface->addressEntries << entry;
|
||||
}
|
||||
|
@ -152,6 +152,10 @@ void tst_QNetworkInterface::dump()
|
||||
<< " (" << qPrintable(e.netmask().toString()) << ')';
|
||||
if (!e.broadcast().isNull())
|
||||
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()) {
|
||||
#define printable(l) qPrintable(l.isForever() ? "forever" : QString::fromLatin1("%1ms").arg(l.remainingTime()))
|
||||
s.nospace() << " preferred:" << printable(e.preferredLifetime())
|
||||
|
Loading…
Reference in New Issue
Block a user