summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/kernel/qnetworkinterface.cpp116
-rw-r--r--src/network/kernel/qnetworkinterface.h10
-rw-r--r--src/network/kernel/qnetworkinterface_linux.cpp12
-rw-r--r--src/network/kernel/qnetworkinterface_p.h5
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp60
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp8
6 files changed, 209 insertions, 2 deletions
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 92525d2c86..e546c8d949 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -335,6 +335,122 @@ void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast)
}
/*!
+ \since 5.11
+
+ Returns \c true if the address lifetime is known, \c false if not. If the
+ lifetime is not known, both preferredLifetime() and validityLifetime() will
+ return QDeadlineTimer::Forever.
+
+ \sa preferredLifetime(), validityLifetime(), setAddressLifetime(), clearAddressLifetime()
+*/
+bool QNetworkAddressEntry::isLifetimeKnown() const
+{
+ return d->lifetimeKnown;
+}
+
+/*!
+ \since 5.11
+
+ Returns the deadline when this address becomes deprecated (no longer
+ preferred), if known. If the address lifetime is not known (see
+ isLifetimeKnown()), this function always returns QDeadlineTimer::Forever.
+
+ While an address is preferred, it may be used by the operating system as
+ the source address for new, outgoing packets. After it becomes deprecated,
+ it will remain valid for incoming packets for a while longer until finally
+ removed (see validityLifetime()).
+
+ \sa validityLifetime(), isLifetimeKnown(), setAddressLifetime(), clearAddressLifetime()
+*/
+QDeadlineTimer QNetworkAddressEntry::preferredLifetime() const
+{
+ return d->preferredLifetime;
+}
+
+/*!
+ \since 5.11
+
+ Returns the deadline when this address becomes invalid and will be removed
+ from the networking stack, if known. If the address lifetime is not known
+ (see isLifetimeKnown()), this function always returns
+ QDeadlineTimer::Forever.
+
+ While an address is valid, it will be accepted by the operating system as a
+ valid destination address for this machine. Whether it is used as a source
+ address for new, outgoing packets is controlled by, among other rules, the
+ preferred lifetime (see preferredLifetime()).
+
+ \sa preferredLifetime(), isLifetimeKnown(), setAddressLifetime(), clearAddressLifetime()
+*/
+QDeadlineTimer QNetworkAddressEntry::validityLifetime() const
+{
+ return d->validityLifetime;
+}
+
+/*!
+ \since 5.11
+
+ Sets both the preferred and valid lifetimes for this address to the \a
+ preferred and \a validity deadlines, respectively. After this call,
+ isLifetimeKnown() will return \c true, even if both parameters are
+ QDeadlineTimer::Forever.
+
+ \sa preferredLifetime(), validityLifetime(), isLifetimeKnown(), clearAddressLifetime()
+*/
+void QNetworkAddressEntry::setAddressLifetime(QDeadlineTimer preferred, QDeadlineTimer validity)
+{
+ d->preferredLifetime = preferred;
+ d->validityLifetime = validity;
+ d->lifetimeKnown = true;
+}
+
+/*!
+ \since 5.11
+
+ Resets both the preferred and valid lifetimes for this address. After this
+ call, isLifetimeKnown() will return \c false.
+
+ \sa preferredLifetime(), validityLifetime(), isLifetimeKnown(), setAddressLifetime()
+*/
+void QNetworkAddressEntry::clearAddressLifetime()
+{
+ d->preferredLifetime = QDeadlineTimer::Forever;
+ d->validityLifetime = QDeadlineTimer::Forever;
+ d->lifetimeKnown = false;
+}
+
+/*!
+ \since 5.11
+
+ Returns \c true if this address is permanent on this interface, \c false if
+ it's temporary. A permenant address is one which has no expiration time and
+ is often static (manually configured).
+
+ If this information could not be determined, this function returns \c true.
+
+ \note Depending on the operating system and the networking configuration
+ tool, it is possible for a temporary address to be interpreted as
+ permanent, if the tool did not inform the details correctly to the
+ operating system.
+
+ \sa isLifetimeKnown(), validityLifetime(), isTemporary()
+*/
+bool QNetworkAddressEntry::isPermanent() const
+{
+ return d->validityLifetime.isForever();
+}
+
+/*!
+ \fn bool QNetworkAddressEntry::isTemporary() const
+ \since 5.11
+
+ Returns \c true if this address is temporary on this interface, \c false if
+ it's permanent.
+
+ \sa isLifetimeKnown(), validityLifetime(), isPermanent()
+*/
+
+/*!
\class QNetworkInterface
\brief The QNetworkInterface class provides a listing of the host's IP
addresses and network interfaces.
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index 7036117e2d..d39615e430 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
-
+class QDeadlineTimer;
template<typename T> class QList;
class QNetworkAddressEntryPrivate;
@@ -81,6 +81,14 @@ public:
QHostAddress broadcast() const;
void setBroadcast(const QHostAddress &newBroadcast);
+ bool isLifetimeKnown() const;
+ QDeadlineTimer preferredLifetime() const;
+ QDeadlineTimer validityLifetime() const;
+ void setAddressLifetime(QDeadlineTimer preferred, QDeadlineTimer validity);
+ void clearAddressLifetime();
+ bool isPermanent() const;
+ bool isTemporary() const { return !isPermanent(); }
+
private:
QScopedPointer<QNetworkAddressEntryPrivate> d;
};
diff --git a/src/network/kernel/qnetworkinterface_linux.cpp b/src/network/kernel/qnetworkinterface_linux.cpp
index a985342286..cc66c310cb 100644
--- a/src/network/kernel/qnetworkinterface_linux.cpp
+++ b/src/network/kernel/qnetworkinterface_linux.cpp
@@ -386,6 +386,18 @@ static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *>
entry.setBroadcast(makeAddress(payloadPtr, payloadLen));
break;
+ case IFA_CACHEINFO:
+ if (size_t(payloadLen) >= sizeof(ifa_cacheinfo)) {
+ auto cacheinfo = reinterpret_cast<ifa_cacheinfo *>(payloadPtr);
+ auto toDeadline = [](quint32 lifetime) -> QDeadlineTimer {
+ if (lifetime == quint32(-1))
+ return QDeadlineTimer::Forever;
+ return QDeadlineTimer(lifetime * 1000);
+ };
+ entry.setAddressLifetime(toDeadline(cacheinfo->ifa_prefered), toDeadline(cacheinfo->ifa_valid));
+ }
+ break;
+
case IFA_FLAGS:
Q_ASSERT(payloadLen == 4);
flags = qFromUnaligned<quint32>(payloadPtr);
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index 44b9b013bc..305a8fe020 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -54,6 +54,7 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtNetwork/qnetworkinterface.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qdeadlinetimer.h>
#include <QtCore/qlist.h>
#include <QtCore/qreadwritelock.h>
#include <QtCore/qstring.h>
@@ -70,7 +71,11 @@ class QNetworkAddressEntryPrivate
public:
QHostAddress address;
QHostAddress broadcast;
+ QDeadlineTimer preferredLifetime = QDeadlineTimer::Forever;
+ QDeadlineTimer validityLifetime = QDeadlineTimer::Forever;
+
QNetmask netmask;
+ bool lifetimeKnown = false;
};
class QNetworkInterfacePrivate: public QSharedData
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index fb94a2185d..7733f073d0 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -46,6 +46,10 @@
#ifndef QT_NO_NETWORKINTERFACE
+#if defined(QT_NO_CLOCK_MONOTONIC)
+# include "qdatetime.h"
+#endif
+
#if defined(QT_LINUXBASE)
# define QT_NO_GETIFADDRS
#endif
@@ -381,11 +385,19 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
return interfaces;
}
+static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
+{
+ Q_UNUSED(entry);
+ Q_UNUSED(sa);
+ Q_UNUSED(ifname)
+}
+
# elif defined(Q_OS_BSD4)
QT_BEGIN_INCLUDE_NAMESPACE
# include <net/if_dl.h>
# include <net/if_media.h>
# include <net/if_types.h>
+# include <netinet/in_var.h>
QT_END_INCLUDE_NAMESPACE
static int openSocket(int &socket)
@@ -471,6 +483,46 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
return interfaces;
}
+static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
+{
+ // get IPv6 address lifetimes
+ if (sa->sa_family != AF_INET6)
+ return;
+
+ struct in6_ifreq ifr;
+
+ int s6 = qt_safe_socket(AF_INET6, SOCK_DGRAM, 0);
+ if (Q_UNLIKELY(s6 < 0)) {
+ qErrnoWarning("QNetworkInterface: could not create IPv6 socket");
+ return;
+ }
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ // get lifetimes
+ ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
+ if (qt_safe_ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr) < 0) {
+ qt_safe_close(s6);
+ return;
+ }
+ qt_safe_close(s6);
+
+ auto toDeadline = [](time_t when) {
+ QDeadlineTimer deadline = QDeadlineTimer::Forever;
+ if (when) {
+#if defined(QT_NO_CLOCK_MONOTONIC)
+ // no monotonic clock
+ deadline.setPreciseRemainingTime(when - QDateTime::currentSecsSinceEpoch());
+#else
+ deadline.setPreciseDeadline(when);
+#endif
+ }
+ return deadline;
+ };
+ entry->setAddressLifetime(toDeadline(ifr.ifr_ifru.ifru_lifetime.ia6t_preferred),
+ toDeadline(ifr.ifr_ifru.ifru_lifetime.ia6t_expire));
+}
+
# else // Generic version
static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
@@ -502,9 +554,14 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
return interfaces;
}
+static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
+{
+ Q_UNUSED(entry);
+ Q_UNUSED(sa);
+ Q_UNUSED(ifname)
+}
# endif
-
static QList<QNetworkInterfacePrivate *> interfaceListing()
{
QList<QNetworkInterfacePrivate *> interfaces;
@@ -553,6 +610,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
entry.setNetmask(addressFromSockaddr(ptr->ifa_netmask, iface->index, iface->name));
if (iface->flags & QNetworkInterface::CanBroadcast)
entry.setBroadcast(addressFromSockaddr(ptr->ifa_broadaddr, iface->index, iface->name));
+ getAddressExtraInfo(&entry, ptr->ifa_addr, name.latin1());
iface->addressEntries << entry;
}
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index f0c0ba2126..34d253a6d2 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -222,6 +222,14 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
QNetworkAddressEntry entry;
entry.setIp(addressFromSockaddr(addr->Address.lpSockaddr));
entry.setPrefixLength(addr->OnLinkPrefixLength);
+
+ auto toDeadline = [](ULONG lifetime) -> QDeadlineTimer {
+ if (lifetime == 0xffffffffUL)
+ return QDeadlineTimer::Forever;
+ return QDeadlineTimer(lifetime * 1000);
+ };
+ entry.setAddressLifetime(toDeadline(addr->ValidLifetime), toDeadline(addr->PreferredLifetime));
+
iface->addressEntries << entry;
}
}