Bug 1713796 - P1: Move nsHostRecord to another file, r=necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D117322
This commit is contained in:
26
netwerk/dns/DNSLogging.h
Normal file
26
netwerk/dns/DNSLogging.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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 mozilla_DNSLogging_h
|
||||||
|
#define mozilla_DNSLogging_h
|
||||||
|
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
|
||||||
|
#undef LOG
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace net {
|
||||||
|
extern LazyLogModule gHostResolverLog;
|
||||||
|
} // namespace net
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#define LOG(msg) \
|
||||||
|
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug, msg)
|
||||||
|
#define LOG1(msg) \
|
||||||
|
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Error, msg)
|
||||||
|
#define LOG_ENABLED() \
|
||||||
|
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
|
||||||
|
|
||||||
|
#endif // mozilla_DNSLogging_h
|
||||||
@@ -8,17 +8,12 @@
|
|||||||
#include "mozilla/EndianUtils.h"
|
#include "mozilla/EndianUtils.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
#include "ODoHService.h"
|
#include "ODoHService.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#undef LOG
|
|
||||||
#undef LOG_ENABLED
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
#define LOG_ENABLED() \
|
|
||||||
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
|
|
||||||
|
|
||||||
static uint16_t get16bit(const unsigned char* aData, unsigned int index) {
|
static uint16_t get16bit(const unsigned char* aData, unsigned int index) {
|
||||||
return ((aData[index] << 8) | aData[index + 1]);
|
return ((aData[index] << 8) | aData[index + 1]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,12 @@
|
|||||||
#include "nsIURIMutator.h"
|
#include "nsIURIMutator.h"
|
||||||
#include "ODoHService.h"
|
#include "ODoHService.h"
|
||||||
#include "TRRService.h"
|
#include "TRRService.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
#undef LOG_ENABLED
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
#define LOG_ENABLED() \
|
|
||||||
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ODoH::Run() {
|
ODoH::Run() {
|
||||||
if (!gODoHService) {
|
if (!gODoHService) {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "ODoH.h"
|
#include "ODoH.h"
|
||||||
#include "TRRService.h"
|
#include "TRRService.h"
|
||||||
#include "nsURLHelper.h"
|
#include "nsURLHelper.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
static const char kODoHProxyURIPref[] = "network.trr.odoh.proxy_uri";
|
static const char kODoHProxyURIPref[] = "network.trr.odoh.proxy_uri";
|
||||||
static const char kODoHTargetHostPref[] = "network.trr.odoh.target_host";
|
static const char kODoHTargetHostPref[] = "network.trr.odoh.target_host";
|
||||||
@@ -29,9 +31,6 @@ namespace net {
|
|||||||
|
|
||||||
ODoHService* gODoHService = nullptr;
|
ODoHService* gODoHService = nullptr;
|
||||||
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(ODoHService, nsIDNSListener, nsIObserver,
|
NS_IMPL_ISUPPORTS(ODoHService, nsIDNSListener, nsIObserver,
|
||||||
nsISupportsWeakReference, nsITimerCallback,
|
nsISupportsWeakReference, nsITimerCallback,
|
||||||
nsIStreamLoaderObserver)
|
nsIStreamLoaderObserver)
|
||||||
|
|||||||
@@ -37,17 +37,12 @@
|
|||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/Tokenizer.h"
|
#include "mozilla/Tokenizer.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
#undef LOG_ENABLED
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
#define LOG_ENABLED() \
|
|
||||||
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor,
|
NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor,
|
||||||
nsIStreamListener, nsIRunnable, nsITimerCallback)
|
nsIStreamListener, nsIRunnable, nsITimerCallback)
|
||||||
|
|
||||||
@@ -1026,8 +1021,5 @@ void TRR::Cancel(nsresult aStatus) {
|
|||||||
|
|
||||||
bool TRR::UseDefaultServer() { return !mRec || mRec->mTrrServer.IsEmpty(); }
|
bool TRR::UseDefaultServer() { return !mRec || mRec->mTrrServer.IsEmpty(); }
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
|
|
||||||
// namespace
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -5,14 +5,12 @@
|
|||||||
#include "TRRQuery.h"
|
#include "TRRQuery.h"
|
||||||
#include "TRR.h"
|
#include "TRR.h"
|
||||||
#include "ODoH.h"
|
#include "ODoH.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
|
|
||||||
static already_AddRefed<AddrInfo> merge_rrset(AddrInfo* rrto,
|
static already_AddRefed<AddrInfo> merge_rrset(AddrInfo* rrto,
|
||||||
AddrInfo* rrfrom) {
|
AddrInfo* rrfrom) {
|
||||||
MOZ_ASSERT(rrto && rrfrom);
|
MOZ_ASSERT(rrto && rrfrom);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include "mozilla/TelemetryComms.h"
|
#include "mozilla/TelemetryComms.h"
|
||||||
#include "mozilla/Tokenizer.h"
|
#include "mozilla/Tokenizer.h"
|
||||||
#include "mozilla/net/rust_helper.h"
|
#include "mozilla/net/rust_helper.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
#if defined(XP_WIN) && !defined(__MINGW32__)
|
#if defined(XP_WIN) && !defined(__MINGW32__)
|
||||||
# include <shlobj_core.h> // for SHGetSpecialFolderPathA
|
# include <shlobj_core.h> // for SHGetSpecialFolderPathA
|
||||||
@@ -40,10 +42,6 @@ static const char kDisableIpv6Pref[] = "network.dns.disableIPv6";
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
|
|
||||||
TRRService* gTRRService = nullptr;
|
TRRService* gTRRService = nullptr;
|
||||||
StaticRefPtr<nsIThread> sTRRBackgroundThread;
|
StaticRefPtr<nsIThread> sTRRBackgroundThread;
|
||||||
static Atomic<TRRService*> sTRRServicePtr;
|
static Atomic<TRRService*> sTRRServicePtr;
|
||||||
@@ -1302,7 +1300,5 @@ AHostResolver::LookupStatus TRRService::CompleteLookupByType(
|
|||||||
return LOOKUP_OK;
|
return LOOKUP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -6,20 +6,17 @@
|
|||||||
|
|
||||||
#include "TRRServiceBase.h"
|
#include "TRRServiceBase.h"
|
||||||
|
|
||||||
#include "mozilla/Logging.h"
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "nsHostResolver.h"
|
#include "nsHostResolver.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsIOService.h"
|
#include "nsIOService.h"
|
||||||
#include "nsIDNSService.h"
|
#include "nsIDNSService.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
#undef LOG
|
|
||||||
extern mozilla::LazyLogModule gHostResolverLog;
|
|
||||||
#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
|
|
||||||
TRRServiceBase::TRRServiceBase()
|
TRRServiceBase::TRRServiceBase()
|
||||||
: mMode(nsIDNSService::MODE_NATIVEONLY), mURISetByDetection(false) {}
|
: mMode(nsIDNSService::MODE_NATIVEONLY), mURISetByDetection(false) {}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ EXPORTS.mozilla.net += [
|
|||||||
SOURCES += [
|
SOURCES += [
|
||||||
"GetAddrInfo.cpp", # Undefines UNICODE
|
"GetAddrInfo.cpp", # Undefines UNICODE
|
||||||
"nsEffectiveTLDService.cpp", # Excluded from UNIFIED_SOURCES due to special build flags.
|
"nsEffectiveTLDService.cpp", # Excluded from UNIFIED_SOURCES due to special build flags.
|
||||||
"nsHostResolver.cpp", # Redefines LOG
|
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
@@ -71,6 +70,8 @@ UNIFIED_SOURCES += [
|
|||||||
"NativeDNSResolverOverrideChild.cpp",
|
"NativeDNSResolverOverrideChild.cpp",
|
||||||
"NativeDNSResolverOverrideParent.cpp",
|
"NativeDNSResolverOverrideParent.cpp",
|
||||||
"nsDNSService2.cpp",
|
"nsDNSService2.cpp",
|
||||||
|
"nsHostRecord.cpp",
|
||||||
|
"nsHostResolver.cpp",
|
||||||
"nsIDNService.cpp",
|
"nsIDNService.cpp",
|
||||||
"ODoH.cpp",
|
"ODoH.cpp",
|
||||||
"ODoHService.cpp",
|
"ODoHService.cpp",
|
||||||
|
|||||||
532
netwerk/dns/nsHostRecord.cpp
Normal file
532
netwerk/dns/nsHostRecord.cpp
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
/* vim:set ts=4 sw=2 sts=2 et cin: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsHostRecord.h"
|
||||||
|
#include "TRRQuery.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// this macro filters out any flags that are not used when constructing the
|
||||||
|
// host key. the significant flags are those that would affect the resulting
|
||||||
|
// host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
|
||||||
|
#define RES_KEY_FLAGS(_f) \
|
||||||
|
((_f) & \
|
||||||
|
(nsHostResolver::RES_CANON_NAME | nsHostResolver::RES_DISABLE_TRR | \
|
||||||
|
nsIDNSService::RESOLVE_TRR_MODE_MASK | nsHostResolver::RES_IP_HINT))
|
||||||
|
|
||||||
|
#define IS_ADDR_TYPE(_type) ((_type) == nsIDNSService::RESOLVE_TYPE_DEFAULT)
|
||||||
|
#define IS_OTHER_TYPE(_type) ((_type) != nsIDNSService::RESOLVE_TYPE_DEFAULT)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
nsHostKey::nsHostKey(const nsACString& aHost, const nsACString& aTrrServer,
|
||||||
|
uint16_t aType, uint16_t aFlags, uint16_t aAf, bool aPb,
|
||||||
|
const nsACString& aOriginsuffix)
|
||||||
|
: host(aHost),
|
||||||
|
mTrrServer(aTrrServer),
|
||||||
|
type(aType),
|
||||||
|
flags(aFlags),
|
||||||
|
af(aAf),
|
||||||
|
pb(aPb),
|
||||||
|
originSuffix(aOriginsuffix) {}
|
||||||
|
|
||||||
|
bool nsHostKey::operator==(const nsHostKey& other) const {
|
||||||
|
return host == other.host && mTrrServer == other.mTrrServer &&
|
||||||
|
type == other.type &&
|
||||||
|
RES_KEY_FLAGS(flags) == RES_KEY_FLAGS(other.flags) && af == other.af &&
|
||||||
|
originSuffix == other.originSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
PLDHashNumber nsHostKey::Hash() const {
|
||||||
|
return AddToHash(HashString(host.get()), HashString(mTrrServer.get()), type,
|
||||||
|
RES_KEY_FLAGS(flags), af, HashString(originSuffix.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nsHostKey::SizeOfExcludingThis(
|
||||||
|
mozilla::MallocSizeOf mallocSizeOf) const {
|
||||||
|
size_t n = 0;
|
||||||
|
n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||||
|
n += mTrrServer.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||||
|
n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// nsHostRecord
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS0(nsHostRecord)
|
||||||
|
|
||||||
|
nsHostRecord::nsHostRecord(const nsHostKey& key)
|
||||||
|
: nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
|
||||||
|
|
||||||
|
void nsHostRecord::Invalidate() { mDoomed = true; }
|
||||||
|
|
||||||
|
void nsHostRecord::Cancel() {
|
||||||
|
RefPtr<TRRQuery> query;
|
||||||
|
{
|
||||||
|
auto lock = mTRRQuery.Lock();
|
||||||
|
query.swap(lock.ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
query->Cancel(NS_ERROR_ABORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsHostRecord::ExpirationStatus nsHostRecord::CheckExpiration(
|
||||||
|
const mozilla::TimeStamp& now) const {
|
||||||
|
if (!mGraceStart.IsNull() && now >= mGraceStart && !mValidEnd.IsNull() &&
|
||||||
|
now < mValidEnd) {
|
||||||
|
return nsHostRecord::EXP_GRACE;
|
||||||
|
}
|
||||||
|
if (!mValidEnd.IsNull() && now < mValidEnd) {
|
||||||
|
return nsHostRecord::EXP_VALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsHostRecord::EXP_EXPIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHostRecord::SetExpiration(const mozilla::TimeStamp& now,
|
||||||
|
unsigned int valid, unsigned int grace) {
|
||||||
|
mValidStart = now;
|
||||||
|
if ((valid + grace) < 60) {
|
||||||
|
grace = 60 - valid;
|
||||||
|
LOG(("SetExpiration: artificially bumped grace to %d\n", grace));
|
||||||
|
}
|
||||||
|
mGraceStart = now + TimeDuration::FromSeconds(valid);
|
||||||
|
mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
|
||||||
|
mTtl = valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHostRecord::CopyExpirationTimesAndFlagsFrom(
|
||||||
|
const nsHostRecord* aFromHostRecord) {
|
||||||
|
// This is used to copy information from a cache entry to a record. All
|
||||||
|
// information necessary for HasUsableRecord needs to be copied.
|
||||||
|
mValidStart = aFromHostRecord->mValidStart;
|
||||||
|
mValidEnd = aFromHostRecord->mValidEnd;
|
||||||
|
mGraceStart = aFromHostRecord->mGraceStart;
|
||||||
|
mDoomed = aFromHostRecord->mDoomed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const {
|
||||||
|
if (mDoomed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HasUsableResultInternal(now, queryFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// AddrHostRecord
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static size_t SizeOfResolveHostCallbackListExcludingHead(
|
||||||
|
const mozilla::LinkedList<RefPtr<nsResolveHostCallback>>& aCallbacks,
|
||||||
|
MallocSizeOf mallocSizeOf) {
|
||||||
|
size_t n = aCallbacks.sizeOfExcludingThis(mallocSizeOf);
|
||||||
|
|
||||||
|
for (const nsResolveHostCallback* t = aCallbacks.getFirst(); t;
|
||||||
|
t = t->getNext()) {
|
||||||
|
n += t->SizeOfIncludingThis(mallocSizeOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
|
||||||
|
|
||||||
|
AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
|
||||||
|
|
||||||
|
AddrHostRecord::~AddrHostRecord() {
|
||||||
|
mCallbacks.clear();
|
||||||
|
Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mUnusableCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddrHostRecord::Blocklisted(const NetAddr* aQuery) {
|
||||||
|
addr_info_lock.AssertCurrentThreadOwns();
|
||||||
|
LOG(("Checking unusable list for host [%s], host record [%p].\n", host.get(),
|
||||||
|
this));
|
||||||
|
|
||||||
|
// skip the string conversion for the common case of no blocklist
|
||||||
|
if (!mUnusableItems.Length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[kIPv6CStrBufSize];
|
||||||
|
if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsDependentCString strQuery(buf);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mUnusableItems.Length(); i++) {
|
||||||
|
if (mUnusableItems.ElementAt(i).Equals(strQuery)) {
|
||||||
|
LOG(("Address [%s] is blocklisted for host [%s].\n", buf, host.get()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
|
||||||
|
addr_info_lock.AssertCurrentThreadOwns();
|
||||||
|
LOG(
|
||||||
|
("Adding address to blocklist for host [%s], host record [%p]."
|
||||||
|
"used trr=%d\n",
|
||||||
|
host.get(), this, mTRRSuccess));
|
||||||
|
|
||||||
|
++mUnusableCount;
|
||||||
|
|
||||||
|
char buf[kIPv6CStrBufSize];
|
||||||
|
if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
|
||||||
|
LOG(
|
||||||
|
("Successfully adding address [%s] to blocklist for host "
|
||||||
|
"[%s].\n",
|
||||||
|
buf, host.get()));
|
||||||
|
mUnusableItems.AppendElement(nsCString(buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddrHostRecord::ResetBlocklist() {
|
||||||
|
addr_info_lock.AssertCurrentThreadOwns();
|
||||||
|
LOG(("Resetting blocklist for host [%s], host record [%p].\n", host.get(),
|
||||||
|
this));
|
||||||
|
mUnusableItems.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AddrHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||||
|
size_t n = mallocSizeOf(this);
|
||||||
|
|
||||||
|
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
|
||||||
|
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
|
||||||
|
|
||||||
|
n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
|
||||||
|
n += mallocSizeOf(addr.get());
|
||||||
|
|
||||||
|
n += mUnusableItems.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||||
|
for (size_t i = 0; i < mUnusableItems.Length(); i++) {
|
||||||
|
n += mUnusableItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddrHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const {
|
||||||
|
// don't use cached negative results for high priority queries.
|
||||||
|
if (negative && IsHighPriority(queryFlags)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckExpiration(now) == EXP_EXPIRED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr_info || addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the entry can be removed, or false if it should be left.
|
||||||
|
// Sets ResolveAgain true for entries being resolved right now.
|
||||||
|
bool AddrHostRecord::RemoveOrRefresh(bool aTrrToo) {
|
||||||
|
// no need to flush TRRed names, they're not resolved "locally"
|
||||||
|
MutexAutoLock lock(addr_info_lock);
|
||||||
|
if (addr_info && !aTrrToo && addr_info->IsTRROrODoH()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (LoadNative()) {
|
||||||
|
if (!onQueue()) {
|
||||||
|
// The request has been passed to the OS resolver. The resultant DNS
|
||||||
|
// record should be considered stale and not trusted; set a flag to
|
||||||
|
// ensure it is called again.
|
||||||
|
StoreResolveAgain(true);
|
||||||
|
}
|
||||||
|
// if onQueue is true, the host entry is already added to the cache
|
||||||
|
// but is still pending to get resolved: just leave it in hash.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Already resolved; not in a pending state; remove from cache
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddrHostRecord::ResolveComplete() {
|
||||||
|
if (LoadNativeUsed()) {
|
||||||
|
if (mNativeSuccess) {
|
||||||
|
uint32_t millis = static_cast<uint32_t>(mNativeDuration.ToMilliseconds());
|
||||||
|
Telemetry::Accumulate(Telemetry::DNS_NATIVE_LOOKUP_TIME, millis);
|
||||||
|
}
|
||||||
|
AccumulateCategoricalKeyed(
|
||||||
|
TRRService::ProviderKey(),
|
||||||
|
mNativeSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osOK
|
||||||
|
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mResolverType == DNSResolverType::ODoH) {
|
||||||
|
// XXX(kershaw): Consider adding the failed host name into a blocklist.
|
||||||
|
if (mTRRSuccess) {
|
||||||
|
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
|
||||||
|
Telemetry::Accumulate(Telemetry::DNS_ODOH_LOOKUP_TIME, millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
|
||||||
|
Telemetry::Accumulate(Telemetry::ODOH_SKIP_REASON_ODOH_FIRST,
|
||||||
|
static_cast<uint32_t>(mTRRSkippedReason));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mResolverType == DNSResolverType::TRR) {
|
||||||
|
if (mTRRSuccess) {
|
||||||
|
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
|
||||||
|
Telemetry::Accumulate(Telemetry::DNS_TRR_LOOKUP_TIME3,
|
||||||
|
TRRService::ProviderKey(), millis);
|
||||||
|
}
|
||||||
|
AccumulateCategoricalKeyed(
|
||||||
|
TRRService::ProviderKey(),
|
||||||
|
mTRRSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrOK
|
||||||
|
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
|
||||||
|
Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_TRR_FIRST2,
|
||||||
|
TRRService::ProviderKey(),
|
||||||
|
static_cast<uint32_t>(mTRRSkippedReason));
|
||||||
|
|
||||||
|
if (!mTRRSuccess) {
|
||||||
|
Telemetry::Accumulate(
|
||||||
|
mNativeSuccess ? Telemetry::TRR_SKIP_REASON_NATIVE_SUCCESS
|
||||||
|
: Telemetry::TRR_SKIP_REASON_NATIVE_FAILED,
|
||||||
|
TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
|
||||||
|
if (flags & nsIDNSService::RESOLVE_DISABLE_TRR) {
|
||||||
|
// TRR is disabled on request, which is a next-level back-off method.
|
||||||
|
Telemetry::Accumulate(Telemetry::DNS_TRR_DISABLED3,
|
||||||
|
TRRService::ProviderKey(), mNativeSuccess);
|
||||||
|
} else {
|
||||||
|
if (mTRRSuccess) {
|
||||||
|
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
|
||||||
|
Telemetry::LABELS_DNS_TRR_FIRST4::TRR);
|
||||||
|
} else if (mNativeSuccess) {
|
||||||
|
if (mResolverType == DNSResolverType::TRR) {
|
||||||
|
AccumulateCategoricalKeyed(
|
||||||
|
TRRService::ProviderKey(),
|
||||||
|
Telemetry::LABELS_DNS_TRR_FIRST4::NativeAfterTRR);
|
||||||
|
} else {
|
||||||
|
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
|
||||||
|
Telemetry::LABELS_DNS_TRR_FIRST4::Native);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AccumulateCategoricalKeyed(
|
||||||
|
TRRService::ProviderKey(),
|
||||||
|
Telemetry::LABELS_DNS_TRR_FIRST4::BothFailed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mEffectiveTRRMode) {
|
||||||
|
case nsIRequest::TRR_DISABLED_MODE:
|
||||||
|
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::nativeOnly);
|
||||||
|
break;
|
||||||
|
case nsIRequest::TRR_FIRST_MODE:
|
||||||
|
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrFirst);
|
||||||
|
break;
|
||||||
|
case nsIRequest::TRR_ONLY_MODE:
|
||||||
|
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrOnly);
|
||||||
|
break;
|
||||||
|
case nsIRequest::TRR_DEFAULT_MODE:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("We should not have a default value here");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mResolverType == DNSResolverType::TRR && !mTRRSuccess && mNativeSuccess &&
|
||||||
|
gTRRService) {
|
||||||
|
gTRRService->AddToBlocklist(nsCString(host), originSuffix, pb, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(uint16_t aFlags) {
|
||||||
|
if (IsHighPriority(aFlags)) {
|
||||||
|
return AddrHostRecord::DNS_PRIORITY_HIGH;
|
||||||
|
}
|
||||||
|
if (IsMediumPriority(aFlags)) {
|
||||||
|
return AddrHostRecord::DNS_PRIORITY_MEDIUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddrHostRecord::DNS_PRIORITY_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// TypeHostRecord
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
|
||||||
|
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
|
||||||
|
|
||||||
|
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
|
||||||
|
: nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
|
||||||
|
|
||||||
|
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
|
||||||
|
|
||||||
|
bool TypeHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const {
|
||||||
|
if (CheckExpiration(now) == EXP_EXPIRED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !mResults.is<Nothing>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TypeHostRecord::RefreshForNegativeResponse() const { return false; }
|
||||||
|
|
||||||
|
NS_IMETHODIMP TypeHostRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
|
||||||
|
// deep copy
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
|
||||||
|
if (!mResults.is<TypeRecordTxt>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
aRecords = mResults.as<CopyableTArray<nsCString>>();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
||||||
|
// deep copy
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
|
||||||
|
if (!mResults.is<TypeRecordTxt>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
auto& results = mResults.as<CopyableTArray<nsCString>>();
|
||||||
|
for (uint32_t i = 0; i < results.Length(); i++) {
|
||||||
|
aRecords.Append(results[i]);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||||
|
size_t n = mallocSizeOf(this);
|
||||||
|
|
||||||
|
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
|
||||||
|
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TypeHostRecord::GetType() {
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
|
||||||
|
return mResults.match(
|
||||||
|
[](TypeRecordEmpty&) {
|
||||||
|
MOZ_ASSERT(false, "This should never be the case");
|
||||||
|
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
||||||
|
},
|
||||||
|
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
|
||||||
|
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeRecordResultType TypeHostRecord::GetResults() {
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
return mResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
||||||
|
|
||||||
|
for (const SVCB& r : results) {
|
||||||
|
RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
|
||||||
|
aRecords.AppendElement(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
|
||||||
|
nsISVCBRecord** aRecord) {
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
||||||
|
nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
|
||||||
|
aNoHttp2, aNoHttp3, results, mAllRecordsExcluded);
|
||||||
|
if (!result) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.forget(aRecord);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetAllRecordsWithEchConfig(
|
||||||
|
bool aNoHttp2, bool aNoHttp3, bool* aAllRecordsHaveEchConfig,
|
||||||
|
bool* aAllRecordsInH3ExcludedList,
|
||||||
|
nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& records = mResults.as<TypeRecordHTTPSSVC>();
|
||||||
|
GetAllRecordsWithEchConfigInternal(aNoHttp2, aNoHttp3, records,
|
||||||
|
aAllRecordsHaveEchConfig,
|
||||||
|
aAllRecordsInH3ExcludedList, aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetHasIPAddresses(bool* aResult) {
|
||||||
|
NS_ENSURE_ARG(aResult);
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
|
||||||
|
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
||||||
|
*aResult = HasIPAddressesInternal(results);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetAllRecordsExcluded(bool* aResult) {
|
||||||
|
NS_ENSURE_ARG(aResult);
|
||||||
|
MutexAutoLock lock(mResultsLock);
|
||||||
|
|
||||||
|
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aResult = mAllRecordsExcluded;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TypeHostRecord::GetTtl(uint32_t* aResult) {
|
||||||
|
NS_ENSURE_ARG(aResult);
|
||||||
|
*aResult = mTtl;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
365
netwerk/dns/nsHostRecord.h
Normal file
365
netwerk/dns/nsHostRecord.h
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
/* vim:set ts=4 sw=2 sts=2 et cin: */
|
||||||
|
/* 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 nsHostRecord_h__
|
||||||
|
#define nsHostRecord_h__
|
||||||
|
|
||||||
|
#include "mozilla/LinkedList.h"
|
||||||
|
#include "mozilla/net/HTTPSSVC.h"
|
||||||
|
#include "nsIDNSService.h"
|
||||||
|
#include "nsIDNSByTypeRecord.h"
|
||||||
|
#include "PLDHashTable.h"
|
||||||
|
#include "TRRSkippedReason.h"
|
||||||
|
|
||||||
|
class nsHostRecord;
|
||||||
|
class nsHostResolver;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace net {
|
||||||
|
class TRR;
|
||||||
|
class TRRQuery;
|
||||||
|
} // namespace net
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to notify listeners when a ResolveHost operation is
|
||||||
|
* complete. Classes that derive it must implement threadsafe nsISupports
|
||||||
|
* to be able to use RefPtr with this class.
|
||||||
|
*/
|
||||||
|
class nsResolveHostCallback
|
||||||
|
: public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>,
|
||||||
|
public nsISupports {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* OnResolveHostComplete
|
||||||
|
*
|
||||||
|
* this function is called to complete a host lookup initiated by
|
||||||
|
* nsHostResolver::ResolveHost. it may be invoked recursively from
|
||||||
|
* ResolveHost or on an unspecified background thread.
|
||||||
|
*
|
||||||
|
* NOTE: it is the responsibility of the implementor of this method
|
||||||
|
* to handle the callback in a thread safe manner.
|
||||||
|
*
|
||||||
|
* @param resolver
|
||||||
|
* nsHostResolver object associated with this result
|
||||||
|
* @param record
|
||||||
|
* the host record containing the results of the lookup
|
||||||
|
* @param status
|
||||||
|
* if successful, |record| contains non-null results
|
||||||
|
*/
|
||||||
|
virtual void OnResolveHostComplete(nsHostResolver* resolver,
|
||||||
|
nsHostRecord* record, nsresult status) = 0;
|
||||||
|
/**
|
||||||
|
* EqualsAsyncListener
|
||||||
|
*
|
||||||
|
* Determines if the listener argument matches the listener member var.
|
||||||
|
* For subclasses not implementing a member listener, should return false.
|
||||||
|
* For subclasses having a member listener, the function should check if
|
||||||
|
* they are the same. Used for cases where a pointer to an object
|
||||||
|
* implementing nsResolveHostCallback is unknown, but a pointer to
|
||||||
|
* the original listener is known.
|
||||||
|
*
|
||||||
|
* @param aListener
|
||||||
|
* nsIDNSListener object associated with the original request
|
||||||
|
*/
|
||||||
|
virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0;
|
||||||
|
|
||||||
|
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~nsResolveHostCallback() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nsHostKey {
|
||||||
|
const nsCString host;
|
||||||
|
const nsCString mTrrServer;
|
||||||
|
uint16_t type = 0;
|
||||||
|
uint16_t flags = 0;
|
||||||
|
uint16_t af = 0;
|
||||||
|
bool pb = false;
|
||||||
|
const nsCString originSuffix;
|
||||||
|
explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
|
||||||
|
uint16_t type, uint16_t flags, uint16_t af, bool pb,
|
||||||
|
const nsACString& originSuffix);
|
||||||
|
bool operator==(const nsHostKey& other) const;
|
||||||
|
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||||
|
PLDHashNumber Hash() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nsHostRecord - ref counted object type stored in host resolver cache.
|
||||||
|
*/
|
||||||
|
class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
|
||||||
|
public nsHostKey,
|
||||||
|
public nsISupports {
|
||||||
|
using TRRSkippedReason = mozilla::net::TRRSkippedReason;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
|
||||||
|
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the TRR mode encoded by the flags
|
||||||
|
nsIRequest::TRRMode TRRMode();
|
||||||
|
|
||||||
|
// Records the first reason that caused TRR to be skipped or to fail.
|
||||||
|
void RecordReason(TRRSkippedReason reason) {
|
||||||
|
if (mTRRSkippedReason == TRRSkippedReason::TRR_UNSET) {
|
||||||
|
mTRRSkippedReason = reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DnsPriority {
|
||||||
|
DNS_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
|
||||||
|
DNS_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
|
||||||
|
DNS_PRIORITY_HIGH,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class nsHostResolver;
|
||||||
|
friend class mozilla::net::TRR;
|
||||||
|
friend class mozilla::net::TRRQuery;
|
||||||
|
|
||||||
|
explicit nsHostRecord(const nsHostKey& key);
|
||||||
|
virtual ~nsHostRecord() = default;
|
||||||
|
|
||||||
|
// Mark hostrecord as not usable
|
||||||
|
void Invalidate();
|
||||||
|
|
||||||
|
enum ExpirationStatus {
|
||||||
|
EXP_VALID,
|
||||||
|
EXP_GRACE,
|
||||||
|
EXP_EXPIRED,
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
|
||||||
|
|
||||||
|
// Convenience function for setting the timestamps above (mValidStart,
|
||||||
|
// mValidEnd, and mGraceStart). valid and grace are durations in seconds.
|
||||||
|
void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
|
||||||
|
unsigned int grace);
|
||||||
|
void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord);
|
||||||
|
|
||||||
|
// Checks if the record is usable (not expired and has a value)
|
||||||
|
bool HasUsableResult(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags = 0) const;
|
||||||
|
|
||||||
|
static DnsPriority GetPriority(uint16_t aFlags);
|
||||||
|
|
||||||
|
virtual void Cancel();
|
||||||
|
virtual bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const = 0;
|
||||||
|
virtual bool RefreshForNegativeResponse() const { return true; }
|
||||||
|
|
||||||
|
mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks;
|
||||||
|
|
||||||
|
bool IsAddrRecord() const {
|
||||||
|
return type == nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the record began being valid. Used mainly for bookkeeping.
|
||||||
|
mozilla::TimeStamp mValidStart;
|
||||||
|
|
||||||
|
// When the record is no longer valid (it's time of expiration)
|
||||||
|
mozilla::TimeStamp mValidEnd;
|
||||||
|
|
||||||
|
// When the record enters its grace period. This must be before mValidEnd.
|
||||||
|
// If a record is in its grace period (and not expired), it will be used
|
||||||
|
// but a request to refresh it will be made.
|
||||||
|
mozilla::TimeStamp mGraceStart;
|
||||||
|
|
||||||
|
uint32_t mTtl = 0;
|
||||||
|
|
||||||
|
// The computed TRR mode that is actually used by the request.
|
||||||
|
// It is set in nsHostResolver::NameLookup and is based on the mode of the
|
||||||
|
// default resolver and the TRRMode encoded in the flags.
|
||||||
|
// The mode into account if the TRR service is disabled,
|
||||||
|
// parental controls are on, domain matches exclusion list, etc.
|
||||||
|
nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
|
||||||
|
|
||||||
|
TRRSkippedReason mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
|
||||||
|
TRRSkippedReason mTRRAFailReason = TRRSkippedReason::TRR_UNSET;
|
||||||
|
TRRSkippedReason mTRRAAAAFailReason = TRRSkippedReason::TRR_UNSET;
|
||||||
|
|
||||||
|
mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
|
||||||
|
|
||||||
|
// counter of outstanding resolving calls
|
||||||
|
mozilla::Atomic<int32_t> mResolving{0};
|
||||||
|
|
||||||
|
// True if this record is a cache of a failed lookup. Negative cache
|
||||||
|
// entries are valid just like any other (though never for more than 60
|
||||||
|
// seconds), but a use of that negative entry forces an asynchronous refresh.
|
||||||
|
bool negative = false;
|
||||||
|
|
||||||
|
// Explicitly expired
|
||||||
|
bool mDoomed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// b020e996-f6ab-45e5-9bf5-1da71dd0053a
|
||||||
|
#define ADDRHOSTRECORD_IID \
|
||||||
|
{ \
|
||||||
|
0xb020e996, 0xf6ab, 0x45e5, { \
|
||||||
|
0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddrHostRecord final : public nsHostRecord {
|
||||||
|
using Mutex = mozilla::Mutex;
|
||||||
|
using DNSResolverType = mozilla::net::DNSResolverType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
/* a fully resolved host record has either a non-null |addr_info| or |addr|
|
||||||
|
* field. if |addr_info| is null, it implies that the |host| is an IP
|
||||||
|
* address literal. in which case, |addr| contains the parsed address.
|
||||||
|
* otherwise, if |addr_info| is non-null, then it contains one or many
|
||||||
|
* IP addresses corresponding to the given host name. if both |addr_info|
|
||||||
|
* and |addr| are null, then the given host has not yet been fully resolved.
|
||||||
|
* |af| is the address family of the record we are querying for.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* the lock protects |addr_info| and |addr_info_gencnt| because they
|
||||||
|
* are mutable and accessed by the resolver worker thread and the
|
||||||
|
* nsDNSService2 class. |addr| doesn't change after it has been
|
||||||
|
* assigned a value. only the resolver worker thread modifies
|
||||||
|
* nsHostRecord (and only in nsHostResolver::CompleteLookup);
|
||||||
|
* the other threads just read it. therefore the resolver worker
|
||||||
|
* thread doesn't need to lock when reading |addr_info|.
|
||||||
|
*/
|
||||||
|
Mutex addr_info_lock{"AddrHostRecord.addr_info_lock"};
|
||||||
|
// generation count of |addr_info|
|
||||||
|
int addr_info_gencnt = 0;
|
||||||
|
RefPtr<mozilla::net::AddrInfo> addr_info;
|
||||||
|
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
|
||||||
|
|
||||||
|
// hold addr_info_lock when calling the blocklist functions
|
||||||
|
bool Blocklisted(const mozilla::net::NetAddr* query);
|
||||||
|
void ResetBlocklist();
|
||||||
|
void ReportUnusable(const mozilla::net::NetAddr* aAddress);
|
||||||
|
|
||||||
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||||
|
|
||||||
|
nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class nsHostResolver;
|
||||||
|
friend class mozilla::net::TRR;
|
||||||
|
friend class mozilla::net::TRRQuery;
|
||||||
|
|
||||||
|
explicit AddrHostRecord(const nsHostKey& key);
|
||||||
|
~AddrHostRecord();
|
||||||
|
|
||||||
|
// Checks if the record is usable (not expired and has a value)
|
||||||
|
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const override;
|
||||||
|
|
||||||
|
bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved
|
||||||
|
// as needed to resolve again.
|
||||||
|
|
||||||
|
void ResolveComplete();
|
||||||
|
|
||||||
|
static DnsPriority GetPriority(uint16_t aFlags);
|
||||||
|
|
||||||
|
// true if pending and on the queue (not yet given to getaddrinfo())
|
||||||
|
bool onQueue() { return LoadNative() && isInList(); }
|
||||||
|
|
||||||
|
// When the lookups of this record started and their durations
|
||||||
|
mozilla::TimeStamp mTrrStart;
|
||||||
|
mozilla::TimeStamp mNativeStart;
|
||||||
|
mozilla::TimeDuration mTrrDuration;
|
||||||
|
mozilla::TimeDuration mNativeDuration;
|
||||||
|
|
||||||
|
// TRR or ODoH was used on this record
|
||||||
|
mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
|
||||||
|
uint8_t mTRRSuccess = 0; // number of successful TRR responses
|
||||||
|
uint8_t mNativeSuccess = 0; // number of native lookup responses
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
|
||||||
|
// true if this record is being resolved "natively", which means that
|
||||||
|
// it is either on the pending queue or owned by one of the worker threads.
|
||||||
|
(uint16_t, Native, 1),
|
||||||
|
(uint16_t, NativeUsed, 1),
|
||||||
|
// true if off queue and contributing to mActiveAnyThreadCount
|
||||||
|
(uint16_t, UsingAnyThread, 1),
|
||||||
|
(uint16_t, GetTtl, 1),
|
||||||
|
(uint16_t, ResolveAgain, 1)
|
||||||
|
))
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// The number of times ReportUnusable() has been called in the record's
|
||||||
|
// lifetime.
|
||||||
|
uint32_t mUnusableCount = 0;
|
||||||
|
|
||||||
|
// a list of addresses associated with this record that have been reported
|
||||||
|
// as unusable. the list is kept as a set of strings to make it independent
|
||||||
|
// of gencnt.
|
||||||
|
nsTArray<nsCString> mUnusableItems;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
|
||||||
|
|
||||||
|
// 77b786a7-04be-44f2-987c-ab8aa96676e0
|
||||||
|
#define TYPEHOSTRECORD_IID \
|
||||||
|
{ \
|
||||||
|
0x77b786a7, 0x04be, 0x44f2, { \
|
||||||
|
0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeHostRecord final : public nsHostRecord,
|
||||||
|
public nsIDNSTXTRecord,
|
||||||
|
public nsIDNSHTTPSSVCRecord,
|
||||||
|
public mozilla::net::DNSHTTPSSVCRecordBase {
|
||||||
|
public:
|
||||||
|
NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_NSIDNSTXTRECORD
|
||||||
|
NS_DECL_NSIDNSHTTPSSVCRECORD
|
||||||
|
|
||||||
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||||
|
uint32_t GetType();
|
||||||
|
mozilla::net::TypeRecordResultType GetResults();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class nsHostResolver;
|
||||||
|
friend class mozilla::net::TRRQuery;
|
||||||
|
|
||||||
|
explicit TypeHostRecord(const nsHostKey& key);
|
||||||
|
~TypeHostRecord();
|
||||||
|
|
||||||
|
// Checks if the record is usable (not expired and has a value)
|
||||||
|
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
||||||
|
uint16_t queryFlags) const override;
|
||||||
|
bool RefreshForNegativeResponse() const override;
|
||||||
|
|
||||||
|
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
|
||||||
|
mozilla::Mutex mResultsLock{"TypeHostRecord.mResultsLock"};
|
||||||
|
|
||||||
|
// When the lookups of this record started (for telemetry).
|
||||||
|
mozilla::TimeStamp mStart;
|
||||||
|
bool mAllRecordsExcluded = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID)
|
||||||
|
|
||||||
|
static inline bool IsHighPriority(uint16_t flags) {
|
||||||
|
return !(flags & (nsHostRecord::DNS_PRIORITY_LOW |
|
||||||
|
nsHostRecord::DNS_PRIORITY_MEDIUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool IsMediumPriority(uint16_t flags) {
|
||||||
|
return flags & nsHostRecord::DNS_PRIORITY_MEDIUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool IsLowPriority(uint16_t flags) {
|
||||||
|
return flags & nsHostRecord::DNS_PRIORITY_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // nsHostRecord_h__
|
||||||
@@ -47,6 +47,8 @@
|
|||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/StaticPrefs_network.h"
|
#include "mozilla/StaticPrefs_network.h"
|
||||||
|
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
|
||||||
|
#include "DNSLogging.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::net;
|
using namespace mozilla::net;
|
||||||
@@ -86,12 +88,6 @@ static_assert(
|
|||||||
|
|
||||||
namespace mozilla::net {
|
namespace mozilla::net {
|
||||||
LazyLogModule gHostResolverLog("nsHostResolver");
|
LazyLogModule gHostResolverLog("nsHostResolver");
|
||||||
#define LOG(args) \
|
|
||||||
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug, args)
|
|
||||||
#define LOG1(args) \
|
|
||||||
MOZ_LOG(mozilla::net::gHostResolverLog, mozilla::LogLevel::Error, args)
|
|
||||||
#define LOG_ENABLED() \
|
|
||||||
MOZ_LOG_TEST(mozilla::net::gHostResolverLog, mozilla::LogLevel::Debug)
|
|
||||||
} // namespace mozilla::net
|
} // namespace mozilla::net
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -137,530 +133,6 @@ class nsResState {
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
static inline bool IsHighPriority(uint16_t flags) {
|
|
||||||
return !(flags & (nsHostResolver::RES_PRIORITY_LOW |
|
|
||||||
nsHostResolver::RES_PRIORITY_MEDIUM));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool IsMediumPriority(uint16_t flags) {
|
|
||||||
return flags & nsHostResolver::RES_PRIORITY_MEDIUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool IsLowPriority(uint16_t flags) {
|
|
||||||
return flags & nsHostResolver::RES_PRIORITY_LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// this macro filters out any flags that are not used when constructing the
|
|
||||||
// host key. the significant flags are those that would affect the resulting
|
|
||||||
// host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
|
|
||||||
#define RES_KEY_FLAGS(_f) \
|
|
||||||
((_f) & \
|
|
||||||
(nsHostResolver::RES_CANON_NAME | nsHostResolver::RES_DISABLE_TRR | \
|
|
||||||
nsIDNSService::RESOLVE_TRR_MODE_MASK | nsHostResolver::RES_IP_HINT))
|
|
||||||
|
|
||||||
#define IS_ADDR_TYPE(_type) ((_type) == nsIDNSService::RESOLVE_TYPE_DEFAULT)
|
|
||||||
#define IS_OTHER_TYPE(_type) ((_type) != nsIDNSService::RESOLVE_TYPE_DEFAULT)
|
|
||||||
|
|
||||||
nsHostKey::nsHostKey(const nsACString& aHost, const nsACString& aTrrServer,
|
|
||||||
uint16_t aType, uint16_t aFlags, uint16_t aAf, bool aPb,
|
|
||||||
const nsACString& aOriginsuffix)
|
|
||||||
: host(aHost),
|
|
||||||
mTrrServer(aTrrServer),
|
|
||||||
type(aType),
|
|
||||||
flags(aFlags),
|
|
||||||
af(aAf),
|
|
||||||
pb(aPb),
|
|
||||||
originSuffix(aOriginsuffix) {}
|
|
||||||
|
|
||||||
bool nsHostKey::operator==(const nsHostKey& other) const {
|
|
||||||
return host == other.host && mTrrServer == other.mTrrServer &&
|
|
||||||
type == other.type &&
|
|
||||||
RES_KEY_FLAGS(flags) == RES_KEY_FLAGS(other.flags) && af == other.af &&
|
|
||||||
originSuffix == other.originSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLDHashNumber nsHostKey::Hash() const {
|
|
||||||
return AddToHash(HashString(host.get()), HashString(mTrrServer.get()), type,
|
|
||||||
RES_KEY_FLAGS(flags), af, HashString(originSuffix.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nsHostKey::SizeOfExcludingThis(
|
|
||||||
mozilla::MallocSizeOf mallocSizeOf) const {
|
|
||||||
size_t n = 0;
|
|
||||||
n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
|
||||||
n += mTrrServer.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
|
||||||
n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS0(nsHostRecord)
|
|
||||||
|
|
||||||
nsHostRecord::nsHostRecord(const nsHostKey& key)
|
|
||||||
: nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
|
|
||||||
|
|
||||||
void nsHostRecord::Invalidate() { mDoomed = true; }
|
|
||||||
|
|
||||||
void nsHostRecord::Cancel() {
|
|
||||||
RefPtr<TRRQuery> query;
|
|
||||||
{
|
|
||||||
auto lock = mTRRQuery.Lock();
|
|
||||||
query.swap(lock.ref());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
query->Cancel(NS_ERROR_ABORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsHostRecord::ExpirationStatus nsHostRecord::CheckExpiration(
|
|
||||||
const mozilla::TimeStamp& now) const {
|
|
||||||
if (!mGraceStart.IsNull() && now >= mGraceStart && !mValidEnd.IsNull() &&
|
|
||||||
now < mValidEnd) {
|
|
||||||
return nsHostRecord::EXP_GRACE;
|
|
||||||
}
|
|
||||||
if (!mValidEnd.IsNull() && now < mValidEnd) {
|
|
||||||
return nsHostRecord::EXP_VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nsHostRecord::EXP_EXPIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsHostRecord::SetExpiration(const mozilla::TimeStamp& now,
|
|
||||||
unsigned int valid, unsigned int grace) {
|
|
||||||
mValidStart = now;
|
|
||||||
if ((valid + grace) < 60) {
|
|
||||||
grace = 60 - valid;
|
|
||||||
LOG(("SetExpiration: artificially bumped grace to %d\n", grace));
|
|
||||||
}
|
|
||||||
mGraceStart = now + TimeDuration::FromSeconds(valid);
|
|
||||||
mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
|
|
||||||
mTtl = valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsHostRecord::CopyExpirationTimesAndFlagsFrom(
|
|
||||||
const nsHostRecord* aFromHostRecord) {
|
|
||||||
// This is used to copy information from a cache entry to a record. All
|
|
||||||
// information necessary for HasUsableRecord needs to be copied.
|
|
||||||
mValidStart = aFromHostRecord->mValidStart;
|
|
||||||
mValidEnd = aFromHostRecord->mValidEnd;
|
|
||||||
mGraceStart = aFromHostRecord->mGraceStart;
|
|
||||||
mDoomed = aFromHostRecord->mDoomed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const {
|
|
||||||
if (mDoomed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HasUsableResultInternal(now, queryFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t SizeOfResolveHostCallbackListExcludingHead(
|
|
||||||
const mozilla::LinkedList<RefPtr<nsResolveHostCallback>>& aCallbacks,
|
|
||||||
MallocSizeOf mallocSizeOf) {
|
|
||||||
size_t n = aCallbacks.sizeOfExcludingThis(mallocSizeOf);
|
|
||||||
|
|
||||||
for (const nsResolveHostCallback* t = aCallbacks.getFirst(); t;
|
|
||||||
t = t->getNext()) {
|
|
||||||
n += t->SizeOfIncludingThis(mallocSizeOf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
|
|
||||||
|
|
||||||
AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
|
|
||||||
|
|
||||||
AddrHostRecord::~AddrHostRecord() {
|
|
||||||
mCallbacks.clear();
|
|
||||||
Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mUnusableCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AddrHostRecord::Blocklisted(const NetAddr* aQuery) {
|
|
||||||
addr_info_lock.AssertCurrentThreadOwns();
|
|
||||||
LOG(("Checking unusable list for host [%s], host record [%p].\n", host.get(),
|
|
||||||
this));
|
|
||||||
|
|
||||||
// skip the string conversion for the common case of no blocklist
|
|
||||||
if (!mUnusableItems.Length()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[kIPv6CStrBufSize];
|
|
||||||
if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nsDependentCString strQuery(buf);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mUnusableItems.Length(); i++) {
|
|
||||||
if (mUnusableItems.ElementAt(i).Equals(strQuery)) {
|
|
||||||
LOG(("Address [%s] is blocklisted for host [%s].\n", buf, host.get()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
|
|
||||||
addr_info_lock.AssertCurrentThreadOwns();
|
|
||||||
LOG(
|
|
||||||
("Adding address to blocklist for host [%s], host record [%p]."
|
|
||||||
"used trr=%d\n",
|
|
||||||
host.get(), this, mTRRSuccess));
|
|
||||||
|
|
||||||
++mUnusableCount;
|
|
||||||
|
|
||||||
char buf[kIPv6CStrBufSize];
|
|
||||||
if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
|
|
||||||
LOG(
|
|
||||||
("Successfully adding address [%s] to blocklist for host "
|
|
||||||
"[%s].\n",
|
|
||||||
buf, host.get()));
|
|
||||||
mUnusableItems.AppendElement(nsCString(buf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddrHostRecord::ResetBlocklist() {
|
|
||||||
addr_info_lock.AssertCurrentThreadOwns();
|
|
||||||
LOG(("Resetting blocklist for host [%s], host record [%p].\n", host.get(),
|
|
||||||
this));
|
|
||||||
mUnusableItems.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t AddrHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
|
||||||
size_t n = mallocSizeOf(this);
|
|
||||||
|
|
||||||
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
|
|
||||||
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
|
|
||||||
|
|
||||||
n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
|
|
||||||
n += mallocSizeOf(addr.get());
|
|
||||||
|
|
||||||
n += mUnusableItems.ShallowSizeOfExcludingThis(mallocSizeOf);
|
|
||||||
for (size_t i = 0; i < mUnusableItems.Length(); i++) {
|
|
||||||
n += mUnusableItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AddrHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const {
|
|
||||||
// don't use cached negative results for high priority queries.
|
|
||||||
if (negative && IsHighPriority(queryFlags)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckExpiration(now) == EXP_EXPIRED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addr_info || addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the entry can be removed, or false if it should be left.
|
|
||||||
// Sets ResolveAgain true for entries being resolved right now.
|
|
||||||
bool AddrHostRecord::RemoveOrRefresh(bool aTrrToo) {
|
|
||||||
// no need to flush TRRed names, they're not resolved "locally"
|
|
||||||
MutexAutoLock lock(addr_info_lock);
|
|
||||||
if (addr_info && !aTrrToo && addr_info->IsTRROrODoH()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (LoadNative()) {
|
|
||||||
if (!onQueue()) {
|
|
||||||
// The request has been passed to the OS resolver. The resultant DNS
|
|
||||||
// record should be considered stale and not trusted; set a flag to
|
|
||||||
// ensure it is called again.
|
|
||||||
StoreResolveAgain(true);
|
|
||||||
}
|
|
||||||
// if onQueue is true, the host entry is already added to the cache
|
|
||||||
// but is still pending to get resolved: just leave it in hash.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Already resolved; not in a pending state; remove from cache
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddrHostRecord::ResolveComplete() {
|
|
||||||
if (LoadNativeUsed()) {
|
|
||||||
if (mNativeSuccess) {
|
|
||||||
uint32_t millis = static_cast<uint32_t>(mNativeDuration.ToMilliseconds());
|
|
||||||
Telemetry::Accumulate(Telemetry::DNS_NATIVE_LOOKUP_TIME, millis);
|
|
||||||
}
|
|
||||||
AccumulateCategoricalKeyed(
|
|
||||||
TRRService::ProviderKey(),
|
|
||||||
mNativeSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osOK
|
|
||||||
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osFail);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mResolverType == DNSResolverType::ODoH) {
|
|
||||||
// XXX(kershaw): Consider adding the failed host name into a blocklist.
|
|
||||||
if (mTRRSuccess) {
|
|
||||||
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
|
|
||||||
Telemetry::Accumulate(Telemetry::DNS_ODOH_LOOKUP_TIME, millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
|
|
||||||
Telemetry::Accumulate(Telemetry::ODOH_SKIP_REASON_ODOH_FIRST,
|
|
||||||
static_cast<uint32_t>(mTRRSkippedReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mResolverType == DNSResolverType::TRR) {
|
|
||||||
if (mTRRSuccess) {
|
|
||||||
uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
|
|
||||||
Telemetry::Accumulate(Telemetry::DNS_TRR_LOOKUP_TIME3,
|
|
||||||
TRRService::ProviderKey(), millis);
|
|
||||||
}
|
|
||||||
AccumulateCategoricalKeyed(
|
|
||||||
TRRService::ProviderKey(),
|
|
||||||
mTRRSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrOK
|
|
||||||
: Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrFail);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
|
|
||||||
Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_TRR_FIRST2,
|
|
||||||
TRRService::ProviderKey(),
|
|
||||||
static_cast<uint32_t>(mTRRSkippedReason));
|
|
||||||
|
|
||||||
if (!mTRRSuccess) {
|
|
||||||
Telemetry::Accumulate(
|
|
||||||
mNativeSuccess ? Telemetry::TRR_SKIP_REASON_NATIVE_SUCCESS
|
|
||||||
: Telemetry::TRR_SKIP_REASON_NATIVE_FAILED,
|
|
||||||
TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
|
|
||||||
if (flags & nsIDNSService::RESOLVE_DISABLE_TRR) {
|
|
||||||
// TRR is disabled on request, which is a next-level back-off method.
|
|
||||||
Telemetry::Accumulate(Telemetry::DNS_TRR_DISABLED3,
|
|
||||||
TRRService::ProviderKey(), mNativeSuccess);
|
|
||||||
} else {
|
|
||||||
if (mTRRSuccess) {
|
|
||||||
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
|
|
||||||
Telemetry::LABELS_DNS_TRR_FIRST4::TRR);
|
|
||||||
} else if (mNativeSuccess) {
|
|
||||||
if (mResolverType == DNSResolverType::TRR) {
|
|
||||||
AccumulateCategoricalKeyed(
|
|
||||||
TRRService::ProviderKey(),
|
|
||||||
Telemetry::LABELS_DNS_TRR_FIRST4::NativeAfterTRR);
|
|
||||||
} else {
|
|
||||||
AccumulateCategoricalKeyed(TRRService::ProviderKey(),
|
|
||||||
Telemetry::LABELS_DNS_TRR_FIRST4::Native);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AccumulateCategoricalKeyed(
|
|
||||||
TRRService::ProviderKey(),
|
|
||||||
Telemetry::LABELS_DNS_TRR_FIRST4::BothFailed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mEffectiveTRRMode) {
|
|
||||||
case nsIRequest::TRR_DISABLED_MODE:
|
|
||||||
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::nativeOnly);
|
|
||||||
break;
|
|
||||||
case nsIRequest::TRR_FIRST_MODE:
|
|
||||||
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrFirst);
|
|
||||||
break;
|
|
||||||
case nsIRequest::TRR_ONLY_MODE:
|
|
||||||
AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrOnly);
|
|
||||||
break;
|
|
||||||
case nsIRequest::TRR_DEFAULT_MODE:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("We should not have a default value here");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mResolverType == DNSResolverType::TRR && !mTRRSuccess && mNativeSuccess &&
|
|
||||||
gTRRService) {
|
|
||||||
gTRRService->AddToBlocklist(nsCString(host), originSuffix, pb, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(uint16_t aFlags) {
|
|
||||||
if (IsHighPriority(aFlags)) {
|
|
||||||
return AddrHostRecord::DNS_PRIORITY_HIGH;
|
|
||||||
}
|
|
||||||
if (IsMediumPriority(aFlags)) {
|
|
||||||
return AddrHostRecord::DNS_PRIORITY_MEDIUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddrHostRecord::DNS_PRIORITY_LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
|
|
||||||
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
|
|
||||||
|
|
||||||
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
|
|
||||||
: nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
|
|
||||||
|
|
||||||
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
|
|
||||||
|
|
||||||
bool TypeHostRecord::HasUsableResultInternal(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const {
|
|
||||||
if (CheckExpiration(now) == EXP_EXPIRED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !mResults.is<Nothing>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TypeHostRecord::RefreshForNegativeResponse() const { return false; }
|
|
||||||
|
|
||||||
NS_IMETHODIMP TypeHostRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
|
|
||||||
// deep copy
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
|
|
||||||
if (!mResults.is<TypeRecordTxt>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
aRecords = mResults.as<CopyableTArray<nsCString>>();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
|
|
||||||
// deep copy
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
|
|
||||||
if (!mResults.is<TypeRecordTxt>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
auto& results = mResults.as<CopyableTArray<nsCString>>();
|
|
||||||
for (uint32_t i = 0; i < results.Length(); i++) {
|
|
||||||
aRecords.Append(results[i]);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
|
||||||
size_t n = mallocSizeOf(this);
|
|
||||||
|
|
||||||
n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
|
|
||||||
n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TypeHostRecord::GetType() {
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
|
|
||||||
return mResults.match(
|
|
||||||
[](TypeRecordEmpty&) {
|
|
||||||
MOZ_ASSERT(false, "This should never be the case");
|
|
||||||
return nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
|
||||||
},
|
|
||||||
[](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
|
|
||||||
[](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeRecordResultType TypeHostRecord::GetResults() {
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
return mResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
|
||||||
|
|
||||||
for (const SVCB& r : results) {
|
|
||||||
RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
|
|
||||||
aRecords.AppendElement(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
|
|
||||||
nsISVCBRecord** aRecord) {
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
|
||||||
nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
|
|
||||||
aNoHttp2, aNoHttp3, results, mAllRecordsExcluded);
|
|
||||||
if (!result) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.forget(aRecord);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetAllRecordsWithEchConfig(
|
|
||||||
bool aNoHttp2, bool aNoHttp3, bool* aAllRecordsHaveEchConfig,
|
|
||||||
bool* aAllRecordsInH3ExcludedList,
|
|
||||||
nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& records = mResults.as<TypeRecordHTTPSSVC>();
|
|
||||||
GetAllRecordsWithEchConfigInternal(aNoHttp2, aNoHttp3, records,
|
|
||||||
aAllRecordsHaveEchConfig,
|
|
||||||
aAllRecordsInH3ExcludedList, aResult);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetHasIPAddresses(bool* aResult) {
|
|
||||||
NS_ENSURE_ARG(aResult);
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
|
|
||||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& results = mResults.as<TypeRecordHTTPSSVC>();
|
|
||||||
*aResult = HasIPAddressesInternal(results);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetAllRecordsExcluded(bool* aResult) {
|
|
||||||
NS_ENSURE_ARG(aResult);
|
|
||||||
MutexAutoLock lock(mResultsLock);
|
|
||||||
|
|
||||||
if (!mResults.is<TypeRecordHTTPSSVC>()) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aResult = mAllRecordsExcluded;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
TypeHostRecord::GetTtl(uint32_t* aResult) {
|
|
||||||
NS_ENSURE_ARG(aResult);
|
|
||||||
*aResult = mTtl;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static const char kPrefGetTtl[] = "network.dns.get-ttl";
|
static const char kPrefGetTtl[] = "network.dns.get-ttl";
|
||||||
static const char kPrefNativeIsLocalhost[] = "network.dns.native-is-localhost";
|
static const char kPrefNativeIsLocalhost[] = "network.dns.native-is-localhost";
|
||||||
static const char kPrefThreadIdleTime[] =
|
static const char kPrefThreadIdleTime[] =
|
||||||
|
|||||||
@@ -14,26 +14,21 @@
|
|||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsIDNSListener.h"
|
#include "nsIDNSListener.h"
|
||||||
#include "nsIDNSService.h"
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "GetAddrInfo.h"
|
#include "GetAddrInfo.h"
|
||||||
#include "mozilla/net/DNS.h"
|
#include "mozilla/net/DNS.h"
|
||||||
#include "mozilla/net/DashboardTypes.h"
|
#include "mozilla/net/DashboardTypes.h"
|
||||||
#include "mozilla/AtomicBitfields.h"
|
#include "mozilla/AtomicBitfields.h"
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/LinkedList.h"
|
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
#include "nsHostRecord.h"
|
||||||
#include "nsRefPtrHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
#include "nsIThreadPool.h"
|
#include "nsIThreadPool.h"
|
||||||
#include "mozilla/net/NetworkConnectivityService.h"
|
#include "mozilla/net/NetworkConnectivityService.h"
|
||||||
#include "nsIDNSByTypeRecord.h"
|
|
||||||
#include "mozilla/net/DNSByTypeRecord.h"
|
#include "mozilla/net/DNSByTypeRecord.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "TRRSkippedReason.h"
|
|
||||||
|
|
||||||
class nsHostResolver;
|
|
||||||
class nsResolveHostCallback;
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
class TRR;
|
class TRR;
|
||||||
@@ -55,336 +50,6 @@ extern mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost;
|
|||||||
(MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
|
(MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
|
||||||
MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
|
MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
|
||||||
|
|
||||||
struct nsHostKey {
|
|
||||||
const nsCString host;
|
|
||||||
const nsCString mTrrServer;
|
|
||||||
uint16_t type = 0;
|
|
||||||
uint16_t flags = 0;
|
|
||||||
uint16_t af = 0;
|
|
||||||
bool pb = false;
|
|
||||||
const nsCString originSuffix;
|
|
||||||
explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
|
|
||||||
uint16_t type, uint16_t flags, uint16_t af, bool pb,
|
|
||||||
const nsACString& originSuffix);
|
|
||||||
bool operator==(const nsHostKey& other) const;
|
|
||||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
|
||||||
PLDHashNumber Hash() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nsHostRecord - ref counted object type stored in host resolver cache.
|
|
||||||
*/
|
|
||||||
class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
|
|
||||||
public nsHostKey,
|
|
||||||
public nsISupports {
|
|
||||||
using TRRSkippedReason = mozilla::net::TRRSkippedReason;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
|
||||||
|
|
||||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the TRR mode encoded by the flags
|
|
||||||
nsIRequest::TRRMode TRRMode();
|
|
||||||
|
|
||||||
// Records the first reason that caused TRR to be skipped or to fail.
|
|
||||||
void RecordReason(TRRSkippedReason reason) {
|
|
||||||
if (mTRRSkippedReason == TRRSkippedReason::TRR_UNSET) {
|
|
||||||
mTRRSkippedReason = reason;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class nsHostResolver;
|
|
||||||
friend class mozilla::net::TRR;
|
|
||||||
friend class mozilla::net::TRRQuery;
|
|
||||||
|
|
||||||
explicit nsHostRecord(const nsHostKey& key);
|
|
||||||
virtual ~nsHostRecord() = default;
|
|
||||||
|
|
||||||
// Mark hostrecord as not usable
|
|
||||||
void Invalidate();
|
|
||||||
|
|
||||||
enum ExpirationStatus {
|
|
||||||
EXP_VALID,
|
|
||||||
EXP_GRACE,
|
|
||||||
EXP_EXPIRED,
|
|
||||||
};
|
|
||||||
|
|
||||||
ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
|
|
||||||
|
|
||||||
// Convenience function for setting the timestamps above (mValidStart,
|
|
||||||
// mValidEnd, and mGraceStart). valid and grace are durations in seconds.
|
|
||||||
void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
|
|
||||||
unsigned int grace);
|
|
||||||
void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord);
|
|
||||||
|
|
||||||
// Checks if the record is usable (not expired and has a value)
|
|
||||||
bool HasUsableResult(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags = 0) const;
|
|
||||||
|
|
||||||
enum DnsPriority {
|
|
||||||
DNS_PRIORITY_LOW,
|
|
||||||
DNS_PRIORITY_MEDIUM,
|
|
||||||
DNS_PRIORITY_HIGH,
|
|
||||||
};
|
|
||||||
static DnsPriority GetPriority(uint16_t aFlags);
|
|
||||||
|
|
||||||
virtual void Cancel();
|
|
||||||
virtual bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const = 0;
|
|
||||||
virtual bool RefreshForNegativeResponse() const { return true; }
|
|
||||||
|
|
||||||
mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks;
|
|
||||||
|
|
||||||
bool IsAddrRecord() const {
|
|
||||||
return type == nsIDNSService::RESOLVE_TYPE_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the record began being valid. Used mainly for bookkeeping.
|
|
||||||
mozilla::TimeStamp mValidStart;
|
|
||||||
|
|
||||||
// When the record is no longer valid (it's time of expiration)
|
|
||||||
mozilla::TimeStamp mValidEnd;
|
|
||||||
|
|
||||||
// When the record enters its grace period. This must be before mValidEnd.
|
|
||||||
// If a record is in its grace period (and not expired), it will be used
|
|
||||||
// but a request to refresh it will be made.
|
|
||||||
mozilla::TimeStamp mGraceStart;
|
|
||||||
|
|
||||||
uint32_t mTtl = 0;
|
|
||||||
|
|
||||||
// The computed TRR mode that is actually used by the request.
|
|
||||||
// It is set in nsHostResolver::NameLookup and is based on the mode of the
|
|
||||||
// default resolver and the TRRMode encoded in the flags.
|
|
||||||
// The mode into account if the TRR service is disabled,
|
|
||||||
// parental controls are on, domain matches exclusion list, etc.
|
|
||||||
nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
|
|
||||||
|
|
||||||
TRRSkippedReason mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
|
|
||||||
TRRSkippedReason mTRRAFailReason = TRRSkippedReason::TRR_UNSET;
|
|
||||||
TRRSkippedReason mTRRAAAAFailReason = TRRSkippedReason::TRR_UNSET;
|
|
||||||
|
|
||||||
mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
|
|
||||||
|
|
||||||
// counter of outstanding resolving calls
|
|
||||||
mozilla::Atomic<int32_t> mResolving{0};
|
|
||||||
|
|
||||||
// True if this record is a cache of a failed lookup. Negative cache
|
|
||||||
// entries are valid just like any other (though never for more than 60
|
|
||||||
// seconds), but a use of that negative entry forces an asynchronous refresh.
|
|
||||||
bool negative = false;
|
|
||||||
|
|
||||||
// Explicitly expired
|
|
||||||
bool mDoomed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// b020e996-f6ab-45e5-9bf5-1da71dd0053a
|
|
||||||
#define ADDRHOSTRECORD_IID \
|
|
||||||
{ \
|
|
||||||
0xb020e996, 0xf6ab, 0x45e5, { \
|
|
||||||
0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddrHostRecord final : public nsHostRecord {
|
|
||||||
using Mutex = mozilla::Mutex;
|
|
||||||
using DNSResolverType = mozilla::net::DNSResolverType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
|
|
||||||
/* a fully resolved host record has either a non-null |addr_info| or |addr|
|
|
||||||
* field. if |addr_info| is null, it implies that the |host| is an IP
|
|
||||||
* address literal. in which case, |addr| contains the parsed address.
|
|
||||||
* otherwise, if |addr_info| is non-null, then it contains one or many
|
|
||||||
* IP addresses corresponding to the given host name. if both |addr_info|
|
|
||||||
* and |addr| are null, then the given host has not yet been fully resolved.
|
|
||||||
* |af| is the address family of the record we are querying for.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* the lock protects |addr_info| and |addr_info_gencnt| because they
|
|
||||||
* are mutable and accessed by the resolver worker thread and the
|
|
||||||
* nsDNSService2 class. |addr| doesn't change after it has been
|
|
||||||
* assigned a value. only the resolver worker thread modifies
|
|
||||||
* nsHostRecord (and only in nsHostResolver::CompleteLookup);
|
|
||||||
* the other threads just read it. therefore the resolver worker
|
|
||||||
* thread doesn't need to lock when reading |addr_info|.
|
|
||||||
*/
|
|
||||||
Mutex addr_info_lock{"AddrHostRecord.addr_info_lock"};
|
|
||||||
// generation count of |addr_info|
|
|
||||||
int addr_info_gencnt = 0;
|
|
||||||
RefPtr<mozilla::net::AddrInfo> addr_info;
|
|
||||||
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
|
|
||||||
|
|
||||||
// hold addr_info_lock when calling the blocklist functions
|
|
||||||
bool Blocklisted(const mozilla::net::NetAddr* query);
|
|
||||||
void ResetBlocklist();
|
|
||||||
void ReportUnusable(const mozilla::net::NetAddr* aAddress);
|
|
||||||
|
|
||||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
|
|
||||||
|
|
||||||
nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class nsHostResolver;
|
|
||||||
friend class mozilla::net::TRR;
|
|
||||||
friend class mozilla::net::TRRQuery;
|
|
||||||
|
|
||||||
explicit AddrHostRecord(const nsHostKey& key);
|
|
||||||
~AddrHostRecord();
|
|
||||||
|
|
||||||
// Checks if the record is usable (not expired and has a value)
|
|
||||||
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const override;
|
|
||||||
|
|
||||||
bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved
|
|
||||||
// as needed to resolve again.
|
|
||||||
|
|
||||||
void ResolveComplete();
|
|
||||||
|
|
||||||
enum DnsPriority {
|
|
||||||
DNS_PRIORITY_LOW,
|
|
||||||
DNS_PRIORITY_MEDIUM,
|
|
||||||
DNS_PRIORITY_HIGH,
|
|
||||||
};
|
|
||||||
static DnsPriority GetPriority(uint16_t aFlags);
|
|
||||||
|
|
||||||
// true if pending and on the queue (not yet given to getaddrinfo())
|
|
||||||
bool onQueue() { return LoadNative() && isInList(); }
|
|
||||||
|
|
||||||
// When the lookups of this record started and their durations
|
|
||||||
mozilla::TimeStamp mTrrStart;
|
|
||||||
mozilla::TimeStamp mNativeStart;
|
|
||||||
mozilla::TimeDuration mTrrDuration;
|
|
||||||
mozilla::TimeDuration mNativeDuration;
|
|
||||||
|
|
||||||
// TRR or ODoH was used on this record
|
|
||||||
mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
|
|
||||||
uint8_t mTRRSuccess = 0; // number of successful TRR responses
|
|
||||||
uint8_t mNativeSuccess = 0; // number of native lookup responses
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
|
|
||||||
// true if this record is being resolved "natively", which means that
|
|
||||||
// it is either on the pending queue or owned by one of the worker threads.
|
|
||||||
(uint16_t, Native, 1),
|
|
||||||
(uint16_t, NativeUsed, 1),
|
|
||||||
// true if off queue and contributing to mActiveAnyThreadCount
|
|
||||||
(uint16_t, UsingAnyThread, 1),
|
|
||||||
(uint16_t, GetTtl, 1),
|
|
||||||
(uint16_t, ResolveAgain, 1)
|
|
||||||
))
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// The number of times ReportUnusable() has been called in the record's
|
|
||||||
// lifetime.
|
|
||||||
uint32_t mUnusableCount = 0;
|
|
||||||
|
|
||||||
// a list of addresses associated with this record that have been reported
|
|
||||||
// as unusable. the list is kept as a set of strings to make it independent
|
|
||||||
// of gencnt.
|
|
||||||
nsTArray<nsCString> mUnusableItems;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
|
|
||||||
|
|
||||||
// 77b786a7-04be-44f2-987c-ab8aa96676e0
|
|
||||||
#define TYPEHOSTRECORD_IID \
|
|
||||||
{ \
|
|
||||||
0x77b786a7, 0x04be, 0x44f2, { \
|
|
||||||
0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
class TypeHostRecord final : public nsHostRecord,
|
|
||||||
public nsIDNSTXTRecord,
|
|
||||||
public nsIDNSHTTPSSVCRecord,
|
|
||||||
public mozilla::net::DNSHTTPSSVCRecordBase {
|
|
||||||
public:
|
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_NSIDNSTXTRECORD
|
|
||||||
NS_DECL_NSIDNSHTTPSSVCRECORD
|
|
||||||
|
|
||||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
|
|
||||||
uint32_t GetType();
|
|
||||||
mozilla::net::TypeRecordResultType GetResults();
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class nsHostResolver;
|
|
||||||
friend class mozilla::net::TRRQuery;
|
|
||||||
|
|
||||||
explicit TypeHostRecord(const nsHostKey& key);
|
|
||||||
~TypeHostRecord();
|
|
||||||
|
|
||||||
// Checks if the record is usable (not expired and has a value)
|
|
||||||
bool HasUsableResultInternal(const mozilla::TimeStamp& now,
|
|
||||||
uint16_t queryFlags) const override;
|
|
||||||
bool RefreshForNegativeResponse() const override;
|
|
||||||
|
|
||||||
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
|
|
||||||
mozilla::Mutex mResultsLock{"TypeHostRecord.mResultsLock"};
|
|
||||||
|
|
||||||
// When the lookups of this record started (for telemetry).
|
|
||||||
mozilla::TimeStamp mStart;
|
|
||||||
bool mAllRecordsExcluded = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to notify listeners when a ResolveHost operation is
|
|
||||||
* complete. Classes that derive it must implement threadsafe nsISupports
|
|
||||||
* to be able to use RefPtr with this class.
|
|
||||||
*/
|
|
||||||
class nsResolveHostCallback
|
|
||||||
: public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>,
|
|
||||||
public nsISupports {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* OnResolveHostComplete
|
|
||||||
*
|
|
||||||
* this function is called to complete a host lookup initiated by
|
|
||||||
* nsHostResolver::ResolveHost. it may be invoked recursively from
|
|
||||||
* ResolveHost or on an unspecified background thread.
|
|
||||||
*
|
|
||||||
* NOTE: it is the responsibility of the implementor of this method
|
|
||||||
* to handle the callback in a thread safe manner.
|
|
||||||
*
|
|
||||||
* @param resolver
|
|
||||||
* nsHostResolver object associated with this result
|
|
||||||
* @param record
|
|
||||||
* the host record containing the results of the lookup
|
|
||||||
* @param status
|
|
||||||
* if successful, |record| contains non-null results
|
|
||||||
*/
|
|
||||||
virtual void OnResolveHostComplete(nsHostResolver* resolver,
|
|
||||||
nsHostRecord* record, nsresult status) = 0;
|
|
||||||
/**
|
|
||||||
* EqualsAsyncListener
|
|
||||||
*
|
|
||||||
* Determines if the listener argument matches the listener member var.
|
|
||||||
* For subclasses not implementing a member listener, should return false.
|
|
||||||
* For subclasses having a member listener, the function should check if
|
|
||||||
* they are the same. Used for cases where a pointer to an object
|
|
||||||
* implementing nsResolveHostCallback is unknown, but a pointer to
|
|
||||||
* the original listener is known.
|
|
||||||
*
|
|
||||||
* @param aListener
|
|
||||||
* nsIDNSListener object associated with the original request
|
|
||||||
*/
|
|
||||||
virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0;
|
|
||||||
|
|
||||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~nsResolveHostCallback() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AHostResolver {
|
class AHostResolver {
|
||||||
public:
|
public:
|
||||||
AHostResolver() = default;
|
AHostResolver() = default;
|
||||||
@@ -506,8 +171,8 @@ class nsHostResolver : public nsISupports, public AHostResolver {
|
|||||||
enum {
|
enum {
|
||||||
RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
|
RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
|
||||||
RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
|
RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
|
||||||
RES_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
|
RES_PRIORITY_MEDIUM = nsHostRecord::DNS_PRIORITY_MEDIUM,
|
||||||
RES_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
|
RES_PRIORITY_LOW = nsHostRecord::DNS_PRIORITY_LOW,
|
||||||
RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
|
RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
|
||||||
// RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
|
// RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
|
||||||
RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,
|
RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ avoid-blacklist-and-whitelist:
|
|||||||
- netwerk/base/nsIOService.h
|
- netwerk/base/nsIOService.h
|
||||||
- netwerk/base/nsURLHelper.cpp
|
- netwerk/base/nsURLHelper.cpp
|
||||||
- netwerk/cookie/CookieCommons.h
|
- netwerk/cookie/CookieCommons.h
|
||||||
|
- netwerk/dns/nsHostRecord.cpp
|
||||||
- netwerk/dns/nsHostResolver.cpp
|
- netwerk/dns/nsHostResolver.cpp
|
||||||
- netwerk/dns/nsIDNService.cpp
|
- netwerk/dns/nsIDNService.cpp
|
||||||
- netwerk/dns/nsIDNService.h
|
- netwerk/dns/nsIDNService.h
|
||||||
|
|||||||
Reference in New Issue
Block a user