QNetConMonitor(Win): Account for LOCALNETWORK reachability

What I originally thought NLM_CONNECTIVITY_IPV*_SUBNET meant turns out
to be what NLM_CONNECTIVITY_IPV*_LOCALNETWORK is, leaving me to wonder
when *_SUBNET is actually used. Anyway we now also check *_LOCALNETWORK
to make sure we're not unnecessarily denying certain connections to be
made.

At the same time check for link-local connections where both local and
remote are link-local, in this case even NLM_CONNECTIVITY_IPV*_NOTRAFFIC
is valid. Unfortunately this check cannot be done in
QNetworkStatusMonitor, so QNAM will likely not allow these connections.

Task-number: QTBUG-80947
Change-Id: Ieb96ce9f4a478eef0c3ea47f2471f701c102b4d4
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Mårten Nordheim 2020-02-11 16:48:19 +01:00
parent 2a2ffe8a48
commit 6c3bca01d9

View File

@ -163,11 +163,14 @@ private:
ComPtr<QNetworkConnectionEvents> connectionEvents;
// We can assume we have access to internet/subnet when this class is created because
// connection has already been established to the peer:
NLM_CONNECTIVITY connectivity =
NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET
| NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET);
NLM_CONNECTIVITY connectivity = NLM_CONNECTIVITY(
NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET
| NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET
| NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_LOCALNETWORK
| NLM_CONNECTIVITY_IPV4_NOTRAFFIC | NLM_CONNECTIVITY_IPV6_NOTRAFFIC);
bool sameSubnet = false;
bool isLinkLocal = false;
bool monitoring = false;
bool comInitFailed = false;
bool remoteIsIPv6 = false;
@ -370,6 +373,7 @@ bool QNetworkConnectionMonitorPrivate::setTargets(const QHostAddress &local,
return false;
}
sameSubnet = remote.isInSubnet(local, it->prefixLength());
isLinkLocal = remote.isLinkLocal() && local.isLinkLocal();
remoteIsIPv6 = remote.protocol() == QAbstractSocket::IPv6Protocol;
return connectionEvents->setTarget(iface);
@ -461,9 +465,28 @@ void QNetworkConnectionMonitor::stopMonitoring()
bool QNetworkConnectionMonitor::isReachable()
{
Q_D(QNetworkConnectionMonitor);
NLM_CONNECTIVITY required = d->sameSubnet
? (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_SUBNET : NLM_CONNECTIVITY_IPV4_SUBNET)
: (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_INTERNET : NLM_CONNECTIVITY_IPV4_INTERNET);
const NLM_CONNECTIVITY RequiredSameSubnetIPv6 =
NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV6_SUBNET | NLM_CONNECTIVITY_IPV6_LOCALNETWORK
| NLM_CONNECTIVITY_IPV6_INTERNET);
const NLM_CONNECTIVITY RequiredSameSubnetIPv4 =
NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV4_LOCALNETWORK
| NLM_CONNECTIVITY_IPV4_INTERNET);
NLM_CONNECTIVITY required;
if (d->isLinkLocal) {
required = NLM_CONNECTIVITY(
d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_NOTRAFFIC | RequiredSameSubnetIPv6
: NLM_CONNECTIVITY_IPV4_NOTRAFFIC | RequiredSameSubnetIPv4);
} else if (d->sameSubnet) {
required =
NLM_CONNECTIVITY(d->remoteIsIPv6 ? RequiredSameSubnetIPv6 : RequiredSameSubnetIPv4);
} else {
required = NLM_CONNECTIVITY(d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_INTERNET
: NLM_CONNECTIVITY_IPV4_INTERNET);
}
return d_func()->connectivity & required;
}
@ -695,7 +718,8 @@ bool QNetworkStatusMonitor::isNetworkAccessible()
{
return d_func()->connectivity
& (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET
| NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET);
| NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET
| NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_LOCALNETWORK);
}
bool QNetworkStatusMonitor::isEnabled()