diff --git a/netwerk/base/IPv6Utils.h b/netwerk/base/IPv6Utils.h deleted file mode 100644 index e472198b09bb..000000000000 --- a/netwerk/base/IPv6Utils.h +++ /dev/null @@ -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_ \ No newline at end of file diff --git a/netwerk/base/nsINetworkLinkService.idl b/netwerk/base/nsINetworkLinkService.idl index f89e3139d4f9..d7d7e766503e 100644 --- a/netwerk/base/nsINetworkLinkService.idl +++ b/netwerk/base/nsINetworkLinkService.idl @@ -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++ diff --git a/netwerk/system/android/nsAndroidNetworkLinkService.cpp b/netwerk/system/android/nsAndroidNetworkLinkService.cpp index 9fe2d42ea8e4..677b13f68e10 100644 --- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp +++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp @@ -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; -} diff --git a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp index 2e81115cdee7..a9ec6a1b0fb3 100644 --- a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp @@ -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(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(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 event = new ChangeEvent(this, aEventID); if (NS_FAILED(rv = NS_DispatchToMainThread(event))) NS_WARNING("Failed to dispatch ChangeEvent"); diff --git a/netwerk/system/linux/nsNotifyAddrListener_Linux.h b/netwerk/system/linux/nsNotifyAddrListener_Linux.h index 5888ecd8a8f7..f4a508cefd97 100644 --- a/netwerk/system/linux/nsNotifyAddrListener_Linux.h +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.h @@ -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" diff --git a/netwerk/system/mac/nsNetworkLinkService.h b/netwerk/system/mac/nsNetworkLinkService.h index 76a128b6757e..57c0df963ffb 100644 --- a/netwerk/system/mac/nsNetworkLinkService.h +++ b/netwerk/system/mac/nsNetworkLinkService.h @@ -7,7 +7,6 @@ #include "nsINetworkLinkService.h" #include "nsIObserver.h" -#include "mozilla/Mutex.h" #include #include @@ -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; }; diff --git a/netwerk/system/mac/nsNetworkLinkService.mm b/netwerk/system/mac/nsNetworkLinkService.mm index 428f9b775b4e..89d295ba527e 100644 --- a/netwerk/system/mac/nsNetworkLinkService.mm +++ b/netwerk/system/mac/nsNetworkLinkService.mm @@ -10,11 +10,11 @@ #include #include #include + #include #include -#include -#include +#include #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 #import @@ -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(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(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); } } diff --git a/netwerk/system/win32/nsNotifyAddrListener.cpp b/netwerk/system/win32/nsNotifyAddrListener.cpp index 838b8da54958..8f8ee6abab30 100644 --- a/netwerk/system/win32/nsNotifyAddrListener.cpp +++ b/netwerk/system/win32/nsNotifyAddrListener.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #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 #include @@ -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 buf(new char[dwActualSize]); + PMIB_IPNETTABLE pIpNetTable = reinterpret_cast(&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(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 buf(new char[dwSize]); + pIpForwardTable = reinterpret_cast(&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(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(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 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 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 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(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 event = new ChangeEvent(this, aEventID); if (NS_FAILED(rv = NS_DispatchToMainThread(event))) diff --git a/netwerk/system/win32/nsNotifyAddrListener.h b/netwerk/system/win32/nsNotifyAddrListener.h index 62f3445d2801..4a26b6ca23c0 100644 --- a/netwerk/system/win32/nsNotifyAddrListener.h +++ b/netwerk/system/win32/nsNotifyAddrListener.h @@ -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; diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 3510a900aca8..34c182adf75d 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -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"],