Backed out 8 changesets (bug 1395914, bug 1561005) for causing bustages in nsNetworkLinkService and nsNotifyAddrListener.cpp CLOSED TREE

Backed out changeset c552aeab0fbf (bug 1561005)
Backed out changeset 61cf9ae8abcf (bug 1561005)
Backed out changeset 5c33e521c0e8 (bug 1561005)
Backed out changeset 82eeb4c5e535 (bug 1561005)
Backed out changeset 6b3b29de9c78 (bug 1561005)
Backed out changeset 719b3b61b9a9 (bug 1395914)
Backed out changeset 2b23587aa5ff (bug 1395914)
Backed out changeset 47f2f3e8d5f9 (bug 1395914)
This commit is contained in:
Mihai Alexandru Michis 2019-06-28 14:37:13 +03:00
Родитель 8673cb0d40
Коммит ff9ddc0bc1
10 изменённых файлов: 191 добавлений и 434 удалений

Просмотреть файл

@ -1,50 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef NETWORK_IPV6_UTILS_H_
#define NETWORK_IPV6_UTILS_H_
namespace mozilla {
namespace net {
namespace utils {
// IPv6 address scopes.
#define IPV6_SCOPE_GLOBAL 0 // Global scope.
#define IPV6_SCOPE_LINKLOCAL 1 // Link-local scope.
#define IPV6_SCOPE_SITELOCAL 2 // Site-local scope (deprecated).
#define IPV6_SCOPE_UNIQUELOCAL 3 // Unique local
#define IPV6_SCOPE_NODELOCAL 4 // Loopback
// Return the scope of the given address.
static int ipv6_scope(const unsigned char addr[16]) {
const unsigned char* b = addr;
unsigned short w = (unsigned short)((b[0] << 8) | b[1]);
if ((b[0] & 0xFE) == 0xFC) {
return IPV6_SCOPE_UNIQUELOCAL;
}
switch (w & 0xFFC0) {
case 0xFE80:
return IPV6_SCOPE_LINKLOCAL;
case 0xFEC0:
return IPV6_SCOPE_SITELOCAL;
case 0x0000:
w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] | b[10] |
b[11] | b[12] | b[13] | b[14];
if (w || b[15] != 0x01) {
break;
}
return IPV6_SCOPE_NODELOCAL;
default:
break;
}
return IPV6_SCOPE_GLOBAL;
}
} // namespace utils
} // namespace net
} // namespace mozilla
#endif // NETWORK_IPV6_UTILS_H_

Просмотреть файл

@ -45,12 +45,6 @@ interface nsINetworkLinkService : nsISupports
* The type of network connection.
*/
readonly attribute unsigned long linkType;
/**
* A string uniquely identifying the current active network interfaces.
* Empty when there are no active network interfaces.
*/
readonly attribute ACString networkID;
};
%{C++

Просмотреть файл

@ -52,9 +52,3 @@ nsAndroidNetworkLinkService::GetLinkType(uint32_t* aLinkType) {
*aLinkType = java::GeckoAppShell::GetNetworkLinkType();
return NS_OK;
}
NS_IMETHODIMP
nsAndroidNetworkLinkService::GetNetworkID(nsACString& aNetworkID) {
aNetworkID.Truncate();
return NS_OK;
}

Просмотреть файл

@ -25,7 +25,6 @@
#include "mozilla/SHA1.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "../../base/IPv6Utils.h"
/* a shorter name that better explains what it does */
#define EINTR_RETRY(x) MOZ_TEMP_FAILURE_RETRY(x)
@ -45,8 +44,8 @@ NS_IMPL_ISUPPORTS(nsNotifyAddrListener, nsINetworkLinkService, nsIRunnable,
nsIObserver)
nsNotifyAddrListener::nsNotifyAddrListener()
: mMutex("nsNotifyAddrListener::mMutex"),
mLinkUp(true), // assume true by default
: mLinkUp(true) // assume true by default
,
mStatusKnown(false),
mAllowChangedEvent(true),
mCoalescingActive(false) {
@ -88,21 +87,14 @@ nsNotifyAddrListener::GetLinkType(uint32_t* aLinkType) {
return NS_OK;
}
NS_IMETHODIMP
nsNotifyAddrListener::GetNetworkID(nsACString& aNetworkID) {
MutexAutoLock lock(mMutex);
aNetworkID = mNetworkId;
return NS_OK;
}
//
// Figure out the current IPv4 "network identification" string.
// Figure out the current "network identification" string.
//
// It detects the IP of the default gateway in the routing table, then the MAC
// address of that IP in the ARP table before it hashes that string (to avoid
// information leakage).
//
static bool ipv4NetworkId(SHA1Sum* sha1) {
void nsNotifyAddrListener::calculateNetworkId(void) {
const char* kProcRoute = "/proc/net/route"; /* IPv4 routes */
const char* kProcArp = "/proc/net/arp";
bool found = false;
@ -156,7 +148,28 @@ static bool ipv4NetworkId(SHA1Sum* sha1) {
if (gw == searchip) {
LOG(("networkid: MAC %s\n", hw));
nsAutoCString mac(hw);
sha1->update(mac.get(), mac.Length());
// This 'addition' could potentially be a
// fixed number from the profile or something.
nsAutoCString addition("local-rubbish");
nsAutoCString output;
SHA1Sum sha1;
nsCString combined(mac + addition);
sha1.update(combined.get(), combined.Length());
uint8_t digest[SHA1Sum::kHashSize];
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest),
SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
LOG(("networkid: id %s\n", output.get()));
if (mNetworkId != output) {
// new id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 1);
mNetworkId = output;
} else {
// same id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 2);
}
found = true;
break;
}
@ -167,132 +180,9 @@ static bool ipv4NetworkId(SHA1Sum* sha1) {
} /* if (farp) */
} /* if (gw) */
} /* if (froute) */
return found;
}
// Figure out the current IPv6 "network identification" string.
//
static bool ipv6NetworkId(SHA1Sum* sha1) {
bool found = false;
FILE* ifs = fopen("/proc/net/if_inet6", "r");
if (ifs) {
char buffer[512];
char ip6[40];
int devnum;
int preflen;
int scope;
int flags;
char name[40];
char* l = fgets(buffer, sizeof(buffer), ifs);
// 2a001a28120000090000000000000002 02 40 00 80 eth0
// +------------------------------+ ++ ++ ++ ++ ++
// | | | | | |
// 1 2 3 4 5 6
//
// 1. IPv6 address displayed in 32 hexadecimal chars without colons as
// separator
//
// 2. Netlink device number (interface index) in hexadecimal.
//
// 3. Prefix length in hexadecimal number of bits
//
// 4. Scope value (see kernel source include/net/ipv6.h and
// net/ipv6/addrconf.c for more)
//
// 5. Interface flags (see include/linux/rtnetlink.h and net/ipv6/addrconf.c
// for more)
//
// 6. Device name
//
while (l) {
memset(ip6, 0, sizeof(ip6));
if (6 == sscanf(buffer, "%32[0-9a-f] %02x %02x %02x %02x %31s", ip6,
&devnum, &preflen, &scope, &flags, name)) {
unsigned char id6[16];
memset(id6, 0, sizeof(id6));
for (int i = 0; i < 16; i++) {
char buf[3];
buf[0] = ip6[i * 2];
buf[1] = ip6[i * 2 + 1];
buf[2] = 0;
// convert from hex
id6[i] = (unsigned char)strtol(buf, nullptr, 16);
}
if (net::utils::ipv6_scope(id6) == IPV6_SCOPE_GLOBAL) {
unsigned char prefix[16];
memset(prefix, 0, sizeof(prefix));
uint8_t maskit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
int bits = preflen;
for (int i = 0; i < 16; i++) {
uint8_t mask = (bits >= 8) ? 0xff : maskit[bits];
prefix[i] = id6[i] & mask;
bits -= 8;
if (bits <= 0) {
break;
}
}
// We hash the IPv6 prefix and prefix length in order to
// differentiate between networks with a different prefix length
// For example: 2a00:/16 and 2a00:0/32
sha1->update(prefix, 16);
sha1->update(&preflen, sizeof(preflen));
found = true;
LOG(("networkid: found global IPv6 address %s/%d\n", ip6, preflen));
}
}
l = fgets(buffer, sizeof(buffer), ifs);
}
fclose(ifs);
}
return found;
}
// Figure out the "network identification".
//
void nsNotifyAddrListener::calculateNetworkId(void) {
MOZ_ASSERT(!NS_IsMainThread(), "Must not be called on the main thread");
SHA1Sum sha1;
bool found4 = ipv4NetworkId(&sha1);
bool found6 = ipv6NetworkId(&sha1);
if (found4 || found6) {
// This 'addition' could potentially be a fixed number from the
// profile or something.
nsAutoCString addition("local-rubbish");
nsAutoCString output;
sha1.update(addition.get(), addition.Length());
uint8_t digest[SHA1Sum::kHashSize];
sha1.finish(digest);
nsAutoCString newString(reinterpret_cast<char*>(digest),
SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
LOG(("networkid: id %s\n", output.get()));
MutexAutoLock lock(mMutex);
if (mNetworkId != output) {
// new id
if (found4 && !found6) {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 1); // IPv4 only
} else if (!found4 && found6) {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 3); // IPv6 only
} else {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 4); // Both!
}
mNetworkId = output;
} else {
// same id
LOG(("Same network id"));
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 2);
}
} else {
if (!found) {
// no id
LOG(("No network id"));
MutexAutoLock lock(mMutex);
mNetworkId.Truncate();
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 0);
Telemetry::Accumulate(Telemetry::NETWORK_ID, 0);
}
}
@ -504,6 +394,7 @@ nsNotifyAddrListener::Run() {
double period = (TimeStamp::Now() - mChangeTime).ToMilliseconds();
if (period >= kNetworkChangeCoalescingPeriod) {
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
calculateNetworkId();
mCoalescingActive = false;
pollWait = -1; // restore to default
} else {
@ -599,7 +490,6 @@ nsresult nsNotifyAddrListener::SendEvent(const char* aEventID) {
LOG(("SendEvent: %s\n", aEventID));
nsresult rv = NS_OK;
calculateNetworkId();
nsCOMPtr<nsIRunnable> event = new ChangeEvent(this, aEventID);
if (NS_FAILED(rv = NS_DispatchToMainThread(event)))
NS_WARNING("Failed to dispatch ChangeEvent");

Просмотреть файл

@ -21,7 +21,6 @@
#include "nsThreadUtils.h"
#include "nsCOMPtr.h"
#include "mozilla/Atomics.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsITimer.h"
#include "nsClassHashtable.h"
@ -65,8 +64,6 @@ class nsNotifyAddrListener : public nsINetworkLinkService,
// Figure out the current "network identification"
void calculateNetworkId(void);
mozilla::Mutex mMutex;
nsCString mNetworkId;
// Checks if there's a network "link"

Просмотреть файл

@ -7,7 +7,6 @@
#include "nsINetworkLinkService.h"
#include "nsIObserver.h"
#include "mozilla/Mutex.h"
#include <SystemConfiguration/SCNetworkReachability.h>
#include <SystemConfiguration/SystemConfiguration.h>
@ -45,8 +44,6 @@ class nsNetworkLinkService : public nsINetworkLinkService, public nsIObserver {
static void IPConfigChanged(SCDynamicStoreRef store, CFArrayRef changedKeys,
void* info);
void calculateNetworkId(void);
mozilla::Mutex mMutex;
nsCString mNetworkId;
};

Просмотреть файл

@ -10,11 +10,11 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include "nsCOMPtr.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
@ -26,7 +26,6 @@
#include "mozilla/Base64.h"
#include "mozilla/Telemetry.h"
#include "nsNetworkLinkService.h"
#include "../../base/IPv6Utils.h"
#import <Cocoa/Cocoa.h>
#import <netinet/in.h>
@ -74,8 +73,7 @@ nsNetworkLinkService::nsNetworkLinkService()
mReachability(nullptr),
mCFRunLoop(nullptr),
mRunLoopSource(nullptr),
mStoreRef(nullptr),
mMutex("nsNetworkLinkService::mMutex") {}
mStoreRef(nullptr) {}
nsNetworkLinkService::~nsNetworkLinkService() = default;
@ -100,13 +98,6 @@ nsNetworkLinkService::GetLinkType(uint32_t* aLinkType) {
return NS_OK;
}
NS_IMETHODIMP
nsNetworkLinkService::GetNetworkID(nsACString& aNetworkID) {
MutexAutoLock lock(mMutex);
aNetworkID = mNetworkId;
return NS_OK;
}
#ifndef SA_SIZE
# define SA_SIZE(sa) \
((!(sa) || ((struct sockaddr*)(sa))->sa_len == 0) \
@ -232,136 +223,47 @@ static int routingTable(char* gw, size_t aGwLen) {
}
//
// Figure out the current IPv4 "network identification" string.
// Figure out the current "network identification" string.
//
// It detects the IP of the default gateway in the routing table, then the MAC
// address of that IP in the ARP table before it hashes that string (to avoid
// information leakage).
//
static bool ipv4NetworkId(SHA1Sum* sha1) {
void nsNetworkLinkService::calculateNetworkId(void) {
bool found = false;
char hw[MAXHOSTNAMELEN];
if (!routingTable(hw, sizeof(hw))) {
char mac[256]; // big enough for a printable MAC address
if (scanArp(hw, mac, sizeof(mac))) {
LOG(("networkid: MAC %s\n", hw));
nsAutoCString mac(hw);
sha1->update(mac.get(), mac.Length());
return true;
}
}
return false;
}
static bool ipv6NetworkId(SHA1Sum* sha1) {
const int kMaxPrefixes = 8;
struct ifaddrs* ifap;
struct in6_addr prefixStore[kMaxPrefixes];
struct in6_addr netmaskStore[kMaxPrefixes];
int prefixCount = 0;
memset(prefixStore, 0, sizeof(prefixStore));
memset(netmaskStore, 0, sizeof(netmaskStore));
if (!getifaddrs(&ifap)) {
struct ifaddrs* ifa;
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
if ((AF_INET6 == ifa->ifa_addr->sa_family) &&
!(ifa->ifa_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))) {
// only IPv6 interfaces that aren't pointtopoint or loopback
struct sockaddr_in6* sin_netmask = (struct sockaddr_in6*)ifa->ifa_netmask;
if (sin_netmask) {
struct sockaddr_in6* sin_addr = (struct sockaddr_in6*)ifa->ifa_addr;
int scope = net::utils::ipv6_scope(sin_addr->sin6_addr.s6_addr);
if (scope == IPV6_SCOPE_GLOBAL) {
struct in6_addr prefix;
memset(&prefix, 0, sizeof(prefix));
// Get the prefix by combining the address and netmask.
for (size_t i = 0; i < sizeof(prefix); ++i) {
prefix.s6_addr[i] =
sin_addr->sin6_addr.s6_addr[i] & sin_netmask->sin6_addr.s6_addr[i];
}
int match = 0;
// check if prefix was already found
for (int i = 0; i < prefixCount; i++) {
if (!memcmp(&prefixStore[i], &prefix, sizeof(prefix)) &&
!memcmp(&netmaskStore[i], &sin_netmask->sin6_addr,
sizeof(sin_netmask->sin6_addr))) {
// a match
match = 1;
break;
}
}
if (match) {
// prefix already found
continue;
}
memcpy(&prefixStore[prefixCount], &prefix, sizeof(prefix));
memcpy(&netmaskStore[prefixCount], &sin_netmask->sin6_addr,
sizeof(sin_netmask->sin6_addr));
prefixCount++;
if (prefixCount == kMaxPrefixes) {
// reach maximum number of prefixes
break;
}
}
}
}
}
freeifaddrs(ifap);
}
if (!prefixCount) {
return false;
}
for (int i = 0; i < prefixCount; i++) {
sha1->update(&prefixStore[i], sizeof(prefixStore[i]));
sha1->update(&netmaskStore[i], sizeof(netmaskStore[i]));
}
return true;
}
void nsNetworkLinkService::calculateNetworkId(void) {
MOZ_ASSERT(!NS_IsMainThread(), "Should not be called on the main thread");
SHA1Sum sha1;
bool found4 = ipv4NetworkId(&sha1);
bool found6 = ipv6NetworkId(&sha1);
if (found4 || found6) {
// This 'addition' could potentially be a fixed number from the
// profile or something.
nsAutoCString addition("local-rubbish");
nsAutoCString output;
sha1.update(addition.get(), addition.Length());
uint8_t digest[SHA1Sum::kHashSize];
sha1.finish(digest);
nsAutoCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
LOG(("networkid: id %s\n", output.get()));
MutexAutoLock lock(mMutex);
if (mNetworkId != output) {
// new id
if (found4 && !found6) {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 1); // IPv4 only
} else if (!found4 && found6) {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 3); // IPv6 only
// This 'addition' could potentially be a
// fixed number from the profile or something.
nsAutoCString addition("local-rubbish");
nsAutoCString output;
SHA1Sum sha1;
nsCString combined(mac + addition);
sha1.update(combined.get(), combined.Length());
uint8_t digest[SHA1Sum::kHashSize];
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
LOG(("networkid: id %s\n", output.get()));
if (mNetworkId != output) {
// new id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 1);
mNetworkId = output;
} else {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 4); // Both!
// same id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 2);
}
mNetworkId = output;
} else {
// same id
LOG(("Same network id"));
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 2);
found = true;
}
} else {
}
if (!found) {
// no id
LOG(("No network id"));
MutexAutoLock lock(mMutex);
mNetworkId.Truncate();
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 0);
Telemetry::Accumulate(Telemetry::NETWORK_ID, 0);
}
}

Просмотреть файл

@ -21,7 +21,6 @@
#include <tcpmib.h>
#include <iphlpapi.h>
#include <netioapi.h>
#include <netlistmgr.h>
#include <iprtrmib.h>
#include "plstr.h"
#include "mozilla/Logging.h"
@ -30,15 +29,14 @@
#include "nsServiceManagerUtils.h"
#include "nsNotifyAddrListener.h"
#include "nsString.h"
#include "nsPrintfCString.h"
#include "nsAutoPtr.h"
#include "mozilla/Services.h"
#include "nsCRT.h"
#include "mozilla/Preferences.h"
#include "mozilla/SHA1.h"
#include "mozilla/Base64.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Telemetry.h"
#include <iptypes.h>
#include <iphlpapi.h>
@ -108,10 +106,10 @@ NS_IMPL_ISUPPORTS(nsNotifyAddrListener, nsINetworkLinkService, nsIRunnable,
nsIObserver)
nsNotifyAddrListener::nsNotifyAddrListener()
: mLinkUp(true), // assume true by default
: mLinkUp(true) // assume true by default
,
mStatusKnown(false),
mCheckAttempted(false),
mMutex("nsNotifyAddrListener::mMutex"),
mCheckEvent(nullptr),
mShutdown(false),
mIPInterfaceChecksum(0),
@ -152,97 +150,138 @@ nsNotifyAddrListener::GetLinkType(uint32_t* aLinkType) {
return NS_OK;
}
NS_IMETHODIMP
nsNotifyAddrListener::GetNetworkID(nsACString& aNetworkID) {
MutexAutoLock lock(mMutex);
aNetworkID = mNetworkId;
return NS_OK;
static bool macAddr(BYTE addr[], DWORD len, char* buf, size_t buflen) {
buf[0] = '\0';
if (!addr || !len || (len * 3 > buflen)) {
return false;
}
for (DWORD i = 0; i < len; ++i) {
sprintf_s(buf + (i * 3), sizeof(buf + (i * 3)), "%02x%s", addr[i],
(i == len - 1) ? "" : ":");
}
return true;
}
bool nsNotifyAddrListener::findMac(char* gateway) {
// query for buffer size needed
DWORD dwActualSize = 0;
bool found = FALSE;
// GetIpNetTable gets the IPv4 to physical address mapping table
DWORD status = GetIpNetTable(NULL, &dwActualSize, FALSE);
if (status == ERROR_INSUFFICIENT_BUFFER) {
// the expected route, now with a known buffer size
UniquePtr<char[]> buf(new char[dwActualSize]);
PMIB_IPNETTABLE pIpNetTable = reinterpret_cast<PMIB_IPNETTABLE>(&buf[0]);
status = GetIpNetTable(pIpNetTable, &dwActualSize, FALSE);
if (status == NO_ERROR) {
for (DWORD i = 0; i < pIpNetTable->dwNumEntries; ++i) {
char hw[256];
if (!macAddr(pIpNetTable->table[i].bPhysAddr,
pIpNetTable->table[i].dwPhysAddrLen, hw, sizeof(hw))) {
// failed to get the MAC
continue;
}
struct in_addr addr;
addr.s_addr = pIpNetTable->table[i].dwAddr;
if (!strcmp(gateway, inet_ntoa(addr))) {
LOG(("networkid: MAC %s\n", hw));
nsAutoCString mac(hw);
// This 'addition' could potentially be a
// fixed number from the profile or something.
nsAutoCString addition("local-rubbish");
nsAutoCString output;
SHA1Sum sha1;
nsCString combined(mac + addition);
sha1.update(combined.get(), combined.Length());
uint8_t digest[SHA1Sum::kHashSize];
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest),
SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
if (NS_FAILED(rv)) {
found = false;
break;
}
LOG(("networkid: id %s\n", output.get()));
if (mNetworkId != output) {
// new id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 1);
mNetworkId = output;
} else {
// same id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 2);
}
found = true;
break;
}
}
}
}
return found;
}
// returns 'true' when the gw is found and stored
static bool defaultgw(char* aGateway, size_t aGatewayLen) {
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
DWORD dwSize = 0;
if (GetIpForwardTable(NULL, &dwSize, 0) != ERROR_INSUFFICIENT_BUFFER) {
return false;
}
UniquePtr<char[]> buf(new char[dwSize]);
pIpForwardTable = reinterpret_cast<PMIB_IPFORWARDTABLE>(&buf[0]);
// Note that the IPv4 addresses returned in GetIpForwardTable entries are
// in network byte order
DWORD retVal = GetIpForwardTable(pIpForwardTable, &dwSize, 0);
if (retVal == NO_ERROR) {
for (unsigned int i = 0; i < pIpForwardTable->dwNumEntries; ++i) {
// Convert IPv4 addresses to strings
struct in_addr IpAddr;
IpAddr.S_un.S_addr =
static_cast<u_long>(pIpForwardTable->table[i].dwForwardDest);
char* ipStr = inet_ntoa(IpAddr);
if (ipStr && !strcmp("0.0.0.0", ipStr)) {
// Default gateway!
IpAddr.S_un.S_addr =
static_cast<u_long>(pIpForwardTable->table[i].dwForwardNextHop);
ipStr = inet_ntoa(IpAddr);
if (ipStr) {
strcpy_s(aGateway, aGatewayLen, ipStr);
return true;
}
}
} // for loop
}
return false;
}
//
// Figure out the current "network identification" string.
//
// It detects the IP of the default gateway in the routing table, then the MAC
// address of that IP in the ARP table before it hashes that string (to avoid
// information leakage).
//
void nsNotifyAddrListener::calculateNetworkId(void) {
MOZ_ASSERT(!NS_IsMainThread(), "Must not be called on the main thread");
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
return;
bool found = FALSE;
char gateway[128];
if (defaultgw(gateway, sizeof(gateway))) {
found = findMac(gateway);
}
auto unitialize = MakeScopeExit([]() { CoUninitialize(); });
RefPtr<INetworkListManager> nlm;
HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL,
IID_INetworkListManager, getter_AddRefs(nlm));
if (NS_WARN_IF(FAILED(hr))) {
LOG(("CoCreateInstance error: %X", hr));
return;
}
RefPtr<IEnumNetworks> enumNetworks;
hr = nlm->GetNetworks(NLM_ENUM_NETWORK_CONNECTED,
getter_AddRefs(enumNetworks));
if (NS_WARN_IF(FAILED(hr))) {
LOG(("GetNetworks error: %X", hr));
return;
}
SHA1Sum sha1;
uint32_t networkCount = 0;
while (true) {
RefPtr<INetwork> network;
DWORD dwReturn;
hr = enumNetworks->Next(1, getter_AddRefs(network), &dwReturn);
if (hr == S_OK && dwReturn > 0) {
GUID nwGUID;
hr = network->GetNetworkId(&nwGUID);
if (hr != S_OK) {
continue;
}
networkCount++;
sha1.update(&nwGUID, sizeof(nwGUID));
nsPrintfCString guid("%08lX%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%lX",
nwGUID.Data1, nwGUID.Data2, nwGUID.Data3,
nwGUID.Data4[0], nwGUID.Data4[1], nwGUID.Data4[2],
nwGUID.Data4[3], nwGUID.Data4[4], nwGUID.Data4[5],
nwGUID.Data4[6], nwGUID.Data4[7]);
LOG(("calculateNetworkId: interface networkID: %s\n", guid.get()));
} else {
break;
}
}
if (networkCount == 0) {
MutexAutoLock lock(mMutex);
mNetworkId.Truncate();
LOG(("calculateNetworkId: no network ID - no active networks"));
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 0);
return;
}
nsAutoCString output;
SHA1Sum::Hash digest;
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
nsresult rv = Base64Encode(newString, output);
if (NS_FAILED(rv)) {
{
MutexAutoLock lock(mMutex);
mNetworkId.Truncate();
}
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 0);
LOG(("calculateNetworkId: no network ID Base64Encode error %X", rv));
return;
}
MutexAutoLock lock(mMutex);
if (output != mNetworkId) {
mNetworkId = output;
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 1);
LOG(("calculateNetworkId: new NetworkID: %s", output.get()));
} else {
Telemetry::Accumulate(Telemetry::NETWORK_ID2, 2);
LOG(("calculateNetworkId: same NetworkID: %s", output.get()));
if (!found) {
// no id
Telemetry::Accumulate(Telemetry::NETWORK_ID, 0);
}
}
@ -260,6 +299,7 @@ nsNotifyAddrListener::nextCoalesceWaitTime() {
// check if coalescing period should continue
double period = (TimeStamp::Now() - mChangeTime).ToMilliseconds();
if (period >= kNetworkChangeCoalescingPeriod) {
calculateNetworkId();
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
mCoalescingActive = false;
return INFINITE; // return default
@ -416,10 +456,6 @@ nsresult nsNotifyAddrListener::SendEvent(const char* aEventID) {
LOG(("SendEvent: network is '%s'\n", aEventID));
if (!NS_IsMainThread()) {
calculateNetworkId();
}
nsresult rv;
nsCOMPtr<nsIRunnable> event = new ChangeEvent(this, aEventID);
if (NS_FAILED(rv = NS_DispatchToMainThread(event)))

Просмотреть файл

@ -15,7 +15,6 @@
#include "nsThreadUtils.h"
#include "nsCOMPtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Mutex.h"
class nsNotifyAddrListener : public nsINetworkLinkService,
public nsIRunnable,
@ -72,8 +71,6 @@ class nsNotifyAddrListener : public nsINetworkLinkService,
// Figure out the current network identification
void calculateNetworkId(void);
bool findMac(char* gateway);
mozilla::Mutex mMutex;
nsCString mNetworkId;
HANDLE mCheckEvent;

Просмотреть файл

@ -4832,14 +4832,14 @@
"n_buckets": 10,
"description": "Time spent (ms) during showdown deleting disk cache v2 for 'clear private data' option"
},
"NETWORK_ID2": {
"record_in_processes": ["main"],
"NETWORK_ID": {
"record_in_processes": ["main", "content"],
"alert_emails": ["necko@mozilla.com"],
"bug_numbers": [1240932, 1395914],
"bug_numbers": [1240932],
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 6,
"description": "Network identification (0=None, 1=New Ipv4, 2=Same, 3=New IPv6, 4=New dual)"
"description": "Network identification (0=None, 1=New, 2=Same)"
},
"IDLE_NOTIFY_IDLE_MS": {
"record_in_processes": ["main", "content"],