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()) {
717 return GetSingleton();
720 if (XRE_IsContentProcess() || XRE_IsSocketProcess()) {
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());
740 MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), XRE_IsParentProcess());
743 if (!NS_IsMainThread()) {
746 gDNSService
= new nsDNSService();
747 if (NS_SUCCEEDED(gDNSService
->Init())) {
748 ClearOnShutdown(&gDNSService
);
750 gDNSService
= nullptr;
754 return do_AddRef(gDNSService
);
757 void nsDNSService::ReadPrefs(const char* name
) {
758 DNSServiceBase::ReadPrefs(name
);
762 mResolverPrefsUpdated
= false;
764 // resolver-specific prefs first
765 if (!name
|| !strcmp(name
, kPrefDnsCacheEntries
)) {
766 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheEntries
, &tmpint
))) {
767 if (!name
|| (tmpint
!= mResCacheEntries
)) {
768 mResCacheEntries
= tmpint
;
769 mResolverPrefsUpdated
= true;
773 if (!name
|| !strcmp(name
, kPrefDnsCacheExpiration
)) {
774 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheExpiration
, &tmpint
))) {
775 if (!name
|| (tmpint
!= mResCacheExpiration
)) {
776 mResCacheExpiration
= tmpint
;
777 mResolverPrefsUpdated
= true;
781 if (!name
|| !strcmp(name
, kPrefDnsCacheGrace
)) {
782 if (NS_SUCCEEDED(Preferences::GetUint(kPrefDnsCacheGrace
, &tmpint
))) {
783 if (!name
|| (tmpint
!= mResCacheGrace
)) {
784 mResCacheGrace
= tmpint
;
785 mResolverPrefsUpdated
= true;
791 if (!name
|| !strcmp(name
, kPrefDnsOfflineLocalhost
)) {
793 Preferences::GetBool(kPrefDnsOfflineLocalhost
, &tmpbool
))) {
794 mOfflineLocalhost
= tmpbool
;
797 if (!name
|| !strcmp(name
, kPrefBlockDotOnion
)) {
798 if (NS_SUCCEEDED(Preferences::GetBool(kPrefBlockDotOnion
, &tmpbool
))) {
799 mBlockDotOnion
= tmpbool
;
802 if (!name
|| !strcmp(name
, kPrefDnsNotifyResolution
)) {
804 Preferences::GetBool(kPrefDnsNotifyResolution
, &tmpbool
))) {
805 mNotifyResolution
= tmpbool
;
808 if (!name
|| !strcmp(name
, kPrefIPv4OnlyDomains
)) {
809 Preferences::GetCString(kPrefIPv4OnlyDomains
, mIPv4OnlyDomains
);
811 if (!name
|| !strcmp(name
, kPrefDnsLocalDomains
)) {
812 nsCString localDomains
;
813 Preferences::GetCString(kPrefDnsLocalDomains
, localDomains
);
814 MutexAutoLock
lock(mLock
);
815 mLocalDomains
.Clear();
816 for (const auto& token
:
817 nsCCharSeparatedTokenizerTemplate
<NS_IsAsciiWhitespace
,
818 nsTokenizerFlags::SeparatorOptional
>(
821 mLocalDomains
.Insert(token
);
824 if (!name
|| !strcmp(name
, kPrefDnsForceResolve
)) {
825 Preferences::GetCString(kPrefDnsForceResolve
, mForceResolve
);
826 mForceResolveOn
= !mForceResolve
.IsEmpty();
831 nsDNSService::Init() {
832 MOZ_ASSERT(!mResolver
);
833 MOZ_ASSERT(NS_IsMainThread());
837 nsCOMPtr
<nsIObserverService
> observerService
=
838 mozilla::services::GetObserverService();
839 if (observerService
) {
840 observerService
->AddObserver(this, "last-pb-context-exited", false);
841 observerService
->AddObserver(this, NS_NETWORK_LINK_TOPIC
, false);
842 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false);
845 RefPtr
<nsHostResolver
> res
;
846 nsresult rv
= nsHostResolver::Create(mResCacheEntries
, mResCacheExpiration
,
847 mResCacheGrace
, getter_AddRefs(res
));
848 if (NS_SUCCEEDED(rv
)) {
849 // now, set all of our member variables while holding the lock
850 MutexAutoLock
lock(mLock
);
854 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
856 // register as prefs observer
857 prefs
->AddObserver(kPrefDnsCacheEntries
, this, false);
858 prefs
->AddObserver(kPrefDnsCacheExpiration
, this, false);
859 prefs
->AddObserver(kPrefDnsCacheGrace
, this, false);
860 prefs
->AddObserver(kPrefIPv4OnlyDomains
, this, false);
861 prefs
->AddObserver(kPrefDnsLocalDomains
, this, false);
862 prefs
->AddObserver(kPrefDnsForceResolve
, this, false);
863 prefs
->AddObserver(kPrefDnsOfflineLocalhost
, this, false);
864 prefs
->AddObserver(kPrefBlockDotOnion
, this, false);
865 prefs
->AddObserver(kPrefDnsNotifyResolution
, this, false);
866 AddPrefObserver(prefs
);
869 nsDNSPrefetch::Initialize(this);
871 RegisterWeakMemoryReporter(this);
873 nsCOMPtr
<nsIObliviousHttpService
> ohttpService(
874 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
876 mTrrService
= new TRRService();
877 if (NS_FAILED(mTrrService
->Init())) {
878 mTrrService
= nullptr;
881 nsCOMPtr
<nsIIDNService
> idn
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
888 nsDNSService::Shutdown() {
889 UnregisterWeakMemoryReporter(this);
891 RefPtr
<nsHostResolver
> res
;
893 MutexAutoLock
lock(mLock
);
894 res
= std::move(mResolver
);
897 // Shutdown outside lock.
901 nsCOMPtr
<nsIObserverService
> observerService
=
902 mozilla::services::GetObserverService();
903 if (observerService
) {
904 observerService
->RemoveObserver(this, NS_NETWORK_LINK_TOPIC
);
905 observerService
->RemoveObserver(this, "last-pb-context-exited");
906 observerService
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
912 bool nsDNSService::GetOffline() const {
913 bool offline
= false;
914 nsCOMPtr
<nsIIOService
> io
= do_GetService(NS_IOSERVICE_CONTRACTID
);
916 io
->GetOffline(&offline
);
922 nsDNSService::GetPrefetchEnabled(bool* outVal
) {
923 MutexAutoLock
lock(mLock
);
924 *outVal
= !mDisablePrefetch
;
929 nsDNSService::SetPrefetchEnabled(bool inVal
) {
930 MutexAutoLock
lock(mLock
);
931 mDisablePrefetch
= !inVal
;
935 already_AddRefed
<nsHostResolver
> nsDNSService::GetResolverLocked() {
936 MutexAutoLock
lock(mLock
);
937 return do_AddRef(mResolver
);
940 nsresult
nsDNSService::PreprocessHostname(bool aLocalDomain
,
941 const nsACString
& aInput
,
945 if (mBlockDotOnion
&& StringEndsWith(aInput
, ".onion"_ns
)) {
946 return NS_ERROR_UNKNOWN_HOST
;
950 aACE
.AssignLiteral("localhost");
954 if (mTrrService
&& mTrrService
->MaybeBootstrap(aInput
, aACE
)) {
958 if (mForceResolveOn
) {
959 MutexAutoLock
lock(mLock
);
960 if (!aInput
.LowerCaseEqualsASCII("localhost") &&
961 !aInput
.LowerCaseEqualsASCII("127.0.0.1")) {
962 aACE
.Assign(mForceResolve
);
967 if (!aIDN
|| IsAscii(aInput
)) {
972 if (!(IsUtf8(aInput
) && NS_SUCCEEDED(aIDN
->ConvertUTF8toACE(aInput
, aACE
)))) {
973 return NS_ERROR_FAILURE
;
978 bool nsDNSService::IsLocalDomain(const nsACString
& aHostname
) const {
979 bool localDomain
= mLocalDomains
.Contains(aHostname
);
980 if (StringEndsWith(aHostname
, "."_ns
)) {
981 localDomain
= localDomain
|| mLocalDomains
.Contains(Substring(
982 aHostname
, 0, aHostname
.Length() - 1));
987 nsresult
nsDNSService::AsyncResolveInternal(
988 const nsACString
& aHostname
, uint16_t type
, nsIDNSService::DNSFlags flags
,
989 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
,
990 nsIEventTarget
* target_
, const OriginAttributes
& aOriginAttributes
,
991 nsICancelable
** result
) {
992 // grab reference to global host resolver and IDN service. beware
993 // simultaneous shutdown!!
994 RefPtr
<nsHostResolver
> res
;
995 nsCOMPtr
<nsIIDNService
> idn
;
996 nsCOMPtr
<nsIEventTarget
> target
= target_
;
997 nsCOMPtr
<nsIDNSListener
> listener
= aListener
;
998 bool localDomain
= false;
1000 MutexAutoLock
lock(mLock
);
1002 if (mDisablePrefetch
&& (flags
& RESOLVE_SPECULATE
)) {
1003 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1009 localDomain
= IsLocalDomain(aHostname
);
1012 if (mNotifyResolution
) {
1013 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1017 return NS_ERROR_OFFLINE
;
1020 if ((type
!= RESOLVE_TYPE_DEFAULT
) && (type
!= RESOLVE_TYPE_TXT
) &&
1021 (type
!= RESOLVE_TYPE_HTTPSSVC
)) {
1022 return NS_ERROR_INVALID_ARG
;
1025 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1026 // nsHostResolver returns NS_ERROR_UNKNOWN_HOST for lots of reasons.
1027 // We use a different error code to differentiate this failure and to make
1028 // it clear(er) where this error comes from.
1029 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1033 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1034 if (NS_FAILED(rv
)) {
1039 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1040 flags
|= RESOLVE_OFFLINE
;
1043 // make sure JS callers get notification on the main thread
1044 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedListener
= do_QueryInterface(listener
);
1045 if (wrappedListener
&& !target
) {
1046 target
= GetMainThreadSerialEventTarget();
1050 listener
= new DNSListenerProxy(listener
, target
);
1054 (type
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, flags
);
1056 MOZ_ASSERT(listener
);
1057 RefPtr
<nsDNSAsyncRequest
> req
=
1058 new nsDNSAsyncRequest(res
, hostname
, DNSAdditionalInfo::URL(aInfo
), type
,
1059 aOriginAttributes
, listener
, flags
, af
);
1061 return NS_ERROR_OUT_OF_MEMORY
;
1064 rv
= res
->ResolveHost(req
->mHost
, DNSAdditionalInfo::URL(aInfo
),
1065 DNSAdditionalInfo::Port(aInfo
), type
,
1066 req
->mOriginAttributes
, flags
, af
, req
);
1071 nsresult
nsDNSService::CancelAsyncResolveInternal(
1072 const nsACString
& aHostname
, uint16_t aType
, nsIDNSService::DNSFlags aFlags
,
1073 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
, nsresult aReason
,
1074 const OriginAttributes
& aOriginAttributes
) {
1075 // grab reference to global host resolver and IDN service. beware
1076 // simultaneous shutdown!!
1077 RefPtr
<nsHostResolver
> res
;
1078 nsCOMPtr
<nsIIDNService
> idn
;
1079 bool localDomain
= false;
1081 MutexAutoLock
lock(mLock
);
1083 if (mDisablePrefetch
&& (aFlags
& RESOLVE_SPECULATE
)) {
1084 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1089 localDomain
= IsLocalDomain(aHostname
);
1092 return NS_ERROR_OFFLINE
;
1096 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1097 if (NS_FAILED(rv
)) {
1102 (aType
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, aFlags
);
1104 res
->CancelAsyncRequest(hostname
, DNSAdditionalInfo::URL(aInfo
), aType
,
1105 aOriginAttributes
, aFlags
, af
, aListener
, aReason
);
1110 nsDNSService::AsyncResolve(const nsACString
& aHostname
,
1111 nsIDNSService::ResolveType aType
,
1112 nsIDNSService::DNSFlags flags
,
1113 nsIDNSAdditionalInfo
* aInfo
,
1114 nsIDNSListener
* listener
, nsIEventTarget
* target_
,
1115 JS::Handle
<JS::Value
> aOriginAttributes
,
1116 JSContext
* aCx
, uint8_t aArgc
,
1117 nsICancelable
** result
) {
1118 OriginAttributes attrs
;
1121 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1122 return NS_ERROR_INVALID_ARG
;
1126 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, listener
, target_
,
1131 nsDNSService::AsyncResolveNative(
1132 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1133 nsIDNSService::DNSFlags flags
, nsIDNSAdditionalInfo
* aInfo
,
1134 nsIDNSListener
* aListener
, nsIEventTarget
* target_
,
1135 const OriginAttributes
& aOriginAttributes
, nsICancelable
** result
) {
1136 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, aListener
,
1137 target_
, aOriginAttributes
, result
);
1141 nsDNSService::NewAdditionalInfo(const nsACString
& aTrrURL
, int32_t aPort
,
1142 nsIDNSAdditionalInfo
** aInfo
) {
1143 RefPtr
<DNSAdditionalInfo
> res
= new DNSAdditionalInfo(aTrrURL
, aPort
);
1149 nsDNSService::CancelAsyncResolve(const nsACString
& aHostname
,
1150 nsIDNSService::ResolveType aType
,
1151 nsIDNSService::DNSFlags aFlags
,
1152 nsIDNSAdditionalInfo
* aInfo
,
1153 nsIDNSListener
* aListener
, nsresult aReason
,
1154 JS::Handle
<JS::Value
> aOriginAttributes
,
1155 JSContext
* aCx
, uint8_t aArgc
) {
1156 OriginAttributes attrs
;
1159 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1160 return NS_ERROR_INVALID_ARG
;
1164 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1169 nsDNSService::CancelAsyncResolveNative(
1170 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1171 nsIDNSService::DNSFlags aFlags
, nsIDNSAdditionalInfo
* aInfo
,
1172 nsIDNSListener
* aListener
, nsresult aReason
,
1173 const OriginAttributes
& aOriginAttributes
) {
1174 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1175 aReason
, aOriginAttributes
);
1179 nsDNSService::Resolve(const nsACString
& aHostname
,
1180 nsIDNSService::DNSFlags flags
,
1181 JS::Handle
<JS::Value
> aOriginAttributes
, JSContext
* aCx
,
1182 uint8_t aArgc
, nsIDNSRecord
** result
) {
1183 OriginAttributes attrs
;
1186 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1187 return NS_ERROR_INVALID_ARG
;
1191 return ResolveNative(aHostname
, flags
, attrs
, result
);
1195 nsDNSService::ResolveNative(const nsACString
& aHostname
,
1196 nsIDNSService::DNSFlags flags
,
1197 const OriginAttributes
& aOriginAttributes
,
1198 nsIDNSRecord
** result
) {
1199 // Synchronous resolution is not available on the main thread.
1200 if (NS_IsMainThread()) {
1201 return NS_ERROR_NOT_AVAILABLE
;
1204 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1207 nsresult
nsDNSService::DeprecatedSyncResolve(
1208 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1209 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1210 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1213 nsresult
nsDNSService::ResolveInternal(
1214 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1215 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1216 // grab reference to global host resolver and IDN service. beware
1217 // simultaneous shutdown!!
1218 RefPtr
<nsHostResolver
> res
;
1219 nsCOMPtr
<nsIIDNService
> idn
;
1220 bool localDomain
= false;
1222 MutexAutoLock
lock(mLock
);
1225 localDomain
= IsLocalDomain(aHostname
);
1228 if (mNotifyResolution
) {
1229 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1232 NS_ENSURE_TRUE(res
, NS_ERROR_OFFLINE
);
1235 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1236 if (NS_FAILED(rv
)) {
1241 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1242 flags
|= RESOLVE_OFFLINE
;
1245 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1246 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1250 // sync resolve: since the host resolver only works asynchronously, we need
1251 // to use a mutex and a condvar to wait for the result. however, since the
1252 // result may be in the resolvers cache, we might get called back recursively
1253 // on the same thread. so, our mutex needs to be re-entrant. in other words,
1254 // we need to use a monitor! ;-)
1257 PRMonitor
* mon
= PR_NewMonitor();
1259 return NS_ERROR_OUT_OF_MEMORY
;
1262 PR_EnterMonitor(mon
);
1263 RefPtr
<nsDNSSyncRequest
> syncReq
= new nsDNSSyncRequest(mon
);
1265 uint16_t af
= GetAFForLookup(hostname
, flags
);
1267 // TRR uses the main thread for the HTTPS channel to the DoH server.
1268 // If this were to block the main thread while waiting for TRR it would
1269 // likely cause a deadlock. Instead we intentionally choose to not use TRR
1271 if (NS_IsMainThread()) {
1272 flags
|= RESOLVE_DISABLE_TRR
;
1275 rv
= res
->ResolveHost(hostname
, ""_ns
, -1, RESOLVE_TYPE_DEFAULT
,
1276 aOriginAttributes
, flags
, af
, syncReq
);
1277 if (NS_SUCCEEDED(rv
)) {
1279 while (!syncReq
->mDone
) {
1280 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
1283 if (NS_FAILED(syncReq
->mStatus
)) {
1284 rv
= syncReq
->mStatus
;
1286 NS_ASSERTION(syncReq
->mHostRecord
, "no host record");
1287 RefPtr
<nsDNSRecord
> rec
= new nsDNSRecord(syncReq
->mHostRecord
);
1292 PR_ExitMonitor(mon
);
1293 PR_DestroyMonitor(mon
);
1298 nsDNSService::GetMyHostName(nsACString
& result
) {
1300 if (PR_GetSystemInfo(PR_SI_HOSTNAME
, name
, sizeof(name
)) == PR_SUCCESS
) {
1304 return NS_ERROR_FAILURE
;
1308 nsDNSService::Observe(nsISupports
* subject
, const char* topic
,
1309 const char16_t
* data
) {
1310 bool flushCache
= false;
1311 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1313 if (!strcmp(topic
, NS_NETWORK_LINK_TOPIC
)) {
1314 nsAutoCString converted
= NS_ConvertUTF16toUTF8(data
);
1315 if (!strcmp(converted
.get(), NS_NETWORK_LINK_DATA_CHANGED
)) {
1318 } else if (!strcmp(topic
, "last-pb-context-exited")) {
1320 } else if (!strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
1321 ReadPrefs(NS_ConvertUTF16toUTF8(data
).get());
1322 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1323 if (mResolverPrefsUpdated
&& resolver
) {
1324 resolver
->SetCacheLimits(mResCacheEntries
, mResCacheExpiration
,
1327 } else if (!strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
1331 if (flushCache
&& resolver
) {
1332 resolver
->FlushCache(false);
1339 uint16_t nsDNSService::GetAFForLookup(const nsACString
& host
,
1340 nsIDNSService::DNSFlags flags
) {
1341 if (StaticPrefs::network_dns_disableIPv6() ||
1342 (flags
& RESOLVE_DISABLE_IPV6
)) {
1346 MutexAutoLock
lock(mLock
);
1348 uint16_t af
= PR_AF_UNSPEC
;
1350 if (!mIPv4OnlyDomains
.IsEmpty()) {
1351 const char *domain
, *domainEnd
, *end
;
1352 uint32_t hostLen
, domainLen
;
1354 // see if host is in one of the IPv4-only domains
1355 domain
= mIPv4OnlyDomains
.BeginReading();
1356 domainEnd
= mIPv4OnlyDomains
.EndReading();
1358 nsACString::const_iterator hostStart
;
1359 host
.BeginReading(hostStart
);
1360 hostLen
= host
.Length();
1363 // skip any whitespace
1364 while (*domain
== ' ' || *domain
== '\t') {
1368 // find end of this domain in the string
1369 end
= strchr(domain
, ',');
1374 // to see if the hostname is in the domain, check if the domain
1375 // matches the end of the hostname.
1376 domainLen
= end
- domain
;
1377 if (domainLen
&& hostLen
>= domainLen
) {
1378 const char* hostTail
= hostStart
.get() + hostLen
- domainLen
;
1379 if (nsCRT::strncasecmp(domain
, hostTail
, domainLen
) == 0) {
1380 // now, make sure either that the hostname is a direct match or
1381 // that the hostname begins with a dot.
1382 if (hostLen
== domainLen
|| *hostTail
== '.' ||
1383 *(hostTail
- 1) == '.') {
1394 if ((af
!= PR_AF_INET
) && (flags
& RESOLVE_DISABLE_IPV4
)) {
1402 nsDNSService::GetDNSCacheEntries(
1403 nsTArray
<mozilla::net::DNSCacheEntries
>* args
) {
1404 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1405 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1406 resolver
->GetDNSCacheEntries(args
);
1411 nsDNSService::ClearCache(bool aTrrToo
) {
1412 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1413 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1414 resolver
->FlushCache(aTrrToo
);
1419 nsDNSService::ReloadParentalControlEnabled() {
1421 mTrrService
->mParentalControlEnabled
=
1422 TRRService::GetParentalControlEnabledInternal();
1428 nsDNSService::SetDetectedTrrURI(const nsACString
& aURI
) {
1430 mTrrService
->SetDetectedTrrURI(aURI
);
1436 nsDNSService::SetHeuristicDetectionResult(nsITRRSkipReason::value aValue
) {
1438 mTrrService
->SetHeuristicDetectionResult(aValue
);
1444 nsDNSService::GetHeuristicDetectionResult(nsITRRSkipReason::value
* aValue
) {
1446 return NS_ERROR_NOT_AVAILABLE
;
1449 *aValue
= mTrrService
->GetHeuristicDetectionResult();
1454 nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue
,
1455 nsACString
& aName
) {
1456 return mozilla::net::GetTRRSkipReasonName(aValue
, aName
);
1460 nsDNSService::GetCurrentTrrURI(nsACString
& aURI
) {
1462 mTrrService
->GetURI(aURI
);
1468 nsDNSService::GetCurrentTrrMode(nsIDNSService::ResolverMode
* aMode
) {
1469 *aMode
= nsIDNSService::MODE_NATIVEONLY
; // The default mode.
1471 *aMode
= mTrrService
->Mode();
1477 nsDNSService::GetCurrentTrrConfirmationState(uint32_t* aConfirmationState
) {
1478 *aConfirmationState
= uint32_t(TRRService::CONFIRM_OFF
);
1480 *aConfirmationState
= mTrrService
->ConfirmationState();
1486 nsDNSService::GetTrrDomain(nsACString
& aTRRDomain
) {
1487 aTRRDomain
.Truncate();
1490 mTrrService
->GetURI(url
);
1492 nsCOMPtr
<nsIURI
> uri
;
1493 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), url
);
1494 if (NS_FAILED(rv
)) {
1495 // An empty TRR domain in case of invalid URL.
1498 return uri
->GetHost(aTRRDomain
);
1501 nsresult
nsDNSService::GetTRRDomainKey(nsACString
& aTRRDomain
) {
1502 aTRRDomain
= TRRService::ProviderKey();
1506 size_t nsDNSService::SizeOfIncludingThis(
1507 mozilla::MallocSizeOf mallocSizeOf
) const {
1508 // Measurement of the following members may be added later if DMD finds it
1513 size_t n
= mallocSizeOf(this);
1514 n
+= mResolver
? mResolver
->SizeOfIncludingThis(mallocSizeOf
) : 0;
1515 n
+= mIPv4OnlyDomains
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1516 n
+= mLocalDomains
.SizeOfExcludingThis(mallocSizeOf
);
1517 n
+= mFailedSVCDomainNames
.ShallowSizeOfExcludingThis(mallocSizeOf
);
1518 for (const auto& data
: mFailedSVCDomainNames
.Values()) {
1519 n
+= data
->ShallowSizeOfExcludingThis(mallocSizeOf
);
1520 for (const auto& name
: *data
) {
1521 n
+= name
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1527 MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf
)
1530 nsDNSService::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1531 nsISupports
* aData
, bool aAnonymize
) {
1532 MOZ_COLLECT_REPORT("explicit/network/dns-service", KIND_HEAP
, UNITS_BYTES
,
1533 SizeOfIncludingThis(DNSServiceMallocSizeOf
),
1534 "Memory used for the DNS service.");
1540 nsDNSService::ReportFailedSVCDomainName(const nsACString
& aOwnerName
,
1541 const nsACString
& aSVCDomainName
) {
1542 MutexAutoLock
lock(mLock
);
1544 mFailedSVCDomainNames
.GetOrInsertNew(aOwnerName
, 1)
1545 ->AppendElement(aSVCDomainName
);
1550 nsDNSService::IsSVCDomainNameFailed(const nsACString
& aOwnerName
,
1551 const nsACString
& aSVCDomainName
,
1553 NS_ENSURE_ARG(aResult
);
1555 MutexAutoLock
lock(mLock
);
1557 nsTArray
<nsCString
>* failedList
= mFailedSVCDomainNames
.Get(aOwnerName
);
1562 *aResult
= failedList
->Contains(aSVCDomainName
);
1567 nsDNSService::ResetExcludedSVCDomainName(const nsACString
& aOwnerName
) {
1568 MutexAutoLock
lock(mLock
);
1569 mFailedSVCDomainNames
.Remove(aOwnerName
);
1574 nsDNSService::GetLastConfirmationStatus(nsresult
* aConfirmationStatus
) {
1576 return NS_ERROR_NOT_AVAILABLE
;
1578 *aConfirmationStatus
= mTrrService
->LastConfirmationStatus();
1582 NS_IMETHODIMP
nsDNSService::GetLastConfirmationSkipReason(
1583 TRRSkippedReason
* aSkipReason
) {
1585 return NS_ERROR_NOT_AVAILABLE
;
1587 *aSkipReason
= mTrrService
->LastConfirmationSkipReason();
1591 namespace mozilla::net
{
1592 nsresult
GetTRRSkipReasonName(TRRSkippedReason aReason
, nsACString
& aName
) {
1593 static_assert(TRRSkippedReason::TRR_UNSET
== 0);
1594 static_assert(TRRSkippedReason::TRR_OK
== 1);
1595 static_assert(TRRSkippedReason::TRR_NO_GSERVICE
== 2);
1596 static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL
== 3);
1597 static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT
== 4);
1598 static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED
== 5);
1599 static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED
== 6);
1600 static_assert(TRRSkippedReason::TRR_FAILED
== 7);
1601 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
== 8);
1602 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
== 9);
1603 static_assert(TRRSkippedReason::TRR_DISABLED_FLAG
== 10);
1604 static_assert(TRRSkippedReason::TRR_TIMEOUT
== 11);
1605 static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
== 12);
1606 static_assert(TRRSkippedReason::TRR_IS_OFFLINE
== 13);
1607 static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED
== 14);
1608 static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
== 15);
1609 static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
== 16);
1610 static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
== 17);
1611 static_assert(TRRSkippedReason::TRR_SEND_FAILED
== 18);
1612 static_assert(TRRSkippedReason::TRR_NET_RESET
== 19);
1613 static_assert(TRRSkippedReason::TRR_NET_TIMEOUT
== 20);
1614 static_assert(TRRSkippedReason::TRR_NET_REFUSED
== 21);
1615 static_assert(TRRSkippedReason::TRR_NET_INTERRUPT
== 22);
1616 static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
== 23);
1617 static_assert(TRRSkippedReason::TRR_NO_ANSWERS
== 24);
1618 static_assert(TRRSkippedReason::TRR_DECODE_FAILED
== 25);
1619 static_assert(TRRSkippedReason::TRR_EXCLUDED
== 26);
1620 static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
== 27);
1621 static_assert(TRRSkippedReason::TRR_RCODE_FAIL
== 28);
1622 static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY
== 29);
1623 static_assert(TRRSkippedReason::TRR_NXDOMAIN
== 30);
1624 static_assert(TRRSkippedReason::TRR_REQ_CANCELLED
== 31);
1625 static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE
== 32);
1626 static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
== 33);
1627 static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
== 34);
1628 static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED
== 35);
1629 static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED
== 36);
1630 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
==
1632 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
==
1634 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
== 39);
1635 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
== 40);
1636 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
== 41);
1637 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
==
1639 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
==
1641 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
==
1643 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
== 45);
1644 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
== 46);
1645 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
== 47);
1646 static_assert(TRRSkippedReason::TRR_BAD_URL
== 48);
1649 case TRRSkippedReason::TRR_UNSET
:
1650 aName
= "TRR_UNSET"_ns
;
1652 case TRRSkippedReason::TRR_OK
:
1653 aName
= "TRR_OK"_ns
;
1655 case TRRSkippedReason::TRR_NO_GSERVICE
:
1656 aName
= "TRR_NO_GSERVICE"_ns
;
1658 case TRRSkippedReason::TRR_PARENTAL_CONTROL
:
1659 aName
= "TRR_PARENTAL_CONTROL"_ns
;
1661 case TRRSkippedReason::TRR_OFF_EXPLICIT
:
1662 aName
= "TRR_OFF_EXPLICIT"_ns
;
1664 case TRRSkippedReason::TRR_REQ_MODE_DISABLED
:
1665 aName
= "TRR_REQ_MODE_DISABLED"_ns
;
1667 case TRRSkippedReason::TRR_MODE_NOT_ENABLED
:
1668 aName
= "TRR_MODE_NOT_ENABLED"_ns
;
1670 case TRRSkippedReason::TRR_FAILED
:
1671 aName
= "TRR_FAILED"_ns
;
1673 case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
:
1674 aName
= "TRR_MODE_UNHANDLED_DEFAULT"_ns
;
1676 case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
:
1677 aName
= "TRR_MODE_UNHANDLED_DISABLED"_ns
;
1679 case TRRSkippedReason::TRR_DISABLED_FLAG
:
1680 aName
= "TRR_DISABLED_FLAG"_ns
;
1682 case TRRSkippedReason::TRR_TIMEOUT
:
1683 aName
= "TRR_TIMEOUT"_ns
;
1685 case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
:
1686 aName
= "TRR_CHANNEL_DNS_FAIL"_ns
;
1688 case TRRSkippedReason::TRR_IS_OFFLINE
:
1689 aName
= "TRR_IS_OFFLINE"_ns
;
1691 case TRRSkippedReason::TRR_NOT_CONFIRMED
:
1692 aName
= "TRR_NOT_CONFIRMED"_ns
;
1694 case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
:
1695 aName
= "TRR_DID_NOT_MAKE_QUERY"_ns
;
1697 case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
:
1698 aName
= "TRR_UNKNOWN_CHANNEL_FAILURE"_ns
;
1700 case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
:
1701 aName
= "TRR_HOST_BLOCKED_TEMPORARY"_ns
;
1703 case TRRSkippedReason::TRR_SEND_FAILED
:
1704 aName
= "TRR_SEND_FAILED"_ns
;
1706 case TRRSkippedReason::TRR_NET_RESET
:
1707 aName
= "TRR_NET_RESET"_ns
;
1709 case TRRSkippedReason::TRR_NET_TIMEOUT
:
1710 aName
= "TRR_NET_TIMEOUT"_ns
;
1712 case TRRSkippedReason::TRR_NET_REFUSED
:
1713 aName
= "TRR_NET_REFUSED"_ns
;
1715 case TRRSkippedReason::TRR_NET_INTERRUPT
:
1716 aName
= "TRR_NET_INTERRUPT"_ns
;
1718 case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
:
1719 aName
= "TRR_NET_INADEQ_SEQURITY"_ns
;
1721 case TRRSkippedReason::TRR_NO_ANSWERS
:
1722 aName
= "TRR_NO_ANSWERS"_ns
;
1724 case TRRSkippedReason::TRR_DECODE_FAILED
:
1725 aName
= "TRR_DECODE_FAILED"_ns
;
1727 case TRRSkippedReason::TRR_EXCLUDED
:
1728 aName
= "TRR_EXCLUDED"_ns
;
1730 case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
:
1731 aName
= "TRR_SERVER_RESPONSE_ERR"_ns
;
1733 case TRRSkippedReason::TRR_RCODE_FAIL
:
1734 aName
= "TRR_RCODE_FAIL"_ns
;
1736 case TRRSkippedReason::TRR_NO_CONNECTIVITY
:
1737 aName
= "TRR_NO_CONNECTIVITY"_ns
;
1739 case TRRSkippedReason::TRR_NXDOMAIN
:
1740 aName
= "TRR_NXDOMAIN"_ns
;
1742 case TRRSkippedReason::TRR_REQ_CANCELLED
:
1743 aName
= "TRR_REQ_CANCELLED"_ns
;
1745 case TRRSkippedReason::ODOH_KEY_NOT_USABLE
:
1746 aName
= "ODOH_KEY_NOT_USABLE"_ns
;
1748 case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
:
1749 aName
= "ODOH_UPDATE_KEY_FAILED"_ns
;
1751 case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
:
1752 aName
= "ODOH_KEY_NOT_AVAILABLE"_ns
;
1754 case TRRSkippedReason::ODOH_ENCRYPTION_FAILED
:
1755 aName
= "ODOH_ENCRYPTION_FAILED"_ns
;
1757 case TRRSkippedReason::ODOH_DECRYPTION_FAILED
:
1758 aName
= "ODOH_DECRYPTION_FAILED"_ns
;
1760 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
:
1761 aName
= "TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH"_ns
;
1763 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
:
1764 aName
= "TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH"_ns
;
1766 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
:
1767 aName
= "TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY"_ns
;
1769 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
:
1770 aName
= "TRR_HEURISTIC_TRIPPED_CANARY"_ns
;
1772 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
:
1773 aName
= "TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS"_ns
;
1775 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
:
1776 aName
= "TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS"_ns
;
1778 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
:
1779 aName
= "TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS"_ns
;
1781 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
:
1782 aName
= "TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY"_ns
;
1784 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
:
1785 aName
= "TRR_HEURISTIC_TRIPPED_VPN"_ns
;
1787 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
:
1788 aName
= "TRR_HEURISTIC_TRIPPED_PROXY"_ns
;
1790 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
:
1791 aName
= "TRR_HEURISTIC_TRIPPED_NRPT"_ns
;
1793 case TRRSkippedReason::TRR_BAD_URL
:
1794 aName
= "TRR_BAD_URL"_ns
;
1797 MOZ_ASSERT(false, "Unknown value");
1802 } // namespace mozilla::net