зеркало из 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
|
||||
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."
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
@ -42,6 +41,13 @@ namespace net {
|
|||
// milliseconds
|
||||
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");
|
||||
#define LOG(args) MOZ_LOG(gNlSvcLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
|
@ -586,8 +592,8 @@ NetlinkService::LinkInfo::LinkInfo(NetlinkLink* aLink)
|
|||
|
||||
NetlinkService::LinkInfo::~LinkInfo() {}
|
||||
|
||||
bool NetlinkService::LinkInfo::UpdateLinkStatus() {
|
||||
LOG(("NetlinkService::LinkInfo::UpdateLinkStatus"));
|
||||
bool NetlinkService::LinkInfo::UpdateStatus() {
|
||||
LOG(("NetlinkService::LinkInfo::UpdateStatus"));
|
||||
|
||||
bool oldIsUp = mIsUp;
|
||||
mIsUp = false;
|
||||
|
@ -619,8 +625,6 @@ NS_IMPL_ISUPPORTS(NetlinkService, nsIRunnable)
|
|||
NetlinkService::NetlinkService()
|
||||
: mMutex("NetlinkService::mMutex"),
|
||||
mInitialScanFinished(false),
|
||||
mDoRouteCheckIPv4(false),
|
||||
mDoRouteCheckIPv6(false),
|
||||
mMsgId(0),
|
||||
mLinkUp(true),
|
||||
mRecalculateNetworkId(false) {
|
||||
|
@ -758,7 +762,6 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
|||
nsAutoCString linkName;
|
||||
link->GetName(linkName);
|
||||
|
||||
bool checkLinks = false;
|
||||
LinkInfo* linkInfo = nullptr;
|
||||
mLinks.Get(linkIndex, &linkInfo);
|
||||
|
||||
|
@ -783,10 +786,7 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
|||
}
|
||||
|
||||
linkInfo->mLink = link.forget();
|
||||
if (linkInfo->UpdateLinkStatus()) {
|
||||
// Link status has changed
|
||||
checkLinks = true;
|
||||
}
|
||||
linkInfo->UpdateStatus();
|
||||
}
|
||||
} else {
|
||||
if (!linkInfo) {
|
||||
|
@ -795,60 +795,9 @@ void NetlinkService::OnLinkMessage(struct nlmsghdr* aNlh) {
|
|||
linkName.get()));
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -926,8 +875,7 @@ void NetlinkService::OnAddrMessage(struct nlmsghdr* aNlh) {
|
|||
}
|
||||
}
|
||||
|
||||
if (linkInfo->UpdateLinkStatus()) {
|
||||
UpdateLinkStatus();
|
||||
if (linkInfo->UpdateStatus()) {
|
||||
TriggerNetworkIDCalculation();
|
||||
} else {
|
||||
// Even if the link status hasn't changed, network ID might have changed
|
||||
|
@ -1199,7 +1147,6 @@ void NetlinkService::RemovePendingMsg() {
|
|||
// by the incoming messages.
|
||||
mInitialScanFinished = true;
|
||||
|
||||
UpdateLinkStatus();
|
||||
TriggerNetworkIDCalculation();
|
||||
|
||||
// Link status should be known by now.
|
||||
|
@ -1294,25 +1241,22 @@ nsresult NetlinkService::Init(NetlinkServiceListener* aListener) {
|
|||
|
||||
mListener = aListener;
|
||||
|
||||
nsAutoCString routecheckIP;
|
||||
|
||||
rv =
|
||||
Preferences::GetCString("network.netlink.route.check.IPv4", routecheckIP);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (inet_pton(AF_INET, routecheckIP.get(), &mRouteCheckIPv4) == 1) {
|
||||
mDoRouteCheckIPv4 = true;
|
||||
}
|
||||
if (inet_pton(AF_INET, NETLINK_ROUTE_CHECK_IPV4, &mRouteCheckIPv4) != 1) {
|
||||
LOG(("Cannot parse address " NETLINK_ROUTE_CHECK_IPV4));
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"Cannot parse address " NETLINK_ROUTE_CHECK_IPV4);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv =
|
||||
Preferences::GetCString("network.netlink.route.check.IPv6", routecheckIP);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (inet_pton(AF_INET6, routecheckIP.get(), &mRouteCheckIPv6) == 1) {
|
||||
mDoRouteCheckIPv6 = true;
|
||||
}
|
||||
if (inet_pton(AF_INET6, NETLINK_ROUTE_CHECK_IPV6, &mRouteCheckIPv6) != 1) {
|
||||
LOG(("Cannot parse address " NETLINK_ROUTE_CHECK_IPV6));
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"Cannot parse address " NETLINK_ROUTE_CHECK_IPV6);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (pipe(mShutdownPipe) == -1) {
|
||||
LOG(("Cannot create pipe"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1378,21 +1322,11 @@ int NetlinkService::GetPollWait() {
|
|||
|
||||
double period = (TimeStamp::Now() - mTriggerTime).ToMilliseconds();
|
||||
if (period >= kNetworkChangeCoalescingPeriod) {
|
||||
// Coalescing time has elapsed, do route check
|
||||
if (!mDoRouteCheckIPv4 && !mDoRouteCheckIPv6) {
|
||||
// If route checking is disabled for whatever reason, calculate ID now
|
||||
CalculateNetworkID();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
// Coalescing time has elapsed, send route check messages to find out where
|
||||
// IPv4 and IPv6 traffic is routed and calculate network ID after the
|
||||
// response is received.
|
||||
EnqueueRtMsg(AF_INET, &mRouteCheckIPv4);
|
||||
EnqueueRtMsg(AF_INET6, &mRouteCheckIPv6);
|
||||
|
||||
// Return 0 to make sure we start sending enqueued messages immediately
|
||||
return 0;
|
||||
|
@ -1565,9 +1499,8 @@ bool NetlinkService::CalculateIDForFamily(uint8_t aFamily, SHA1Sum* aSHA1) {
|
|||
}
|
||||
|
||||
if (!*routeCheckResultPtr) {
|
||||
// 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
|
||||
// from the preferences. In any case, there is no more to do.
|
||||
// If we don't have result for route check to mRouteCheckIPv4/6 host, the
|
||||
// network is unreachable and there is no more to do.
|
||||
LOG(("There is no route check result."));
|
||||
return retval;
|
||||
}
|
||||
|
@ -1758,6 +1691,38 @@ void NetlinkService::ComputeDNSSuffixList() {
|
|||
#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".
|
||||
void NetlinkService::CalculateNetworkID() {
|
||||
LOG(("NetlinkService::CalculateNetworkID"));
|
||||
|
|
|
@ -86,14 +86,8 @@ class NetlinkService : public nsIRunnable {
|
|||
// A pipe to signal shutdown with.
|
||||
int mShutdownPipe[2];
|
||||
|
||||
// Is true if preference network.netlink.route.check.IPv4 was successfully
|
||||
// parsed and stored to mRouteCheckIPv4
|
||||
bool mDoRouteCheckIPv4;
|
||||
// IP addresses that are used to check the route for public traffic.
|
||||
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;
|
||||
|
||||
pid_t mPid;
|
||||
|
@ -119,7 +113,7 @@ class NetlinkService : public nsIRunnable {
|
|||
|
||||
// Updates mIsUp according to current mLink and mAddresses. Returns true if
|
||||
// the value has changed.
|
||||
bool UpdateLinkStatus();
|
||||
bool UpdateStatus();
|
||||
|
||||
// NetlinkLink structure for this link
|
||||
nsAutoPtr<NetlinkLink> mLink;
|
||||
|
|
Загрузка…
Ссылка в новой задаче