зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1593693 - nsINetworkLinkService.isLinkUp returns true when no network connection is available, r=valentin
Determining link status from states and addresses of the individual interfaces isn't always reliable. With this patch we assume the link is up when we could find a route for kRouteCheckIPv4 host or kRouteCheckIPv6 host. Differential Revision: https://phabricator.services.mozilla.com/D52027 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
7e65be9414
Коммит
2d153a80d4
|
@ -6823,20 +6823,6 @@
|
||||||
value: true
|
value: true
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
# IP addresses that are used by netlink service to check whether default route
|
|
||||||
# is used for outgoing traffic. They are used just to check routing rules,
|
|
||||||
# no packets are sent to those hosts. Initially, addresses of host
|
|
||||||
# detectportal.firefox.com were used but they don't necessarily need to be
|
|
||||||
# updated when addresses of this host change.
|
|
||||||
- name: network.netlink.route.check.IPv4
|
|
||||||
type: String
|
|
||||||
value: "23.219.91.27"
|
|
||||||
mirror: never
|
|
||||||
- name: network.netlink.route.check.IPv6
|
|
||||||
type: String
|
|
||||||
value: "2a02:26f0:40::17db:5b1b"
|
|
||||||
mirror: never
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Prefs starting with "nglayout."
|
# Prefs starting with "nglayout."
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "mozilla/Base64.h"
|
#include "mozilla/Base64.h"
|
||||||
#include "mozilla/FileUtils.h"
|
#include "mozilla/FileUtils.h"
|
||||||
#include "mozilla/Preferences.h"
|
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
@ -42,6 +41,13 @@ namespace net {
|
||||||
// milliseconds
|
// milliseconds
|
||||||
static const unsigned int kNetworkChangeCoalescingPeriod = 1000;
|
static const unsigned int kNetworkChangeCoalescingPeriod = 1000;
|
||||||
|
|
||||||
|
// IP addresses that are used to check the route for public traffic. They are
|
||||||
|
// used just to check routing rules, no packets are sent to those hosts.
|
||||||
|
// Initially, addresses of host detectportal.firefox.com were used but they
|
||||||
|
// don't necessarily need to be updated when addresses of this host change.
|
||||||
|
#define NETLINK_ROUTE_CHECK_IPV4 "23.219.91.27"
|
||||||
|
#define NETLINK_ROUTE_CHECK_IPV6 "2a02:26f0:40::17db:5b1b"
|
||||||
|
|
||||||
static LazyLogModule gNlSvcLog("NetlinkService");
|
static LazyLogModule gNlSvcLog("NetlinkService");
|
||||||
#define LOG(args) MOZ_LOG(gNlSvcLog, mozilla::LogLevel::Debug, args)
|
#define LOG(args) MOZ_LOG(gNlSvcLog, mozilla::LogLevel::Debug, args)
|
||||||
|
|
||||||
|
@ -586,8 +592,8 @@ NetlinkService::LinkInfo::LinkInfo(NetlinkLink* aLink)
|
||||||
|
|
||||||
NetlinkService::LinkInfo::~LinkInfo() {}
|
NetlinkService::LinkInfo::~LinkInfo() {}
|
||||||
|
|
||||||
bool NetlinkService::LinkInfo::UpdateLinkStatus() {
|
bool NetlinkService::LinkInfo::UpdateStatus() {
|
||||||
LOG(("NetlinkService::LinkInfo::UpdateLinkStatus"));
|
LOG(("NetlinkService::LinkInfo::UpdateStatus"));
|
||||||
|
|
||||||
bool oldIsUp = mIsUp;
|
bool oldIsUp = mIsUp;
|
||||||
mIsUp = false;
|
mIsUp = false;
|
||||||
|
@ -619,8 +625,6 @@ NS_IMPL_ISUPPORTS(NetlinkService, nsIRunnable)
|
||||||
NetlinkService::NetlinkService()
|
NetlinkService::NetlinkService()
|
||||||
: mMutex("NetlinkService::mMutex"),
|
: mMutex("NetlinkService::mMutex"),
|
||||||
mInitialScanFinished(false),
|
mInitialScanFinished(false),
|
||||||
mDoRouteCheckIPv4(false),
|
|
||||||
mDoRouteCheckIPv6(false),
|
|
||||||
mMsgId(0),
|
mMsgId(0),
|
||||||
mLinkUp(true),
|
mLinkUp(true),
|
||||||
mRecalculateNetworkId(false) {
|
mRecalculateNetworkId(false) {
|
||||||
|
@ -758,7 +762,6 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
||||||
nsAutoCString linkName;
|
nsAutoCString linkName;
|
||||||
link->GetName(linkName);
|
link->GetName(linkName);
|
||||||
|
|
||||||
bool checkLinks = false;
|
|
||||||
LinkInfo* linkInfo = nullptr;
|
LinkInfo* linkInfo = nullptr;
|
||||||
mLinks.Get(linkIndex, &linkInfo);
|
mLinks.Get(linkIndex, &linkInfo);
|
||||||
|
|
||||||
|
@ -783,10 +786,7 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
linkInfo->mLink = link.forget();
|
linkInfo->mLink = link.forget();
|
||||||
if (linkInfo->UpdateLinkStatus()) {
|
linkInfo->UpdateStatus();
|
||||||
// Link status has changed
|
|
||||||
checkLinks = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!linkInfo) {
|
if (!linkInfo) {
|
||||||
|
@ -795,60 +795,9 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
||||||
linkName.get()));
|
linkName.get()));
|
||||||
} else {
|
} else {
|
||||||
LOG(("Removing link [index=%u, name=%s]", linkIndex, linkName.get()));
|
LOG(("Removing link [index=%u, name=%s]", linkIndex, linkName.get()));
|
||||||
if (linkInfo->mIsUp) {
|
|
||||||
// We're removing link that is up, check link status
|
|
||||||
checkLinks = true;
|
|
||||||
}
|
|
||||||
mLinks.Remove(linkIndex);
|
mLinks.Remove(linkIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkLinks) {
|
|
||||||
UpdateLinkStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetlinkService::UpdateLinkStatus() {
|
|
||||||
if (!mInitialScanFinished) {
|
|
||||||
// Wait until we get all links via netlink
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(("NetlinkService::UpdateLinkStatus"));
|
|
||||||
|
|
||||||
// Link is up when there is non-local address associated with it.
|
|
||||||
bool newLinkUp = false;
|
|
||||||
|
|
||||||
for (auto iter = mLinks.ConstIter(); !iter.Done(); iter.Next()) {
|
|
||||||
LinkInfo* linkInfo = iter.Data();
|
|
||||||
nsAutoCString linkName;
|
|
||||||
linkInfo->mLink->GetName(linkName);
|
|
||||||
|
|
||||||
if (linkInfo->mIsUp) {
|
|
||||||
LOG((" %s is up", linkName.get()));
|
|
||||||
newLinkUp = true;
|
|
||||||
} else {
|
|
||||||
LOG((" %s is down", linkName.get()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mLinkUp != newLinkUp) {
|
|
||||||
RefPtr<NetlinkServiceListener> listener;
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(mMutex);
|
|
||||||
listener = mListener;
|
|
||||||
mLinkUp = newLinkUp;
|
|
||||||
}
|
|
||||||
if (mLinkUp) {
|
|
||||||
if (listener) {
|
|
||||||
listener->OnLinkUp();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (listener) {
|
|
||||||
listener->OnLinkDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
|
void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
|
||||||
|
@ -926,8 +875,7 @@ void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linkInfo->UpdateLinkStatus()) {
|
if (linkInfo->UpdateStatus()) {
|
||||||
UpdateLinkStatus();
|
|
||||||
TriggerNetworkIDCalculation();
|
TriggerNetworkIDCalculation();
|
||||||
} else {
|
} else {
|
||||||
// Even if the link status hasn't changed, network ID might have changed
|
// Even if the link status hasn't changed, network ID might have changed
|
||||||
|
@ -1199,7 +1147,6 @@ void NetlinkService::RemovePendingMsg() {
|
||||||
// by the incoming messages.
|
// by the incoming messages.
|
||||||
mInitialScanFinished = true;
|
mInitialScanFinished = true;
|
||||||
|
|
||||||
UpdateLinkStatus();
|
|
||||||
TriggerNetworkIDCalculation();
|
TriggerNetworkIDCalculation();
|
||||||
|
|
||||||
// Link status should be known by now.
|
// Link status should be known by now.
|
||||||
|
@ -1294,25 +1241,22 @@ nsresult NetlinkService::Init(NetlinkServiceListener* aListener) {
|
||||||
|
|
||||||
mListener = aListener;
|
mListener = aListener;
|
||||||
|
|
||||||
nsAutoCString routecheckIP;
|
if (inet_pton(AF_INET, NETLINK_ROUTE_CHECK_IPV4, &mRouteCheckIPv4) != 1) {
|
||||||
|
LOG(("Cannot parse address " NETLINK_ROUTE_CHECK_IPV4));
|
||||||
rv =
|
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||||
Preferences::GetCString("network.netlink.route.check.IPv4", routecheckIP);
|
"Cannot parse address " NETLINK_ROUTE_CHECK_IPV4);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
return NS_ERROR_UNEXPECTED;
|
||||||
if (inet_pton(AF_INET, routecheckIP.get(), &mRouteCheckIPv4) == 1) {
|
|
||||||
mDoRouteCheckIPv4 = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv =
|
if (inet_pton(AF_INET6, NETLINK_ROUTE_CHECK_IPV6, &mRouteCheckIPv6) != 1) {
|
||||||
Preferences::GetCString("network.netlink.route.check.IPv6", routecheckIP);
|
LOG(("Cannot parse address " NETLINK_ROUTE_CHECK_IPV6));
|
||||||
if (NS_SUCCEEDED(rv)) {
|
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||||
if (inet_pton(AF_INET6, routecheckIP.get(), &mRouteCheckIPv6) == 1) {
|
"Cannot parse address " NETLINK_ROUTE_CHECK_IPV6);
|
||||||
mDoRouteCheckIPv6 = true;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe(mShutdownPipe) == -1) {
|
if (pipe(mShutdownPipe) == -1) {
|
||||||
|
LOG(("Cannot create pipe"));
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1378,21 +1322,11 @@ int NetlinkService::GetPollWait() {
|
||||||
|
|
||||||
double period = (TimeStamp::Now() - mTriggerTime).ToMilliseconds();
|
double period = (TimeStamp::Now() - mTriggerTime).ToMilliseconds();
|
||||||
if (period >= kNetworkChangeCoalescingPeriod) {
|
if (period >= kNetworkChangeCoalescingPeriod) {
|
||||||
// Coalescing time has elapsed, do route check
|
// Coalescing time has elapsed, send route check messages to find out where
|
||||||
if (!mDoRouteCheckIPv4 && !mDoRouteCheckIPv6) {
|
// IPv4 and IPv6 traffic is routed and calculate network ID after the
|
||||||
// If route checking is disabled for whatever reason, calculate ID now
|
// response is received.
|
||||||
CalculateNetworkID();
|
EnqueueRtMsg(AF_INET, &mRouteCheckIPv4);
|
||||||
return -1;
|
EnqueueRtMsg(AF_INET6, &mRouteCheckIPv6);
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise send route check messages and calculate network ID after the
|
|
||||||
// response is received
|
|
||||||
if (mDoRouteCheckIPv4) {
|
|
||||||
EnqueueRtMsg(AF_INET, &mRouteCheckIPv4);
|
|
||||||
}
|
|
||||||
if (mDoRouteCheckIPv6) {
|
|
||||||
EnqueueRtMsg(AF_INET6, &mRouteCheckIPv6);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return 0 to make sure we start sending enqueued messages immediately
|
// Return 0 to make sure we start sending enqueued messages immediately
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1565,9 +1499,8 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*routeCheckResultPtr) {
|
if (!*routeCheckResultPtr) {
|
||||||
// If we don't have result for route check to mRouteCheckIPv4/6 host. The
|
// If we don't have result for route check to mRouteCheckIPv4/6 host, the
|
||||||
// network is either unreachable or the checking was disabled by removing IP
|
// network is unreachable and there is no more to do.
|
||||||
// from the preferences. In any case, there is no more to do.
|
|
||||||
LOG(("There is no route check result."));
|
LOG(("There is no route check result."));
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1758,6 +1691,38 @@ void NetlinkService::ComputeDNSSuffixList() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetlinkService::UpdateLinkStatus() {
|
||||||
|
LOG(("NetlinkService::UpdateLinkStatus"));
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mRecalculateNetworkId);
|
||||||
|
MOZ_ASSERT(mInitialScanFinished);
|
||||||
|
|
||||||
|
// Link is up when we have a route for NETLINK_ROUTE_CHECK_IPV4 or
|
||||||
|
// NETLINK_ROUTE_CHECK_IPV6
|
||||||
|
bool newLinkUp = mIPv4RouteCheckResult || mIPv6RouteCheckResult;
|
||||||
|
|
||||||
|
if (mLinkUp == newLinkUp) {
|
||||||
|
LOG(("Link status hasn't changed [linkUp=%d]", mLinkUp));
|
||||||
|
} else {
|
||||||
|
LOG(("Link status has changed [linkUp=%d]", newLinkUp));
|
||||||
|
RefPtr<NetlinkServiceListener> listener;
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
listener = mListener;
|
||||||
|
mLinkUp = newLinkUp;
|
||||||
|
}
|
||||||
|
if (mLinkUp) {
|
||||||
|
if (listener) {
|
||||||
|
listener->OnLinkUp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (listener) {
|
||||||
|
listener->OnLinkDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out the "network identification".
|
// Figure out the "network identification".
|
||||||
void NetlinkService::CalculateNetworkID() {
|
void NetlinkService::CalculateNetworkID() {
|
||||||
LOG(("NetlinkService::CalculateNetworkID"));
|
LOG(("NetlinkService::CalculateNetworkID"));
|
||||||
|
|
|
@ -86,14 +86,8 @@ class NetlinkService : public nsIRunnable {
|
||||||
// A pipe to signal shutdown with.
|
// A pipe to signal shutdown with.
|
||||||
int mShutdownPipe[2];
|
int mShutdownPipe[2];
|
||||||
|
|
||||||
// Is true if preference network.netlink.route.check.IPv4 was successfully
|
// IP addresses that are used to check the route for public traffic.
|
||||||
// parsed and stored to mRouteCheckIPv4
|
|
||||||
bool mDoRouteCheckIPv4;
|
|
||||||
struct in_addr mRouteCheckIPv4;
|
struct in_addr mRouteCheckIPv4;
|
||||||
|
|
||||||
// Is true if preference network.netlink.route.check.IPv6 was successfully
|
|
||||||
// parsed and stored to mRouteCheckIPv6
|
|
||||||
bool mDoRouteCheckIPv6;
|
|
||||||
struct in6_addr mRouteCheckIPv6;
|
struct in6_addr mRouteCheckIPv6;
|
||||||
|
|
||||||
pid_t mPid;
|
pid_t mPid;
|
||||||
|
@ -119,7 +113,7 @@ class NetlinkService : public nsIRunnable {
|
||||||
|
|
||||||
// Updates mIsUp according to current mLink and mAddresses. Returns true if
|
// Updates mIsUp according to current mLink and mAddresses. Returns true if
|
||||||
// the value has changed.
|
// the value has changed.
|
||||||
bool UpdateLinkStatus();
|
bool UpdateStatus();
|
||||||
|
|
||||||
// NetlinkLink structure for this link
|
// NetlinkLink structure for this link
|
||||||
nsAutoPtr<NetlinkLink> mLink;
|
nsAutoPtr<NetlinkLink> mLink;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче