зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1395914 - Figure out network id for IPv6 too (Linux) r=michal
Differential Revision: https://phabricator.services.mozilla.com/D34903 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6d7a4fd701
Коммит
1fc5fb9a40
|
@ -0,0 +1,50 @@
|
|||
/* 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_
|
|
@ -25,6 +25,7 @@
|
|||
#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)
|
||||
|
@ -88,13 +89,13 @@ nsNotifyAddrListener::GetLinkType(uint32_t* aLinkType) {
|
|||
}
|
||||
|
||||
//
|
||||
// Figure out the current "network identification" string.
|
||||
// Figure out the current IPv4 "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) {
|
||||
static bool ipv4NetworkId(SHA1Sum* sha1) {
|
||||
const char* kProcRoute = "/proc/net/route"; /* IPv4 routes */
|
||||
const char* kProcArp = "/proc/net/arp";
|
||||
bool found = false;
|
||||
|
@ -148,28 +149,7 @@ void nsNotifyAddrListener::calculateNetworkId(void) {
|
|||
if (gw == searchip) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
sha1->update(mac.get(), mac.Length());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -180,7 +160,124 @@ void nsNotifyAddrListener::calculateNetworkId(void) {
|
|||
} /* if (farp) */
|
||||
} /* if (gw) */
|
||||
} /* if (froute) */
|
||||
if (!found) {
|
||||
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) {
|
||||
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()));
|
||||
if (mNetworkId != output) {
|
||||
// new id
|
||||
if (found4 && !found6) {
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_ID, 1); // IPv4 only
|
||||
} else if (!found4 && found6) {
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_ID, 3); // IPv6 only
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_ID, 4); // Both!
|
||||
}
|
||||
mNetworkId = output;
|
||||
} else {
|
||||
// same id
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_ID, 2);
|
||||
}
|
||||
} else {
|
||||
// no id
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_ID, 0);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче