Bug 1667579 - Pref to manually enter NAT64 prefix. r=valentin,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D94597
This commit is contained in:
mcccs 2020-11-02 08:05:10 +00:00
Родитель 06aecc5c9f
Коммит 039fe95a03
3 изменённых файлов: 90 добавлений и 7 удалений

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

@ -8695,6 +8695,15 @@
value: true
mirror: always
# Manually enter the NAT64 prefix that will be used if IPv4 is unavailable.
# The value is formatted as IPv6 with the least significant bits to be dropped.
# For example, 64:ff9b:: is a common prefix. This will not disable
# the NAT64 check, although the value of this pref will be prioritized.
- name: network.connectivity-service.nat64-prefix
type: String
value: ""
mirror: never
# Whether to enable echconfig.
- name: network.dns.echconfig.enabled
type: RelaxedAtomicBool

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

@ -125,6 +125,30 @@ already_AddRefed<AddrInfo> NetworkConnectivityService::MapNAT64IPs(
return builder.Finish();
}
// Returns true if a prefix was read and saved to the argument
static inline bool NAT64PrefixFromPref(NetAddr* prefix) {
nsAutoCString nat64PrefixPref;
PRNetAddr prAddr{};
nsresult rv = Preferences::GetCString(
"network.connectivity-service.nat64-prefix", nat64PrefixPref);
if (NS_FAILED(rv) || nat64PrefixPref.IsEmpty() ||
PR_StringToNetAddr(nat64PrefixPref.get(), &prAddr) != PR_SUCCESS ||
prAddr.raw.family != PR_AF_INET6) {
return false;
}
PRNetAddrToNetAddr(&prAddr, prefix);
return true;
}
static inline bool NAT64PrefixCompare(const NetAddr& prefix1,
const NetAddr& prefix2) {
// Compare the first 96 bits as 64 + 32
return prefix1.inet6.ip.u64[0] == prefix2.inet6.ip.u64[0] &&
prefix1.inet6.ip.u32[2] == prefix2.inet6.ip.u32[2];
}
void NetworkConnectivityService::PerformChecks() {
mDNSv4 = UNKNOWN;
mDNSv6 = UNKNOWN;
@ -137,6 +161,17 @@ void NetworkConnectivityService::PerformChecks() {
{
MutexAutoLock lock(mLock);
mNAT64Prefixes.Clear();
// NAT64 checks might be disabled.
// Since We can't guarantee a DNS response, we should set up
// NAT64 manually now if needed.
NetAddr priorityPrefix{};
bool havePrefix = NAT64PrefixFromPref(&priorityPrefix);
if (havePrefix) {
mNAT64Prefixes.AppendElement(priorityPrefix);
mNAT64 = OK;
}
}
RecheckDNS();
@ -153,8 +188,17 @@ void NetworkConnectivityService::SaveNAT64Prefixes(nsIDNSRecord* aRecord) {
MutexAutoLock lock(mLock);
mNAT64Prefixes.Clear();
NetAddr priorityPrefix{};
bool havePrefix = NAT64PrefixFromPref(&priorityPrefix);
if (havePrefix) {
mNAT64 = OK;
mNAT64Prefixes.AppendElement(priorityPrefix);
}
if (!rec) {
mNAT64 = NOT_AVAILABLE;
if (!havePrefix) {
mNAT64 = NOT_AVAILABLE;
}
return;
}
@ -199,7 +243,7 @@ void NetworkConnectivityService::SaveNAT64Prefixes(nsIDNSRecord* aRecord) {
NetAddr prev = mNAT64Prefixes[0];
for (size_t i = 1; i < length; i++) {
if (mNAT64Prefixes[i] == prev) {
if (NAT64PrefixCompare(prev, mNAT64Prefixes[i])) {
mNAT64Prefixes.RemoveElementAt(i);
i--;
length--;
@ -208,6 +252,18 @@ void NetworkConnectivityService::SaveNAT64Prefixes(nsIDNSRecord* aRecord) {
}
}
// The prioritized address might also appear in the record we received.
if (havePrefix) {
for (size_t i = 1; i < length; i++) {
if (NAT64PrefixCompare(priorityPrefix, mNAT64Prefixes[i])) {
mNAT64Prefixes.RemoveElementAt(i);
// It wouldn't appear more than once.
break;
}
}
}
mNAT64 = OK;
}
@ -261,6 +317,7 @@ NetworkConnectivityService::RecheckDNS() {
nsIDNSService::RESOLVE_DISABLE_IPV4 | nsIDNSService::RESOLVE_DISABLE_TRR,
nullptr, this, NS_GetCurrentThread(), attrs,
getter_AddRefs(mDNSv6Request));
NS_ENSURE_SUCCESS(rv, rv);
if (StaticPrefs::network_connectivity_service_nat64_check()) {
rv = dns->AsyncResolveNative("ipv4only.arpa"_ns,
@ -269,6 +326,7 @@ NetworkConnectivityService::RecheckDNS() {
nsIDNSService::RESOLVE_DISABLE_TRR,
nullptr, this, NS_GetCurrentThread(), attrs,
getter_AddRefs(mNAT64Request));
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
}

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

@ -63,12 +63,17 @@ add_task(async function test_add_nat64_prefix_to_trr() {
let [req, resp] = await channelOpenPromise(chan);
equal(resp, "<h1> 404 Path not found: /test?bla=some</h1>");
dns.clearCache(true);
override.addIPOverride("ipv4only.arpa", "fe80::6a99:9b2b:c000:00aa");
override.addIPOverride("ipv4only.arpa", "fe80::9b2b:c000:00aa");
Services.prefs.setCharPref(
"network.connectivity-service.nat64-prefix",
"ae80::3b1b:c343:1133"
);
Services.obs.notifyObservers(null, "network:captive-portal-connectivity");
await promiseObserverNotification(
let notification = promiseObserverNotification(
"network:connectivity-service:dns-checks-complete"
);
Services.obs.notifyObservers(null, "network:captive-portal-connectivity");
await notification;
Services.prefs.setIntPref("network.trr.mode", 2);
Services.prefs.setCharPref(
@ -90,10 +95,21 @@ add_task(async function test_add_nat64_prefix_to_trr() {
});
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
inRecord.getNextAddrAsString();
Assert.equal(
inRecord.getNextAddrAsString(),
"fe80::6a99:9b2b:102:304",
"1.2.3.4",
`Checking that native IPv4 addresses have higher priority.`
);
Assert.equal(
inRecord.getNextAddrAsString(),
"ae80::3b1b:102:304",
`Checking the manually entered NAT64-prefixed address is in the middle.`
);
Assert.equal(
inRecord.getNextAddrAsString(),
"fe80::9b2b:102:304",
`Checking that the NAT64-prefixed address is appended at the back.`
);