1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsDNSService2.h"
8 #include "nsIDNSRecord.h"
9 #include "nsIDNSListener.h"
10 #include "nsIDNSByTypeRecord.h"
11 #include "nsICancelable.h"
12 #include "nsIPrefBranch.h"
13 #include "nsIOService.h"
14 #include "nsIXPConnect.h"
15 #include "nsProxyRelease.h"
16 #include "nsReadableUtils.h"
21 #include "nsDNSPrefetch.h"
22 #include "nsThreadUtils.h"
23 #include "nsIProtocolProxyService.h"
24 #include "nsIObliviousHttp.h"
29 #include "nsCharSeparatedTokenizer.h"
30 #include "nsNetAddr.h"
31 #include "nsProxyRelease.h"
32 #include "nsQueryObject.h"
33 #include "nsIObserverService.h"
34 #include "nsINetworkLinkService.h"
35 #include "DNSAdditionalInfo.h"
36 #include "TRRService.h"
38 #include "mozilla/Attributes.h"
39 #include "mozilla/ClearOnShutdown.h"
40 #include "mozilla/net/NeckoCommon.h"
41 #include "mozilla/net/ChildDNSService.h"
42 #include "mozilla/net/DNSListenerProxy.h"
43 #include "mozilla/Services.h"
44 #include "mozilla/StaticPrefs_network.h"
45 #include "mozilla/StaticPtr.h"
46 #include "mozilla/SyncRunnable.h"
47 #include "mozilla/TextUtils.h"
48 #include "mozilla/Utf8.h"
50 using namespace mozilla
;
51 using namespace mozilla::net
;
53 static const char kPrefDnsCacheEntries
[] = "network.dnsCacheEntries";
54 static const char kPrefDnsCacheExpiration
[] = "network.dnsCacheExpiration";
55 static const char kPrefDnsCacheGrace
[] =
56 "network.dnsCacheExpirationGracePeriod";
57 static const char kPrefIPv4OnlyDomains
[] = "network.dns.ipv4OnlyDomains";
58 static const char kPrefBlockDotOnion
[] = "network.dns.blockDotOnion";
59 static const char kPrefDnsLocalDomains
[] = "network.dns.localDomains";
60 static const char kPrefDnsForceResolve
[] = "network.dns.forceResolve";
61 static const char kPrefDnsOfflineLocalhost
[] = "network.dns.offline-localhost";
62 static const char kPrefDnsNotifyResolution
[] = "network.dns.notifyResolution";
64 //-----------------------------------------------------------------------------
66 class nsDNSRecord
: public nsIDNSAddrRecord
{
68 NS_DECL_THREADSAFE_ISUPPORTS
70 NS_DECL_NSIDNSADDRRECORD
72 explicit nsDNSRecord(nsHostRecord
* hostRecord
) {
73 mHostRecord
= do_QueryObject(hostRecord
);
77 virtual ~nsDNSRecord() = default;
79 RefPtr
<AddrHostRecord
> mHostRecord
;
80 // Since mIter is holding a weak reference to the NetAddr array we must
81 // make sure it is not released. So we also keep a RefPtr to the AddrInfo
82 // which is immutable.
83 RefPtr
<AddrInfo
> mAddrInfo
;
84 nsTArray
<NetAddr
>::const_iterator mIter
;
85 const NetAddr
* iter() {
86 if (!mIter
.GetArray()) {
89 if (mIter
.GetArray()->end() == mIter
) {
95 int mIterGenCnt
= -1; // the generation count of
96 // mHostRecord->addr_info when we
101 NS_IMPL_ISUPPORTS(nsDNSRecord
, nsIDNSRecord
, nsIDNSAddrRecord
)
104 nsDNSRecord::GetCanonicalName(nsACString
& result
) {
105 // this method should only be called if we have a CNAME
106 NS_ENSURE_TRUE(mHostRecord
->flags
& nsHostResolver::RES_CANON_NAME
,
107 NS_ERROR_NOT_AVAILABLE
);
109 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
111 // if the record is for an IP address literal, then the canonical
112 // host name is the IP address literal.
113 if (!mHostRecord
->addr_info
) {
114 result
= mHostRecord
->host
;
118 if (mHostRecord
->addr_info
->CanonicalHostname().IsEmpty()) {
119 result
= mHostRecord
->addr_info
->Hostname();
121 result
= mHostRecord
->addr_info
->CanonicalHostname();
127 nsDNSRecord::IsTRR(bool* retval
) {
128 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
129 if (mHostRecord
->addr_info
) {
130 *retval
= mHostRecord
->addr_info
->IsTRR();
138 nsDNSRecord::ResolvedInSocketProcess(bool* retval
) {
144 nsDNSRecord::GetTrrFetchDuration(double* aTime
) {
145 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
146 if (mHostRecord
->addr_info
&& mHostRecord
->addr_info
->IsTRR()) {
147 *aTime
= mHostRecord
->addr_info
->GetTrrFetchDuration();
155 nsDNSRecord::GetTrrFetchDurationNetworkOnly(double* aTime
) {
156 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
157 if (mHostRecord
->addr_info
&& mHostRecord
->addr_info
->IsTRR()) {
158 *aTime
= mHostRecord
->addr_info
->GetTrrFetchDurationNetworkOnly();
166 nsDNSRecord::GetNextAddr(uint16_t port
, NetAddr
* addr
) {
168 return NS_ERROR_NOT_AVAILABLE
;
171 mHostRecord
->addr_info_lock
.Lock();
172 if (mHostRecord
->addr_info
) {
173 if (mIterGenCnt
!= mHostRecord
->addr_info_gencnt
) {
174 // mHostRecord->addr_info has changed, restart the iteration.
175 mIter
= nsTArray
<NetAddr
>::const_iterator();
176 mIterGenCnt
= mHostRecord
->addr_info_gencnt
;
177 // Make sure to hold a RefPtr to the AddrInfo so we can iterate through
178 // the NetAddr array.
179 mAddrInfo
= mHostRecord
->addr_info
;
182 bool startedFresh
= !iter();
186 mIter
= mAddrInfo
->Addresses().begin();
190 } while (iter() && mHostRecord
->Blocklisted(iter()));
192 if (!iter() && startedFresh
) {
193 // If everything was blocklisted we want to reset the blocklist (and
194 // likely relearn it) and return the first address. That is better
196 mHostRecord
->ResetBlocklist();
197 mIter
= mAddrInfo
->Addresses().begin();
204 mHostRecord
->addr_info_lock
.Unlock();
208 mIter
= nsTArray
<NetAddr
>::const_iterator();
211 return NS_ERROR_NOT_AVAILABLE
;
214 mHostRecord
->addr_info_lock
.Unlock();
216 if (!mHostRecord
->addr
) {
217 // Both mHostRecord->addr_info and mHostRecord->addr are null.
218 // This can happen if mHostRecord->addr_info expired and the
219 // attempt to reresolve it failed.
220 return NS_ERROR_NOT_AVAILABLE
;
222 memcpy(addr
, mHostRecord
->addr
.get(), sizeof(NetAddr
));
228 if (addr
->raw
.family
== AF_INET
) {
229 addr
->inet
.port
= port
;
230 } else if (addr
->raw
.family
== AF_INET6
) {
231 addr
->inet6
.port
= port
;
238 nsDNSRecord::GetAddresses(nsTArray
<NetAddr
>& aAddressArray
) {
240 return NS_ERROR_NOT_AVAILABLE
;
243 mHostRecord
->addr_info_lock
.Lock();
244 if (mHostRecord
->addr_info
) {
245 for (const auto& address
: mHostRecord
->addr_info
->Addresses()) {
246 if (mHostRecord
->Blocklisted(&address
)) {
249 NetAddr
* addr
= aAddressArray
.AppendElement(address
);
250 if (addr
->raw
.family
== AF_INET
) {
252 } else if (addr
->raw
.family
== AF_INET6
) {
253 addr
->inet6
.port
= 0;
256 mHostRecord
->addr_info_lock
.Unlock();
258 mHostRecord
->addr_info_lock
.Unlock();
260 if (!mHostRecord
->addr
) {
261 return NS_ERROR_NOT_AVAILABLE
;
263 NetAddr
* addr
= aAddressArray
.AppendElement(NetAddr());
264 memcpy(addr
, mHostRecord
->addr
.get(), sizeof(NetAddr
));
265 if (addr
->raw
.family
== AF_INET
) {
267 } else if (addr
->raw
.family
== AF_INET6
) {
268 addr
->inet6
.port
= 0;
275 nsDNSRecord::GetScriptableNextAddr(uint16_t port
, nsINetAddr
** result
) {
277 nsresult rv
= GetNextAddr(port
, &addr
);
282 RefPtr
<nsNetAddr
> netaddr
= new nsNetAddr(&addr
);
283 netaddr
.forget(result
);
289 nsDNSRecord::GetNextAddrAsString(nsACString
& result
) {
291 nsresult rv
= GetNextAddr(0, &addr
);
296 char buf
[kIPv6CStrBufSize
];
297 if (addr
.ToStringBuffer(buf
, sizeof(buf
))) {
301 NS_ERROR("NetAddrToString failed unexpectedly");
302 return NS_ERROR_FAILURE
; // conversion failed for some reason
306 nsDNSRecord::HasMore(bool* result
) {
312 nsTArray
<NetAddr
>::const_iterator iterCopy
= mIter
;
313 int iterGenCntCopy
= mIterGenCnt
;
316 *result
= NS_SUCCEEDED(GetNextAddr(0, &addr
));
319 mIterGenCnt
= iterGenCntCopy
;
326 nsDNSRecord::Rewind() {
327 mIter
= nsTArray
<NetAddr
>::const_iterator();
334 nsDNSRecord::ReportUnusable(uint16_t aPort
) {
335 // right now we don't use the port in the blocklist
337 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
339 // Check that we are using a real addr_info (as opposed to a single
340 // constant address), and that the generation count is valid. Otherwise,
341 // ignore the report.
343 if (mHostRecord
->addr_info
&& mIterGenCnt
== mHostRecord
->addr_info_gencnt
&&
345 mHostRecord
->ReportUnusable(iter());
352 nsDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode
* aMode
) {
353 *aMode
= mHostRecord
->EffectiveTRRMode();
357 NS_IMETHODIMP
nsDNSRecord::GetTrrSkipReason(
358 nsITRRSkipReason::value
* aTrrSkipReason
) {
359 *aTrrSkipReason
= mHostRecord
->TrrSkipReason();
364 nsDNSRecord::GetTtl(uint32_t* aTtl
) { return mHostRecord
->GetTtl(aTtl
); }
366 class nsDNSByTypeRecord
: public nsIDNSByTypeRecord
,
367 public nsIDNSTXTRecord
,
368 public nsIDNSHTTPSSVCRecord
{
370 NS_DECL_THREADSAFE_ISUPPORTS
372 NS_DECL_NSIDNSBYTYPERECORD
373 NS_DECL_NSIDNSTXTRECORD
374 NS_DECL_NSIDNSHTTPSSVCRECORD
376 explicit nsDNSByTypeRecord(nsHostRecord
* hostRecord
) {
377 mHostRecord
= do_QueryObject(hostRecord
);
381 virtual ~nsDNSByTypeRecord() = default;
382 RefPtr
<TypeHostRecord
> mHostRecord
;
385 NS_IMPL_ISUPPORTS(nsDNSByTypeRecord
, nsIDNSRecord
, nsIDNSByTypeRecord
,
386 nsIDNSTXTRecord
, nsIDNSHTTPSSVCRecord
)
389 nsDNSByTypeRecord::GetType(uint32_t* aType
) {
390 *aType
= mHostRecord
->GetType();
395 nsDNSByTypeRecord::GetRecords(CopyableTArray
<nsCString
>& aRecords
) {
397 return mHostRecord
->GetRecords(aRecords
);
401 nsDNSByTypeRecord::GetRecordsAsOneString(nsACString
& aRecords
) {
403 return mHostRecord
->GetRecordsAsOneString(aRecords
);
407 nsDNSByTypeRecord::GetRecords(nsTArray
<RefPtr
<nsISVCBRecord
>>& aRecords
) {
408 return mHostRecord
->GetRecords(aRecords
);
412 nsDNSByTypeRecord::GetServiceModeRecord(bool aNoHttp2
, bool aNoHttp3
,
413 nsISVCBRecord
** aRecord
) {
414 return mHostRecord
->GetServiceModeRecord(aNoHttp2
, aNoHttp3
, aRecord
);
418 nsDNSByTypeRecord::GetAllRecordsWithEchConfig(
419 bool aNoHttp2
, bool aNoHttp3
, bool* aAllRecordsHaveEchConfig
,
420 bool* aAllRecordsInH3ExcludedList
,
421 nsTArray
<RefPtr
<nsISVCBRecord
>>& aResult
) {
422 return mHostRecord
->GetAllRecordsWithEchConfig(
423 aNoHttp2
, aNoHttp3
, aAllRecordsHaveEchConfig
, aAllRecordsInH3ExcludedList
,
428 nsDNSByTypeRecord::GetHasIPAddresses(bool* aResult
) {
429 return mHostRecord
->GetHasIPAddresses(aResult
);
433 nsDNSByTypeRecord::GetAllRecordsExcluded(bool* aResult
) {
434 return mHostRecord
->GetAllRecordsExcluded(aResult
);
438 nsDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType
* aResults
) {
439 *aResults
= mHostRecord
->GetResults();
444 nsDNSByTypeRecord::GetTtl(uint32_t* aTtl
) { return mHostRecord
->GetTtl(aTtl
); }
446 //-----------------------------------------------------------------------------
448 class nsDNSAsyncRequest final
: public nsResolveHostCallback
,
449 public nsICancelable
{
451 NS_DECL_THREADSAFE_ISUPPORTS
452 NS_DECL_NSICANCELABLE
454 nsDNSAsyncRequest(nsHostResolver
* res
, const nsACString
& host
,
455 const nsACString
& trrServer
, uint16_t type
,
456 const OriginAttributes
& attrs
, nsIDNSListener
* listener
,
457 nsIDNSService::DNSFlags flags
, uint16_t af
)
460 mTrrServer(trrServer
),
462 mOriginAttributes(attrs
),
467 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
468 // Returns TRUE if the DNS listener arg is the same as the member listener
469 // Used in Cancellations to remove DNS requests associated with a
470 // particular hostname and nsIDNSListener
471 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
473 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
475 RefPtr
<nsHostResolver
> mResolver
;
476 nsCString mHost
; // hostname we're resolving
477 nsCString mTrrServer
; // A trr server to be used.
479 const OriginAttributes
480 mOriginAttributes
; // The originAttributes for this resolving
481 nsCOMPtr
<nsIDNSListener
> mListener
;
482 nsIDNSService::DNSFlags mFlags
= nsIDNSService::RESOLVE_DEFAULT_FLAGS
;
486 virtual ~nsDNSAsyncRequest() = default;
489 NS_IMPL_ISUPPORTS(nsDNSAsyncRequest
, nsICancelable
)
491 void nsDNSAsyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
492 nsHostRecord
* hostRecord
,
494 // need to have an owning ref when we issue the callback to enable
495 // the caller to be able to addref/release multiple times without
496 // destroying the record prematurely.
497 nsCOMPtr
<nsIDNSRecord
> rec
;
498 if (NS_SUCCEEDED(status
) ||
499 mFlags
& nsIDNSService::RESOLVE_WANT_RECORD_ON_ERROR
) {
500 MOZ_ASSERT(hostRecord
, "no host record");
501 if (hostRecord
->type
!= nsDNSService::RESOLVE_TYPE_DEFAULT
) {
502 rec
= new nsDNSByTypeRecord(hostRecord
);
504 rec
= new nsDNSRecord(hostRecord
);
508 mListener
->OnLookupComplete(this, rec
, status
);
512 bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
513 uintptr_t originalListenerAddr
= reinterpret_cast<uintptr_t>(mListener
.get());
514 RefPtr
<DNSListenerProxy
> wrapper
= do_QueryObject(mListener
);
516 originalListenerAddr
= wrapper
->GetOriginalListenerAddress();
519 uintptr_t listenerAddr
= reinterpret_cast<uintptr_t>(aListener
);
520 return (listenerAddr
== originalListenerAddr
);
523 size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
524 size_t n
= mallocSizeOf(this);
526 // The following fields aren't measured.
527 // - mHost, because it's a non-owning pointer
528 // - mResolver, because it's a non-owning pointer
529 // - mListener, because it's a non-owning pointer
535 nsDNSAsyncRequest::Cancel(nsresult reason
) {
536 NS_ENSURE_ARG(NS_FAILED(reason
));
537 MOZ_DIAGNOSTIC_ASSERT(mResolver
, "mResolver should not be null");
538 mResolver
->DetachCallback(mHost
, mTrrServer
, mType
, mOriginAttributes
, mFlags
,
543 //-----------------------------------------------------------------------------
545 class nsDNSSyncRequest
: public nsResolveHostCallback
{
546 NS_DECL_THREADSAFE_ISUPPORTS
548 explicit nsDNSSyncRequest(PRMonitor
* mon
) : mMonitor(mon
) {}
550 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
551 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
552 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
555 nsresult mStatus
= NS_OK
;
556 RefPtr
<nsHostRecord
> mHostRecord
;
559 virtual ~nsDNSSyncRequest() = default;
561 PRMonitor
* mMonitor
= nullptr;
564 NS_IMPL_ISUPPORTS0(nsDNSSyncRequest
)
566 void nsDNSSyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
567 nsHostRecord
* hostRecord
,
569 // store results, and wake up nsDNSService::Resolve to process results.
570 PR_EnterMonitor(mMonitor
);
573 mHostRecord
= hostRecord
;
575 PR_ExitMonitor(mMonitor
);
578 bool nsDNSSyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
579 // Sync request: no listener to compare
583 size_t nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
584 size_t n
= mallocSizeOf(this);
586 // The following fields aren't measured.
587 // - mHostRecord, because it's a non-owning pointer
589 // Measurement of the following members may be added later if DMD finds it
596 class NotifyDNSResolution
: public Runnable
{
598 explicit NotifyDNSResolution(const nsACString
& aHostname
)
599 : mozilla::Runnable("NotifyDNSResolution"), mHostname(aHostname
) {}
601 NS_IMETHOD
Run() override
{
602 MOZ_ASSERT(NS_IsMainThread());
603 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
605 obs
->NotifyObservers(nullptr, "dns-resolution-request",
606 NS_ConvertUTF8toUTF16(mHostname
).get());
615 //-----------------------------------------------------------------------------
617 static StaticRefPtr
<DNSServiceWrapper
> gDNSServiceWrapper
;
619 NS_IMPL_ISUPPORTS(DNSServiceWrapper
, nsIDNSService
, nsPIDNSService
)
622 already_AddRefed
<nsIDNSService
> DNSServiceWrapper::GetSingleton() {
623 if (!gDNSServiceWrapper
) {
624 gDNSServiceWrapper
= new DNSServiceWrapper();
625 gDNSServiceWrapper
->mDNSServiceInUse
= ChildDNSService::GetSingleton();
626 if (gDNSServiceWrapper
->mDNSServiceInUse
) {
627 ClearOnShutdown(&gDNSServiceWrapper
);
628 nsDNSPrefetch::Initialize(gDNSServiceWrapper
);
630 gDNSServiceWrapper
= nullptr;
634 return do_AddRef(gDNSServiceWrapper
);
638 void DNSServiceWrapper::SwitchToBackupDNSService() {
639 if (!gDNSServiceWrapper
) {
643 gDNSServiceWrapper
->mBackupDNSService
= nsDNSService::GetSingleton();
645 MutexAutoLock
lock(gDNSServiceWrapper
->mLock
);
646 gDNSServiceWrapper
->mBackupDNSService
.swap(
647 gDNSServiceWrapper
->mDNSServiceInUse
);
650 nsIDNSService
* DNSServiceWrapper::DNSService() {
651 MOZ_ASSERT(XRE_IsParentProcess());
653 MutexAutoLock
lock(mLock
);
654 return mDNSServiceInUse
.get();
657 nsPIDNSService
* DNSServiceWrapper::PIDNSService() {
658 MOZ_ASSERT(XRE_IsParentProcess());
660 nsCOMPtr
<nsPIDNSService
> service
= do_QueryInterface(DNSService());
661 return service
.get();
664 //-----------------------------------------------------------------------------
665 NS_IMPL_ISUPPORTS_INHERITED(nsDNSService
, DNSServiceBase
, nsIDNSService
,
666 nsPIDNSService
, nsIMemoryReporter
)
668 /******************************************************************************
670 * singleton instance ctor/dtor methods
671 ******************************************************************************/
672 static StaticRefPtr
<nsDNSService
> gDNSService
;
673 static Atomic
<bool> gInited(false);
675 already_AddRefed
<nsIDNSService
> GetOrInitDNSService() {
677 return nsDNSService::GetXPCOMSingleton();
680 nsCOMPtr
<nsIDNSService
> dns
= nullptr;
681 auto initTask
= [&dns
]() { dns
= do_GetService(NS_DNSSERVICE_CID
); };
682 if (!NS_IsMainThread()) {
683 // Forward to the main thread synchronously.
684 RefPtr
<nsIThread
> mainThread
= do_GetMainThread();
689 SyncRunnable::DispatchToThread(
690 mainThread
, NS_NewRunnableFunction("GetOrInitDNSService", initTask
));
698 already_AddRefed
<nsIDNSService
> nsDNSService::GetXPCOMSingleton() {
699 auto getDNSHelper
= []() -> already_AddRefed
<nsIDNSService
> {
700 if (nsIOService::UseSocketProcess()) {
701 if (XRE_IsSocketProcess()) {
702 return GetSingleton();
705 if (XRE_IsParentProcess()) {
706 return DNSServiceWrapper::GetSingleton();
709 if (XRE_IsContentProcess()) {
710 return ChildDNSService::GetSingleton();
716 if (XRE_IsParentProcess() || XRE_IsSocketProcess()) {
717 return GetSingleton();
720 if (XRE_IsContentProcess()) {
721 return ChildDNSService::GetSingleton();
728 return getDNSHelper();
731 nsCOMPtr
<nsIDNSService
> dns
= getDNSHelper();
738 already_AddRefed
<nsDNSService
> nsDNSService::GetSingleton() {
739 MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess());
742 if (!NS_IsMainThread()) {
745 gDNSService
= new nsDNSService();
746 if (NS_SUCCEEDED(gDNSService
->Init())) {
747 ClearOnShutdown(&gDNSService
);
749 gDNSService
= nullptr;
753 return do_AddRef(gDNSService
);
756 void nsDNSService::ReadPrefs(const char* name
) {
757 DNSServiceBase::ReadPrefs(name
);
761 mResolverPrefsUpdated
= false;
763 // resolver-specific prefs first
764 if (!name
|| !strcmp(name
, kPrefDnsCacheEntries
)) {
765 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheEntries
, &tmpint
))) {
766 if (!name
|| (tmpint
!= mResCacheEntries
)) {
767 mResCacheEntries
= tmpint
;
768 mResolverPrefsUpdated
= true;
772 if (!name
|| !strcmp(name
, kPrefDnsCacheExpiration
)) {
773 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheExpiration
, &tmpint
))) {
774 if (!name
|| (tmpint
!= mResCacheExpiration
)) {
775 mResCacheExpiration
= tmpint
;
776 mResolverPrefsUpdated
= true;
780 if (!name
|| !strcmp(name
, kPrefDnsCacheGrace
)) {
781 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheGrace
, &tmpint
))) {
782 if (!name
|| (tmpint
!= mResCacheGrace
)) {
783 mResCacheGrace
= tmpint
;
784 mResolverPrefsUpdated
= true;
790 if (!name
|| !strcmp(name
, kPrefDnsOfflineLocalhost
)) {
792 Preferences::GetBool(kPrefDnsOfflineLocalhost
, &tmpbool
))) {
793 mOfflineLocalhost
= tmpbool
;
796 if (!name
|| !strcmp(name
, kPrefBlockDotOnion
)) {
797 if (NS_SUCCEEDED(Preferences::GetBool(kPrefBlockDotOnion
, &tmpbool
))) {
798 mBlockDotOnion
= tmpbool
;
801 if (!name
|| !strcmp(name
, kPrefDnsNotifyResolution
)) {
803 Preferences::GetBool(kPrefDnsNotifyResolution
, &tmpbool
))) {
804 mNotifyResolution
= tmpbool
;
807 if (!name
|| !strcmp(name
, kPrefIPv4OnlyDomains
)) {
808 Preferences::GetCString(kPrefIPv4OnlyDomains
, mIPv4OnlyDomains
);
810 if (!name
|| !strcmp(name
, kPrefDnsLocalDomains
)) {
811 nsCString localDomains
;
812 Preferences::GetCString(kPrefDnsLocalDomains
, localDomains
);
813 MutexAutoLock
lock(mLock
);
814 mLocalDomains
.Clear();
815 for (const auto& token
:
816 nsCCharSeparatedTokenizerTemplate
<NS_IsAsciiWhitespace
,
817 nsTokenizerFlags::SeparatorOptional
>(
820 mLocalDomains
.Insert(token
);
823 if (!name
|| !strcmp(name
, kPrefDnsForceResolve
)) {
824 Preferences::GetCString(kPrefDnsForceResolve
, mForceResolve
);
825 mForceResolveOn
= !mForceResolve
.IsEmpty();
830 nsDNSService::Init() {
831 MOZ_ASSERT(!mResolver
);
832 MOZ_ASSERT(NS_IsMainThread());
836 nsCOMPtr
<nsIObserverService
> observerService
=
837 mozilla::services::GetObserverService();
838 if (observerService
) {
839 observerService
->AddObserver(this, "last-pb-context-exited", false);
840 observerService
->AddObserver(this, NS_NETWORK_LINK_TOPIC
, false);
841 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false);
844 RefPtr
<nsHostResolver
> res
;
845 nsresult rv
= nsHostResolver::Create(mResCacheEntries
, mResCacheExpiration
,
846 mResCacheGrace
, getter_AddRefs(res
));
847 if (NS_SUCCEEDED(rv
)) {
848 // now, set all of our member variables while holding the lock
849 MutexAutoLock
lock(mLock
);
853 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
855 // register as prefs observer
856 prefs
->AddObserver(kPrefDnsCacheEntries
, this, false);
857 prefs
->AddObserver(kPrefDnsCacheExpiration
, this, false);
858 prefs
->AddObserver(kPrefDnsCacheGrace
, this, false);
859 prefs
->AddObserver(kPrefIPv4OnlyDomains
, this, false);
860 prefs
->AddObserver(kPrefDnsLocalDomains
, this, false);
861 prefs
->AddObserver(kPrefDnsForceResolve
, this, false);
862 prefs
->AddObserver(kPrefDnsOfflineLocalhost
, this, false);
863 prefs
->AddObserver(kPrefBlockDotOnion
, this, false);
864 prefs
->AddObserver(kPrefDnsNotifyResolution
, this, false);
865 AddPrefObserver(prefs
);
868 nsDNSPrefetch::Initialize(this);
870 RegisterWeakMemoryReporter(this);
872 nsCOMPtr
<nsIObliviousHttpService
> ohttpService(
873 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
875 mTrrService
= new TRRService();
876 if (NS_FAILED(mTrrService
->Init())) {
877 mTrrService
= nullptr;
880 nsCOMPtr
<nsIIDNService
> idn
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
887 nsDNSService::Shutdown() {
888 UnregisterWeakMemoryReporter(this);
890 RefPtr
<nsHostResolver
> res
;
892 MutexAutoLock
lock(mLock
);
893 res
= std::move(mResolver
);
896 // Shutdown outside lock.
900 nsCOMPtr
<nsIObserverService
> observerService
=
901 mozilla::services::GetObserverService();
902 if (observerService
) {
903 observerService
->RemoveObserver(this, NS_NETWORK_LINK_TOPIC
);
904 observerService
->RemoveObserver(this, "last-pb-context-exited");
905 observerService
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
911 bool nsDNSService::GetOffline() const {
912 bool offline
= false;
913 nsCOMPtr
<nsIIOService
> io
= do_GetService(NS_IOSERVICE_CONTRACTID
);
915 io
->GetOffline(&offline
);
921 nsDNSService::GetPrefetchEnabled(bool* outVal
) {
922 MutexAutoLock
lock(mLock
);
923 *outVal
= !mDisablePrefetch
;
928 nsDNSService::SetPrefetchEnabled(bool inVal
) {
929 MutexAutoLock
lock(mLock
);
930 mDisablePrefetch
= !inVal
;
934 already_AddRefed
<nsHostResolver
> nsDNSService::GetResolverLocked() {
935 MutexAutoLock
lock(mLock
);
936 return do_AddRef(mResolver
);
939 nsresult
nsDNSService::PreprocessHostname(bool aLocalDomain
,
940 const nsACString
& aInput
,
944 if (mBlockDotOnion
&& StringEndsWith(aInput
, ".onion"_ns
)) {
945 return NS_ERROR_UNKNOWN_HOST
;
949 aACE
.AssignLiteral("localhost");
953 if (mTrrService
&& mTrrService
->MaybeBootstrap(aInput
, aACE
)) {
957 if (mForceResolveOn
) {
958 MutexAutoLock
lock(mLock
);
959 if (!aInput
.LowerCaseEqualsASCII("localhost") &&
960 !aInput
.LowerCaseEqualsASCII("127.0.0.1")) {
961 aACE
.Assign(mForceResolve
);
966 if (!aIDN
|| IsAscii(aInput
)) {
971 if (!(IsUtf8(aInput
) && NS_SUCCEEDED(aIDN
->ConvertUTF8toACE(aInput
, aACE
)))) {
972 return NS_ERROR_FAILURE
;
977 nsresult
nsDNSService::AsyncResolveInternal(
978 const nsACString
& aHostname
, uint16_t type
, nsIDNSService::DNSFlags flags
,
979 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
,
980 nsIEventTarget
* target_
, const OriginAttributes
& aOriginAttributes
,
981 nsICancelable
** result
) {
982 // grab reference to global host resolver and IDN service. beware
983 // simultaneous shutdown!!
984 RefPtr
<nsHostResolver
> res
;
985 nsCOMPtr
<nsIIDNService
> idn
;
986 nsCOMPtr
<nsIEventTarget
> target
= target_
;
987 nsCOMPtr
<nsIDNSListener
> listener
= aListener
;
988 bool localDomain
= false;
990 MutexAutoLock
lock(mLock
);
992 if (mDisablePrefetch
&& (flags
& RESOLVE_SPECULATE
)) {
993 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
998 localDomain
= mLocalDomains
.Contains(aHostname
);
1001 if (mNotifyResolution
) {
1002 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1006 return NS_ERROR_OFFLINE
;
1009 if ((type
!= RESOLVE_TYPE_DEFAULT
) && (type
!= RESOLVE_TYPE_TXT
) &&
1010 (type
!= RESOLVE_TYPE_HTTPSSVC
)) {
1011 return NS_ERROR_INVALID_ARG
;
1014 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1015 // nsHostResolver returns NS_ERROR_UNKNOWN_HOST for lots of reasons.
1016 // We use a different error code to differentiate this failure and to make
1017 // it clear(er) where this error comes from.
1018 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1022 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1023 if (NS_FAILED(rv
)) {
1028 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1029 flags
|= RESOLVE_OFFLINE
;
1032 // make sure JS callers get notification on the main thread
1033 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedListener
= do_QueryInterface(listener
);
1034 if (wrappedListener
&& !target
) {
1035 target
= GetMainThreadSerialEventTarget();
1039 listener
= new DNSListenerProxy(listener
, target
);
1043 (type
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, flags
);
1045 MOZ_ASSERT(listener
);
1046 RefPtr
<nsDNSAsyncRequest
> req
=
1047 new nsDNSAsyncRequest(res
, hostname
, DNSAdditionalInfo::URL(aInfo
), type
,
1048 aOriginAttributes
, listener
, flags
, af
);
1050 return NS_ERROR_OUT_OF_MEMORY
;
1053 rv
= res
->ResolveHost(req
->mHost
, DNSAdditionalInfo::URL(aInfo
),
1054 DNSAdditionalInfo::Port(aInfo
), type
,
1055 req
->mOriginAttributes
, flags
, af
, req
);
1060 nsresult
nsDNSService::CancelAsyncResolveInternal(
1061 const nsACString
& aHostname
, uint16_t aType
, nsIDNSService::DNSFlags aFlags
,
1062 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
, nsresult aReason
,
1063 const OriginAttributes
& aOriginAttributes
) {
1064 // grab reference to global host resolver and IDN service. beware
1065 // simultaneous shutdown!!
1066 RefPtr
<nsHostResolver
> res
;
1067 nsCOMPtr
<nsIIDNService
> idn
;
1068 bool localDomain
= false;
1070 MutexAutoLock
lock(mLock
);
1072 if (mDisablePrefetch
&& (aFlags
& RESOLVE_SPECULATE
)) {
1073 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1078 localDomain
= mLocalDomains
.Contains(aHostname
);
1081 return NS_ERROR_OFFLINE
;
1085 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1086 if (NS_FAILED(rv
)) {
1091 (aType
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, aFlags
);
1093 res
->CancelAsyncRequest(hostname
, DNSAdditionalInfo::URL(aInfo
), aType
,
1094 aOriginAttributes
, aFlags
, af
, aListener
, aReason
);
1099 nsDNSService::AsyncResolve(const nsACString
& aHostname
,
1100 nsIDNSService::ResolveType aType
,
1101 nsIDNSService::DNSFlags flags
,
1102 nsIDNSAdditionalInfo
* aInfo
,
1103 nsIDNSListener
* listener
, nsIEventTarget
* target_
,
1104 JS::Handle
<JS::Value
> aOriginAttributes
,
1105 JSContext
* aCx
, uint8_t aArgc
,
1106 nsICancelable
** result
) {
1107 OriginAttributes attrs
;
1110 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1111 return NS_ERROR_INVALID_ARG
;
1115 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, listener
, target_
,
1120 nsDNSService::AsyncResolveNative(
1121 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1122 nsIDNSService::DNSFlags flags
, nsIDNSAdditionalInfo
* aInfo
,
1123 nsIDNSListener
* aListener
, nsIEventTarget
* target_
,
1124 const OriginAttributes
& aOriginAttributes
, nsICancelable
** result
) {
1125 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, aListener
,
1126 target_
, aOriginAttributes
, result
);
1130 nsDNSService::NewAdditionalInfo(const nsACString
& aTrrURL
, int32_t aPort
,
1131 nsIDNSAdditionalInfo
** aInfo
) {
1132 RefPtr
<DNSAdditionalInfo
> res
= new DNSAdditionalInfo(aTrrURL
, aPort
);
1138 nsDNSService::CancelAsyncResolve(const nsACString
& aHostname
,
1139 nsIDNSService::ResolveType aType
,
1140 nsIDNSService::DNSFlags aFlags
,
1141 nsIDNSAdditionalInfo
* aInfo
,
1142 nsIDNSListener
* aListener
, nsresult aReason
,
1143 JS::Handle
<JS::Value
> aOriginAttributes
,
1144 JSContext
* aCx
, uint8_t aArgc
) {
1145 OriginAttributes attrs
;
1148 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1149 return NS_ERROR_INVALID_ARG
;
1153 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1158 nsDNSService::CancelAsyncResolveNative(
1159 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1160 nsIDNSService::DNSFlags aFlags
, nsIDNSAdditionalInfo
* aInfo
,
1161 nsIDNSListener
* aListener
, nsresult aReason
,
1162 const OriginAttributes
& aOriginAttributes
) {
1163 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1164 aReason
, aOriginAttributes
);
1168 nsDNSService::Resolve(const nsACString
& aHostname
,
1169 nsIDNSService::DNSFlags flags
,
1170 JS::Handle
<JS::Value
> aOriginAttributes
, JSContext
* aCx
,
1171 uint8_t aArgc
, nsIDNSRecord
** result
) {
1172 OriginAttributes attrs
;
1175 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1176 return NS_ERROR_INVALID_ARG
;
1180 return ResolveNative(aHostname
, flags
, attrs
, result
);
1184 nsDNSService::ResolveNative(const nsACString
& aHostname
,
1185 nsIDNSService::DNSFlags flags
,
1186 const OriginAttributes
& aOriginAttributes
,
1187 nsIDNSRecord
** result
) {
1188 // Synchronous resolution is not available on the main thread.
1189 if (NS_IsMainThread()) {
1190 return NS_ERROR_NOT_AVAILABLE
;
1193 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1196 nsresult
nsDNSService::DeprecatedSyncResolve(
1197 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1198 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1199 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1202 nsresult
nsDNSService::ResolveInternal(
1203 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1204 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1205 // grab reference to global host resolver and IDN service. beware
1206 // simultaneous shutdown!!
1207 RefPtr
<nsHostResolver
> res
;
1208 nsCOMPtr
<nsIIDNService
> idn
;
1209 bool localDomain
= false;
1211 MutexAutoLock
lock(mLock
);
1214 localDomain
= mLocalDomains
.Contains(aHostname
);
1217 if (mNotifyResolution
) {
1218 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1221 NS_ENSURE_TRUE(res
, NS_ERROR_OFFLINE
);
1224 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1225 if (NS_FAILED(rv
)) {
1230 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1231 flags
|= RESOLVE_OFFLINE
;
1234 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1235 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1239 // sync resolve: since the host resolver only works asynchronously, we need
1240 // to use a mutex and a condvar to wait for the result. however, since the
1241 // result may be in the resolvers cache, we might get called back recursively
1242 // on the same thread. so, our mutex needs to be re-entrant. in other words,
1243 // we need to use a monitor! ;-)
1246 PRMonitor
* mon
= PR_NewMonitor();
1248 return NS_ERROR_OUT_OF_MEMORY
;
1251 PR_EnterMonitor(mon
);
1252 RefPtr
<nsDNSSyncRequest
> syncReq
= new nsDNSSyncRequest(mon
);
1254 uint16_t af
= GetAFForLookup(hostname
, flags
);
1256 // TRR uses the main thread for the HTTPS channel to the DoH server.
1257 // If this were to block the main thread while waiting for TRR it would
1258 // likely cause a deadlock. Instead we intentionally choose to not use TRR
1260 if (NS_IsMainThread()) {
1261 flags
|= RESOLVE_DISABLE_TRR
;
1264 rv
= res
->ResolveHost(hostname
, ""_ns
, -1, RESOLVE_TYPE_DEFAULT
,
1265 aOriginAttributes
, flags
, af
, syncReq
);
1266 if (NS_SUCCEEDED(rv
)) {
1268 while (!syncReq
->mDone
) {
1269 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
1272 if (NS_FAILED(syncReq
->mStatus
)) {
1273 rv
= syncReq
->mStatus
;
1275 NS_ASSERTION(syncReq
->mHostRecord
, "no host record");
1276 RefPtr
<nsDNSRecord
> rec
= new nsDNSRecord(syncReq
->mHostRecord
);
1281 PR_ExitMonitor(mon
);
1282 PR_DestroyMonitor(mon
);
1287 nsDNSService::GetMyHostName(nsACString
& result
) {
1289 if (PR_GetSystemInfo(PR_SI_HOSTNAME
, name
, sizeof(name
)) == PR_SUCCESS
) {
1293 return NS_ERROR_FAILURE
;
1297 nsDNSService::Observe(nsISupports
* subject
, const char* topic
,
1298 const char16_t
* data
) {
1299 bool flushCache
= false;
1300 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1302 if (!strcmp(topic
, NS_NETWORK_LINK_TOPIC
)) {
1303 nsAutoCString converted
= NS_ConvertUTF16toUTF8(data
);
1304 if (!strcmp(converted
.get(), NS_NETWORK_LINK_DATA_CHANGED
)) {
1307 } else if (!strcmp(topic
, "last-pb-context-exited")) {
1309 } else if (!strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
1310 ReadPrefs(NS_ConvertUTF16toUTF8(data
).get());
1311 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1312 if (mResolverPrefsUpdated
&& resolver
) {
1313 resolver
->SetCacheLimits(mResCacheEntries
, mResCacheExpiration
,
1316 } else if (!strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
1320 if (flushCache
&& resolver
) {
1321 resolver
->FlushCache(false);
1328 uint16_t nsDNSService::GetAFForLookup(const nsACString
& host
,
1329 nsIDNSService::DNSFlags flags
) {
1330 if (StaticPrefs::network_dns_disableIPv6() ||
1331 (flags
& RESOLVE_DISABLE_IPV6
)) {
1335 MutexAutoLock
lock(mLock
);
1337 uint16_t af
= PR_AF_UNSPEC
;
1339 if (!mIPv4OnlyDomains
.IsEmpty()) {
1340 const char *domain
, *domainEnd
, *end
;
1341 uint32_t hostLen
, domainLen
;
1343 // see if host is in one of the IPv4-only domains
1344 domain
= mIPv4OnlyDomains
.BeginReading();
1345 domainEnd
= mIPv4OnlyDomains
.EndReading();
1347 nsACString::const_iterator hostStart
;
1348 host
.BeginReading(hostStart
);
1349 hostLen
= host
.Length();
1352 // skip any whitespace
1353 while (*domain
== ' ' || *domain
== '\t') {
1357 // find end of this domain in the string
1358 end
= strchr(domain
, ',');
1363 // to see if the hostname is in the domain, check if the domain
1364 // matches the end of the hostname.
1365 domainLen
= end
- domain
;
1366 if (domainLen
&& hostLen
>= domainLen
) {
1367 const char* hostTail
= hostStart
.get() + hostLen
- domainLen
;
1368 if (nsCRT::strncasecmp(domain
, hostTail
, domainLen
) == 0) {
1369 // now, make sure either that the hostname is a direct match or
1370 // that the hostname begins with a dot.
1371 if (hostLen
== domainLen
|| *hostTail
== '.' ||
1372 *(hostTail
- 1) == '.') {
1383 if ((af
!= PR_AF_INET
) && (flags
& RESOLVE_DISABLE_IPV4
)) {
1391 nsDNSService::GetDNSCacheEntries(
1392 nsTArray
<mozilla::net::DNSCacheEntries
>* args
) {
1393 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1394 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1395 resolver
->GetDNSCacheEntries(args
);
1400 nsDNSService::ClearCache(bool aTrrToo
) {
1401 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1402 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1403 resolver
->FlushCache(aTrrToo
);
1408 nsDNSService::ReloadParentalControlEnabled() {
1410 mTrrService
->mParentalControlEnabled
=
1411 TRRService::GetParentalControlEnabledInternal();
1417 nsDNSService::SetDetectedTrrURI(const nsACString
& aURI
) {
1419 mTrrService
->SetDetectedTrrURI(aURI
);
1425 nsDNSService::SetHeuristicDetectionResult(nsITRRSkipReason::value aValue
) {
1427 mTrrService
->SetHeuristicDetectionResult(aValue
);
1433 nsDNSService::GetHeuristicDetectionResult(nsITRRSkipReason::value
* aValue
) {
1435 return NS_ERROR_NOT_AVAILABLE
;
1438 *aValue
= mTrrService
->GetHeuristicDetectionResult();
1443 nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue
,
1444 nsACString
& aName
) {
1445 return mozilla::net::GetTRRSkipReasonName(aValue
, aName
);
1449 nsDNSService::GetCurrentTrrURI(nsACString
& aURI
) {
1451 mTrrService
->GetURI(aURI
);
1457 nsDNSService::GetCurrentTrrMode(nsIDNSService::ResolverMode
* aMode
) {
1458 *aMode
= nsIDNSService::MODE_NATIVEONLY
; // The default mode.
1460 *aMode
= mTrrService
->Mode();
1466 nsDNSService::GetCurrentTrrConfirmationState(uint32_t* aConfirmationState
) {
1467 *aConfirmationState
= uint32_t(TRRService::CONFIRM_OFF
);
1469 *aConfirmationState
= mTrrService
->ConfirmationState();
1475 nsDNSService::GetTrrDomain(nsACString
& aTRRDomain
) {
1476 aTRRDomain
.Truncate();
1479 mTrrService
->GetURI(url
);
1481 nsCOMPtr
<nsIURI
> uri
;
1482 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), url
);
1483 if (NS_FAILED(rv
)) {
1484 // An empty TRR domain in case of invalid URL.
1487 return uri
->GetHost(aTRRDomain
);
1490 nsresult
nsDNSService::GetTRRDomainKey(nsACString
& aTRRDomain
) {
1491 aTRRDomain
= TRRService::ProviderKey();
1495 size_t nsDNSService::SizeOfIncludingThis(
1496 mozilla::MallocSizeOf mallocSizeOf
) const {
1497 // Measurement of the following members may be added later if DMD finds it
1502 size_t n
= mallocSizeOf(this);
1503 n
+= mResolver
? mResolver
->SizeOfIncludingThis(mallocSizeOf
) : 0;
1504 n
+= mIPv4OnlyDomains
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1505 n
+= mLocalDomains
.SizeOfExcludingThis(mallocSizeOf
);
1506 n
+= mFailedSVCDomainNames
.ShallowSizeOfExcludingThis(mallocSizeOf
);
1507 for (const auto& data
: mFailedSVCDomainNames
.Values()) {
1508 n
+= data
->ShallowSizeOfExcludingThis(mallocSizeOf
);
1509 for (const auto& name
: *data
) {
1510 n
+= name
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1516 MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf
)
1519 nsDNSService::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1520 nsISupports
* aData
, bool aAnonymize
) {
1521 MOZ_COLLECT_REPORT("explicit/network/dns-service", KIND_HEAP
, UNITS_BYTES
,
1522 SizeOfIncludingThis(DNSServiceMallocSizeOf
),
1523 "Memory used for the DNS service.");
1529 nsDNSService::ReportFailedSVCDomainName(const nsACString
& aOwnerName
,
1530 const nsACString
& aSVCDomainName
) {
1531 MutexAutoLock
lock(mLock
);
1533 mFailedSVCDomainNames
.GetOrInsertNew(aOwnerName
, 1)
1534 ->AppendElement(aSVCDomainName
);
1539 nsDNSService::IsSVCDomainNameFailed(const nsACString
& aOwnerName
,
1540 const nsACString
& aSVCDomainName
,
1542 NS_ENSURE_ARG(aResult
);
1544 MutexAutoLock
lock(mLock
);
1546 nsTArray
<nsCString
>* failedList
= mFailedSVCDomainNames
.Get(aOwnerName
);
1551 *aResult
= failedList
->Contains(aSVCDomainName
);
1556 nsDNSService::ResetExcludedSVCDomainName(const nsACString
& aOwnerName
) {
1557 MutexAutoLock
lock(mLock
);
1558 mFailedSVCDomainNames
.Remove(aOwnerName
);
1563 nsDNSService::GetLastConfirmationStatus(nsresult
* aConfirmationStatus
) {
1565 return NS_ERROR_NOT_AVAILABLE
;
1567 *aConfirmationStatus
= mTrrService
->LastConfirmationStatus();
1571 NS_IMETHODIMP
nsDNSService::GetLastConfirmationSkipReason(
1572 TRRSkippedReason
* aSkipReason
) {
1574 return NS_ERROR_NOT_AVAILABLE
;
1576 *aSkipReason
= mTrrService
->LastConfirmationSkipReason();
1580 namespace mozilla::net
{
1581 nsresult
GetTRRSkipReasonName(TRRSkippedReason aReason
, nsACString
& aName
) {
1582 static_assert(TRRSkippedReason::TRR_UNSET
== 0);
1583 static_assert(TRRSkippedReason::TRR_OK
== 1);
1584 static_assert(TRRSkippedReason::TRR_NO_GSERVICE
== 2);
1585 static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL
== 3);
1586 static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT
== 4);
1587 static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED
== 5);
1588 static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED
== 6);
1589 static_assert(TRRSkippedReason::TRR_FAILED
== 7);
1590 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
== 8);
1591 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
== 9);
1592 static_assert(TRRSkippedReason::TRR_DISABLED_FLAG
== 10);
1593 static_assert(TRRSkippedReason::TRR_TIMEOUT
== 11);
1594 static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
== 12);
1595 static_assert(TRRSkippedReason::TRR_IS_OFFLINE
== 13);
1596 static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED
== 14);
1597 static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
== 15);
1598 static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
== 16);
1599 static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
== 17);
1600 static_assert(TRRSkippedReason::TRR_SEND_FAILED
== 18);
1601 static_assert(TRRSkippedReason::TRR_NET_RESET
== 19);
1602 static_assert(TRRSkippedReason::TRR_NET_TIMEOUT
== 20);
1603 static_assert(TRRSkippedReason::TRR_NET_REFUSED
== 21);
1604 static_assert(TRRSkippedReason::TRR_NET_INTERRUPT
== 22);
1605 static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
== 23);
1606 static_assert(TRRSkippedReason::TRR_NO_ANSWERS
== 24);
1607 static_assert(TRRSkippedReason::TRR_DECODE_FAILED
== 25);
1608 static_assert(TRRSkippedReason::TRR_EXCLUDED
== 26);
1609 static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
== 27);
1610 static_assert(TRRSkippedReason::TRR_RCODE_FAIL
== 28);
1611 static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY
== 29);
1612 static_assert(TRRSkippedReason::TRR_NXDOMAIN
== 30);
1613 static_assert(TRRSkippedReason::TRR_REQ_CANCELLED
== 31);
1614 static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE
== 32);
1615 static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
== 33);
1616 static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
== 34);
1617 static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED
== 35);
1618 static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED
== 36);
1619 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
==
1621 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
==
1623 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
== 39);
1624 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
== 40);
1625 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
== 41);
1626 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
==
1628 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
==
1630 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
==
1632 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
== 45);
1633 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
== 46);
1634 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
== 47);
1635 static_assert(TRRSkippedReason::TRR_BAD_URL
== 48);
1638 case TRRSkippedReason::TRR_UNSET
:
1639 aName
= "TRR_UNSET"_ns
;
1641 case TRRSkippedReason::TRR_OK
:
1642 aName
= "TRR_OK"_ns
;
1644 case TRRSkippedReason::TRR_NO_GSERVICE
:
1645 aName
= "TRR_NO_GSERVICE"_ns
;
1647 case TRRSkippedReason::TRR_PARENTAL_CONTROL
:
1648 aName
= "TRR_PARENTAL_CONTROL"_ns
;
1650 case TRRSkippedReason::TRR_OFF_EXPLICIT
:
1651 aName
= "TRR_OFF_EXPLICIT"_ns
;
1653 case TRRSkippedReason::TRR_REQ_MODE_DISABLED
:
1654 aName
= "TRR_REQ_MODE_DISABLED"_ns
;
1656 case TRRSkippedReason::TRR_MODE_NOT_ENABLED
:
1657 aName
= "TRR_MODE_NOT_ENABLED"_ns
;
1659 case TRRSkippedReason::TRR_FAILED
:
1660 aName
= "TRR_FAILED"_ns
;
1662 case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
:
1663 aName
= "TRR_MODE_UNHANDLED_DEFAULT"_ns
;
1665 case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
:
1666 aName
= "TRR_MODE_UNHANDLED_DISABLED"_ns
;
1668 case TRRSkippedReason::TRR_DISABLED_FLAG
:
1669 aName
= "TRR_DISABLED_FLAG"_ns
;
1671 case TRRSkippedReason::TRR_TIMEOUT
:
1672 aName
= "TRR_TIMEOUT"_ns
;
1674 case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
:
1675 aName
= "TRR_CHANNEL_DNS_FAIL"_ns
;
1677 case TRRSkippedReason::TRR_IS_OFFLINE
:
1678 aName
= "TRR_IS_OFFLINE"_ns
;
1680 case TRRSkippedReason::TRR_NOT_CONFIRMED
:
1681 aName
= "TRR_NOT_CONFIRMED"_ns
;
1683 case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
:
1684 aName
= "TRR_DID_NOT_MAKE_QUERY"_ns
;
1686 case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
:
1687 aName
= "TRR_UNKNOWN_CHANNEL_FAILURE"_ns
;
1689 case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
:
1690 aName
= "TRR_HOST_BLOCKED_TEMPORARY"_ns
;
1692 case TRRSkippedReason::TRR_SEND_FAILED
:
1693 aName
= "TRR_SEND_FAILED"_ns
;
1695 case TRRSkippedReason::TRR_NET_RESET
:
1696 aName
= "TRR_NET_RESET"_ns
;
1698 case TRRSkippedReason::TRR_NET_TIMEOUT
:
1699 aName
= "TRR_NET_TIMEOUT"_ns
;
1701 case TRRSkippedReason::TRR_NET_REFUSED
:
1702 aName
= "TRR_NET_REFUSED"_ns
;
1704 case TRRSkippedReason::TRR_NET_INTERRUPT
:
1705 aName
= "TRR_NET_INTERRUPT"_ns
;
1707 case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
:
1708 aName
= "TRR_NET_INADEQ_SEQURITY"_ns
;
1710 case TRRSkippedReason::TRR_NO_ANSWERS
:
1711 aName
= "TRR_NO_ANSWERS"_ns
;
1713 case TRRSkippedReason::TRR_DECODE_FAILED
:
1714 aName
= "TRR_DECODE_FAILED"_ns
;
1716 case TRRSkippedReason::TRR_EXCLUDED
:
1717 aName
= "TRR_EXCLUDED"_ns
;
1719 case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
:
1720 aName
= "TRR_SERVER_RESPONSE_ERR"_ns
;
1722 case TRRSkippedReason::TRR_RCODE_FAIL
:
1723 aName
= "TRR_RCODE_FAIL"_ns
;
1725 case TRRSkippedReason::TRR_NO_CONNECTIVITY
:
1726 aName
= "TRR_NO_CONNECTIVITY"_ns
;
1728 case TRRSkippedReason::TRR_NXDOMAIN
:
1729 aName
= "TRR_NXDOMAIN"_ns
;
1731 case TRRSkippedReason::TRR_REQ_CANCELLED
:
1732 aName
= "TRR_REQ_CANCELLED"_ns
;
1734 case TRRSkippedReason::ODOH_KEY_NOT_USABLE
:
1735 aName
= "ODOH_KEY_NOT_USABLE"_ns
;
1737 case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
:
1738 aName
= "ODOH_UPDATE_KEY_FAILED"_ns
;
1740 case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
:
1741 aName
= "ODOH_KEY_NOT_AVAILABLE"_ns
;
1743 case TRRSkippedReason::ODOH_ENCRYPTION_FAILED
:
1744 aName
= "ODOH_ENCRYPTION_FAILED"_ns
;
1746 case TRRSkippedReason::ODOH_DECRYPTION_FAILED
:
1747 aName
= "ODOH_DECRYPTION_FAILED"_ns
;
1749 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
:
1750 aName
= "TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH"_ns
;
1752 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
:
1753 aName
= "TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH"_ns
;
1755 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
:
1756 aName
= "TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY"_ns
;
1758 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
:
1759 aName
= "TRR_HEURISTIC_TRIPPED_CANARY"_ns
;
1761 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
:
1762 aName
= "TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS"_ns
;
1764 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
:
1765 aName
= "TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS"_ns
;
1767 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
:
1768 aName
= "TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS"_ns
;
1770 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
:
1771 aName
= "TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY"_ns
;
1773 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
:
1774 aName
= "TRR_HEURISTIC_TRIPPED_VPN"_ns
;
1776 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
:
1777 aName
= "TRR_HEURISTIC_TRIPPED_PROXY"_ns
;
1779 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
:
1780 aName
= "TRR_HEURISTIC_TRIPPED_NRPT"_ns
;
1782 case TRRSkippedReason::TRR_BAD_URL
:
1783 aName
= "TRR_BAD_URL"_ns
;
1786 MOZ_ASSERT(false, "Unknown value");
1791 } // namespace mozilla::net