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 kPrefDisableIPv6
[] = "network.dns.disableIPv6";
59 static const char kPrefBlockDotOnion
[] = "network.dns.blockDotOnion";
60 static const char kPrefDnsLocalDomains
[] = "network.dns.localDomains";
61 static const char kPrefDnsForceResolve
[] = "network.dns.forceResolve";
62 static const char kPrefDnsOfflineLocalhost
[] = "network.dns.offline-localhost";
63 static const char kPrefDnsNotifyResolution
[] = "network.dns.notifyResolution";
65 //-----------------------------------------------------------------------------
67 class nsDNSRecord
: public nsIDNSAddrRecord
{
69 NS_DECL_THREADSAFE_ISUPPORTS
71 NS_DECL_NSIDNSADDRRECORD
73 explicit nsDNSRecord(nsHostRecord
* hostRecord
) {
74 mHostRecord
= do_QueryObject(hostRecord
);
78 virtual ~nsDNSRecord() = default;
80 RefPtr
<AddrHostRecord
> mHostRecord
;
81 // Since mIter is holding a weak reference to the NetAddr array we must
82 // make sure it is not released. So we also keep a RefPtr to the AddrInfo
83 // which is immutable.
84 RefPtr
<AddrInfo
> mAddrInfo
;
85 nsTArray
<NetAddr
>::const_iterator mIter
;
86 const NetAddr
* iter() {
87 if (!mIter
.GetArray()) {
90 if (mIter
.GetArray()->end() == mIter
) {
96 int mIterGenCnt
= -1; // the generation count of
97 // mHostRecord->addr_info when we
102 NS_IMPL_ISUPPORTS(nsDNSRecord
, nsIDNSRecord
, nsIDNSAddrRecord
)
105 nsDNSRecord::GetCanonicalName(nsACString
& result
) {
106 // this method should only be called if we have a CNAME
107 NS_ENSURE_TRUE(mHostRecord
->flags
& nsHostResolver::RES_CANON_NAME
,
108 NS_ERROR_NOT_AVAILABLE
);
110 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
112 // if the record is for an IP address literal, then the canonical
113 // host name is the IP address literal.
114 if (!mHostRecord
->addr_info
) {
115 result
= mHostRecord
->host
;
119 if (mHostRecord
->addr_info
->CanonicalHostname().IsEmpty()) {
120 result
= mHostRecord
->addr_info
->Hostname();
122 result
= mHostRecord
->addr_info
->CanonicalHostname();
128 nsDNSRecord::IsTRR(bool* retval
) {
129 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
130 if (mHostRecord
->addr_info
) {
131 *retval
= mHostRecord
->addr_info
->IsTRR();
139 nsDNSRecord::ResolvedInSocketProcess(bool* retval
) {
145 nsDNSRecord::GetTrrFetchDuration(double* aTime
) {
146 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
147 if (mHostRecord
->addr_info
&& mHostRecord
->addr_info
->IsTRR()) {
148 *aTime
= mHostRecord
->addr_info
->GetTrrFetchDuration();
156 nsDNSRecord::GetTrrFetchDurationNetworkOnly(double* aTime
) {
157 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
158 if (mHostRecord
->addr_info
&& mHostRecord
->addr_info
->IsTRR()) {
159 *aTime
= mHostRecord
->addr_info
->GetTrrFetchDurationNetworkOnly();
167 nsDNSRecord::GetNextAddr(uint16_t port
, NetAddr
* addr
) {
169 return NS_ERROR_NOT_AVAILABLE
;
172 mHostRecord
->addr_info_lock
.Lock();
173 if (mHostRecord
->addr_info
) {
174 if (mIterGenCnt
!= mHostRecord
->addr_info_gencnt
) {
175 // mHostRecord->addr_info has changed, restart the iteration.
176 mIter
= nsTArray
<NetAddr
>::const_iterator();
177 mIterGenCnt
= mHostRecord
->addr_info_gencnt
;
178 // Make sure to hold a RefPtr to the AddrInfo so we can iterate through
179 // the NetAddr array.
180 mAddrInfo
= mHostRecord
->addr_info
;
183 bool startedFresh
= !iter();
187 mIter
= mAddrInfo
->Addresses().begin();
191 } while (iter() && mHostRecord
->Blocklisted(iter()));
193 if (!iter() && startedFresh
) {
194 // If everything was blocklisted we want to reset the blocklist (and
195 // likely relearn it) and return the first address. That is better
197 mHostRecord
->ResetBlocklist();
198 mIter
= mAddrInfo
->Addresses().begin();
205 mHostRecord
->addr_info_lock
.Unlock();
209 mIter
= nsTArray
<NetAddr
>::const_iterator();
212 return NS_ERROR_NOT_AVAILABLE
;
215 mHostRecord
->addr_info_lock
.Unlock();
217 if (!mHostRecord
->addr
) {
218 // Both mHostRecord->addr_info and mHostRecord->addr are null.
219 // This can happen if mHostRecord->addr_info expired and the
220 // attempt to reresolve it failed.
221 return NS_ERROR_NOT_AVAILABLE
;
223 memcpy(addr
, mHostRecord
->addr
.get(), sizeof(NetAddr
));
229 if (addr
->raw
.family
== AF_INET
) {
230 addr
->inet
.port
= port
;
231 } else if (addr
->raw
.family
== AF_INET6
) {
232 addr
->inet6
.port
= port
;
239 nsDNSRecord::GetAddresses(nsTArray
<NetAddr
>& aAddressArray
) {
241 return NS_ERROR_NOT_AVAILABLE
;
244 mHostRecord
->addr_info_lock
.Lock();
245 if (mHostRecord
->addr_info
) {
246 for (const auto& address
: mHostRecord
->addr_info
->Addresses()) {
247 if (mHostRecord
->Blocklisted(&address
)) {
250 NetAddr
* addr
= aAddressArray
.AppendElement(address
);
251 if (addr
->raw
.family
== AF_INET
) {
253 } else if (addr
->raw
.family
== AF_INET6
) {
254 addr
->inet6
.port
= 0;
257 mHostRecord
->addr_info_lock
.Unlock();
259 mHostRecord
->addr_info_lock
.Unlock();
261 if (!mHostRecord
->addr
) {
262 return NS_ERROR_NOT_AVAILABLE
;
264 NetAddr
* addr
= aAddressArray
.AppendElement(NetAddr());
265 memcpy(addr
, mHostRecord
->addr
.get(), sizeof(NetAddr
));
266 if (addr
->raw
.family
== AF_INET
) {
268 } else if (addr
->raw
.family
== AF_INET6
) {
269 addr
->inet6
.port
= 0;
276 nsDNSRecord::GetScriptableNextAddr(uint16_t port
, nsINetAddr
** result
) {
278 nsresult rv
= GetNextAddr(port
, &addr
);
283 RefPtr
<nsNetAddr
> netaddr
= new nsNetAddr(&addr
);
284 netaddr
.forget(result
);
290 nsDNSRecord::GetNextAddrAsString(nsACString
& result
) {
292 nsresult rv
= GetNextAddr(0, &addr
);
297 char buf
[kIPv6CStrBufSize
];
298 if (addr
.ToStringBuffer(buf
, sizeof(buf
))) {
302 NS_ERROR("NetAddrToString failed unexpectedly");
303 return NS_ERROR_FAILURE
; // conversion failed for some reason
307 nsDNSRecord::HasMore(bool* result
) {
313 nsTArray
<NetAddr
>::const_iterator iterCopy
= mIter
;
314 int iterGenCntCopy
= mIterGenCnt
;
317 *result
= NS_SUCCEEDED(GetNextAddr(0, &addr
));
320 mIterGenCnt
= iterGenCntCopy
;
327 nsDNSRecord::Rewind() {
328 mIter
= nsTArray
<NetAddr
>::const_iterator();
335 nsDNSRecord::ReportUnusable(uint16_t aPort
) {
336 // right now we don't use the port in the blocklist
338 MutexAutoLock
lock(mHostRecord
->addr_info_lock
);
340 // Check that we are using a real addr_info (as opposed to a single
341 // constant address), and that the generation count is valid. Otherwise,
342 // ignore the report.
344 if (mHostRecord
->addr_info
&& mIterGenCnt
== mHostRecord
->addr_info_gencnt
&&
346 mHostRecord
->ReportUnusable(iter());
353 nsDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode
* aMode
) {
354 *aMode
= mHostRecord
->EffectiveTRRMode();
358 NS_IMETHODIMP
nsDNSRecord::GetTrrSkipReason(
359 nsITRRSkipReason::value
* aTrrSkipReason
) {
360 *aTrrSkipReason
= mHostRecord
->TrrSkipReason();
365 nsDNSRecord::GetTtl(uint32_t* aTtl
) { return mHostRecord
->GetTtl(aTtl
); }
367 class nsDNSByTypeRecord
: public nsIDNSByTypeRecord
,
368 public nsIDNSTXTRecord
,
369 public nsIDNSHTTPSSVCRecord
{
371 NS_DECL_THREADSAFE_ISUPPORTS
373 NS_DECL_NSIDNSBYTYPERECORD
374 NS_DECL_NSIDNSTXTRECORD
375 NS_DECL_NSIDNSHTTPSSVCRECORD
377 explicit nsDNSByTypeRecord(nsHostRecord
* hostRecord
) {
378 mHostRecord
= do_QueryObject(hostRecord
);
382 virtual ~nsDNSByTypeRecord() = default;
383 RefPtr
<TypeHostRecord
> mHostRecord
;
386 NS_IMPL_ISUPPORTS(nsDNSByTypeRecord
, nsIDNSRecord
, nsIDNSByTypeRecord
,
387 nsIDNSTXTRecord
, nsIDNSHTTPSSVCRecord
)
390 nsDNSByTypeRecord::GetType(uint32_t* aType
) {
391 *aType
= mHostRecord
->GetType();
396 nsDNSByTypeRecord::GetRecords(CopyableTArray
<nsCString
>& aRecords
) {
398 return mHostRecord
->GetRecords(aRecords
);
402 nsDNSByTypeRecord::GetRecordsAsOneString(nsACString
& aRecords
) {
404 return mHostRecord
->GetRecordsAsOneString(aRecords
);
408 nsDNSByTypeRecord::GetRecords(nsTArray
<RefPtr
<nsISVCBRecord
>>& aRecords
) {
409 return mHostRecord
->GetRecords(aRecords
);
413 nsDNSByTypeRecord::GetServiceModeRecord(bool aNoHttp2
, bool aNoHttp3
,
414 nsISVCBRecord
** aRecord
) {
415 return mHostRecord
->GetServiceModeRecord(aNoHttp2
, aNoHttp3
, aRecord
);
419 nsDNSByTypeRecord::GetAllRecordsWithEchConfig(
420 bool aNoHttp2
, bool aNoHttp3
, bool* aAllRecordsHaveEchConfig
,
421 bool* aAllRecordsInH3ExcludedList
,
422 nsTArray
<RefPtr
<nsISVCBRecord
>>& aResult
) {
423 return mHostRecord
->GetAllRecordsWithEchConfig(
424 aNoHttp2
, aNoHttp3
, aAllRecordsHaveEchConfig
, aAllRecordsInH3ExcludedList
,
429 nsDNSByTypeRecord::GetHasIPAddresses(bool* aResult
) {
430 return mHostRecord
->GetHasIPAddresses(aResult
);
434 nsDNSByTypeRecord::GetAllRecordsExcluded(bool* aResult
) {
435 return mHostRecord
->GetAllRecordsExcluded(aResult
);
439 nsDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType
* aResults
) {
440 *aResults
= mHostRecord
->GetResults();
445 nsDNSByTypeRecord::GetTtl(uint32_t* aTtl
) { return mHostRecord
->GetTtl(aTtl
); }
447 //-----------------------------------------------------------------------------
449 class nsDNSAsyncRequest final
: public nsResolveHostCallback
,
450 public nsICancelable
{
452 NS_DECL_THREADSAFE_ISUPPORTS
453 NS_DECL_NSICANCELABLE
455 nsDNSAsyncRequest(nsHostResolver
* res
, const nsACString
& host
,
456 const nsACString
& trrServer
, uint16_t type
,
457 const OriginAttributes
& attrs
, nsIDNSListener
* listener
,
458 nsIDNSService::DNSFlags flags
, uint16_t af
)
461 mTrrServer(trrServer
),
463 mOriginAttributes(attrs
),
468 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
469 // Returns TRUE if the DNS listener arg is the same as the member listener
470 // Used in Cancellations to remove DNS requests associated with a
471 // particular hostname and nsIDNSListener
472 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
474 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
476 RefPtr
<nsHostResolver
> mResolver
;
477 nsCString mHost
; // hostname we're resolving
478 nsCString mTrrServer
; // A trr server to be used.
480 const OriginAttributes
481 mOriginAttributes
; // The originAttributes for this resolving
482 nsCOMPtr
<nsIDNSListener
> mListener
;
483 nsIDNSService::DNSFlags mFlags
= nsIDNSService::RESOLVE_DEFAULT_FLAGS
;
487 virtual ~nsDNSAsyncRequest() = default;
490 NS_IMPL_ISUPPORTS(nsDNSAsyncRequest
, nsICancelable
)
492 void nsDNSAsyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
493 nsHostRecord
* hostRecord
,
495 // need to have an owning ref when we issue the callback to enable
496 // the caller to be able to addref/release multiple times without
497 // destroying the record prematurely.
498 nsCOMPtr
<nsIDNSRecord
> rec
;
499 if (NS_SUCCEEDED(status
) ||
500 mFlags
& nsIDNSService::RESOLVE_WANT_RECORD_ON_ERROR
) {
501 MOZ_ASSERT(hostRecord
, "no host record");
502 if (hostRecord
->type
!= nsDNSService::RESOLVE_TYPE_DEFAULT
) {
503 rec
= new nsDNSByTypeRecord(hostRecord
);
505 rec
= new nsDNSRecord(hostRecord
);
509 mListener
->OnLookupComplete(this, rec
, status
);
513 bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
514 uintptr_t originalListenerAddr
= reinterpret_cast<uintptr_t>(mListener
.get());
515 RefPtr
<DNSListenerProxy
> wrapper
= do_QueryObject(mListener
);
517 originalListenerAddr
= wrapper
->GetOriginalListenerAddress();
520 uintptr_t listenerAddr
= reinterpret_cast<uintptr_t>(aListener
);
521 return (listenerAddr
== originalListenerAddr
);
524 size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
525 size_t n
= mallocSizeOf(this);
527 // The following fields aren't measured.
528 // - mHost, because it's a non-owning pointer
529 // - mResolver, because it's a non-owning pointer
530 // - mListener, because it's a non-owning pointer
536 nsDNSAsyncRequest::Cancel(nsresult reason
) {
537 NS_ENSURE_ARG(NS_FAILED(reason
));
538 MOZ_DIAGNOSTIC_ASSERT(mResolver
, "mResolver should not be null");
539 mResolver
->DetachCallback(mHost
, mTrrServer
, mType
, mOriginAttributes
, mFlags
,
544 //-----------------------------------------------------------------------------
546 class nsDNSSyncRequest
: public nsResolveHostCallback
{
547 NS_DECL_THREADSAFE_ISUPPORTS
549 explicit nsDNSSyncRequest(PRMonitor
* mon
) : mMonitor(mon
) {}
551 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
552 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
553 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
556 nsresult mStatus
= NS_OK
;
557 RefPtr
<nsHostRecord
> mHostRecord
;
560 virtual ~nsDNSSyncRequest() = default;
562 PRMonitor
* mMonitor
= nullptr;
565 NS_IMPL_ISUPPORTS0(nsDNSSyncRequest
)
567 void nsDNSSyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
568 nsHostRecord
* hostRecord
,
570 // store results, and wake up nsDNSService::Resolve to process results.
571 PR_EnterMonitor(mMonitor
);
574 mHostRecord
= hostRecord
;
576 PR_ExitMonitor(mMonitor
);
579 bool nsDNSSyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
580 // Sync request: no listener to compare
584 size_t nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
585 size_t n
= mallocSizeOf(this);
587 // The following fields aren't measured.
588 // - mHostRecord, because it's a non-owning pointer
590 // Measurement of the following members may be added later if DMD finds it
597 class NotifyDNSResolution
: public Runnable
{
599 explicit NotifyDNSResolution(const nsACString
& aHostname
)
600 : mozilla::Runnable("NotifyDNSResolution"), mHostname(aHostname
) {}
602 NS_IMETHOD
Run() override
{
603 MOZ_ASSERT(NS_IsMainThread());
604 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
606 obs
->NotifyObservers(nullptr, "dns-resolution-request",
607 NS_ConvertUTF8toUTF16(mHostname
).get());
616 //-----------------------------------------------------------------------------
618 static StaticRefPtr
<DNSServiceWrapper
> gDNSServiceWrapper
;
620 NS_IMPL_ISUPPORTS(DNSServiceWrapper
, nsIDNSService
, nsPIDNSService
)
623 already_AddRefed
<nsIDNSService
> DNSServiceWrapper::GetSingleton() {
624 if (!gDNSServiceWrapper
) {
625 gDNSServiceWrapper
= new DNSServiceWrapper();
626 gDNSServiceWrapper
->mDNSServiceInUse
= ChildDNSService::GetSingleton();
627 if (gDNSServiceWrapper
->mDNSServiceInUse
) {
628 ClearOnShutdown(&gDNSServiceWrapper
);
629 nsDNSPrefetch::Initialize(gDNSServiceWrapper
);
631 gDNSServiceWrapper
= nullptr;
635 return do_AddRef(gDNSServiceWrapper
);
639 void DNSServiceWrapper::SwitchToBackupDNSService() {
640 if (!gDNSServiceWrapper
) {
644 gDNSServiceWrapper
->mBackupDNSService
= nsDNSService::GetSingleton();
646 MutexAutoLock
lock(gDNSServiceWrapper
->mLock
);
647 gDNSServiceWrapper
->mBackupDNSService
.swap(
648 gDNSServiceWrapper
->mDNSServiceInUse
);
651 nsIDNSService
* DNSServiceWrapper::DNSService() {
652 MOZ_ASSERT(XRE_IsParentProcess());
654 MutexAutoLock
lock(mLock
);
655 return mDNSServiceInUse
.get();
658 nsPIDNSService
* DNSServiceWrapper::PIDNSService() {
659 MOZ_ASSERT(XRE_IsParentProcess());
661 nsCOMPtr
<nsPIDNSService
> service
= do_QueryInterface(DNSService());
662 return service
.get();
665 //-----------------------------------------------------------------------------
666 NS_IMPL_ISUPPORTS_INHERITED(nsDNSService
, DNSServiceBase
, nsIDNSService
,
667 nsPIDNSService
, nsIMemoryReporter
)
669 /******************************************************************************
671 * singleton instance ctor/dtor methods
672 ******************************************************************************/
673 static StaticRefPtr
<nsDNSService
> gDNSService
;
674 static Atomic
<bool> gInited(false);
676 already_AddRefed
<nsIDNSService
> GetOrInitDNSService() {
678 return nsDNSService::GetXPCOMSingleton();
681 nsCOMPtr
<nsIDNSService
> dns
= nullptr;
682 auto initTask
= [&dns
]() { dns
= do_GetService(NS_DNSSERVICE_CID
); };
683 if (!NS_IsMainThread()) {
684 // Forward to the main thread synchronously.
685 RefPtr
<nsIThread
> mainThread
= do_GetMainThread();
690 SyncRunnable::DispatchToThread(
691 mainThread
, NS_NewRunnableFunction("GetOrInitDNSService", initTask
));
699 already_AddRefed
<nsIDNSService
> nsDNSService::GetXPCOMSingleton() {
700 auto getDNSHelper
= []() -> already_AddRefed
<nsIDNSService
> {
701 if (nsIOService::UseSocketProcess()) {
702 if (XRE_IsSocketProcess()) {
703 return GetSingleton();
706 if (XRE_IsParentProcess()) {
707 return DNSServiceWrapper::GetSingleton();
710 if (XRE_IsContentProcess()) {
711 return ChildDNSService::GetSingleton();
717 if (XRE_IsParentProcess() || XRE_IsSocketProcess()) {
718 return GetSingleton();
721 if (XRE_IsContentProcess()) {
722 return ChildDNSService::GetSingleton();
729 return getDNSHelper();
732 nsCOMPtr
<nsIDNSService
> dns
= getDNSHelper();
739 already_AddRefed
<nsDNSService
> nsDNSService::GetSingleton() {
740 MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess());
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
, kPrefDisableIPv6
)) {
792 if (NS_SUCCEEDED(Preferences::GetBool(kPrefDisableIPv6
, &tmpbool
))) {
793 mDisableIPv6
= tmpbool
;
796 if (!name
|| !strcmp(name
, kPrefDnsOfflineLocalhost
)) {
798 Preferences::GetBool(kPrefDnsOfflineLocalhost
, &tmpbool
))) {
799 mOfflineLocalhost
= tmpbool
;
802 if (!name
|| !strcmp(name
, kPrefBlockDotOnion
)) {
803 if (NS_SUCCEEDED(Preferences::GetBool(kPrefBlockDotOnion
, &tmpbool
))) {
804 mBlockDotOnion
= tmpbool
;
807 if (!name
|| !strcmp(name
, kPrefDnsNotifyResolution
)) {
809 Preferences::GetBool(kPrefDnsNotifyResolution
, &tmpbool
))) {
810 mNotifyResolution
= tmpbool
;
813 if (!name
|| !strcmp(name
, kPrefIPv4OnlyDomains
)) {
814 Preferences::GetCString(kPrefIPv4OnlyDomains
, mIPv4OnlyDomains
);
816 if (!name
|| !strcmp(name
, kPrefDnsLocalDomains
)) {
817 nsCString localDomains
;
818 Preferences::GetCString(kPrefDnsLocalDomains
, localDomains
);
819 MutexAutoLock
lock(mLock
);
820 mLocalDomains
.Clear();
821 for (const auto& token
:
822 nsCCharSeparatedTokenizerTemplate
<NS_IsAsciiWhitespace
,
823 nsTokenizerFlags::SeparatorOptional
>(
826 mLocalDomains
.Insert(token
);
829 if (!name
|| !strcmp(name
, kPrefDnsForceResolve
)) {
830 Preferences::GetCString(kPrefDnsForceResolve
, mForceResolve
);
831 mForceResolveOn
= !mForceResolve
.IsEmpty();
836 nsDNSService::Init() {
837 MOZ_ASSERT(!mResolver
);
838 MOZ_ASSERT(NS_IsMainThread());
842 nsCOMPtr
<nsIObserverService
> observerService
=
843 mozilla::services::GetObserverService();
844 if (observerService
) {
845 observerService
->AddObserver(this, "last-pb-context-exited", false);
846 observerService
->AddObserver(this, NS_NETWORK_LINK_TOPIC
, false);
847 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false);
850 RefPtr
<nsHostResolver
> res
;
851 nsresult rv
= nsHostResolver::Create(mResCacheEntries
, mResCacheExpiration
,
852 mResCacheGrace
, getter_AddRefs(res
));
853 if (NS_SUCCEEDED(rv
)) {
854 // now, set all of our member variables while holding the lock
855 MutexAutoLock
lock(mLock
);
859 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
861 // register as prefs observer
862 prefs
->AddObserver(kPrefDnsCacheEntries
, this, false);
863 prefs
->AddObserver(kPrefDnsCacheExpiration
, this, false);
864 prefs
->AddObserver(kPrefDnsCacheGrace
, this, false);
865 prefs
->AddObserver(kPrefIPv4OnlyDomains
, this, false);
866 prefs
->AddObserver(kPrefDnsLocalDomains
, this, false);
867 prefs
->AddObserver(kPrefDnsForceResolve
, this, false);
868 prefs
->AddObserver(kPrefDisableIPv6
, this, false);
869 prefs
->AddObserver(kPrefDnsOfflineLocalhost
, this, false);
870 prefs
->AddObserver(kPrefBlockDotOnion
, this, false);
871 prefs
->AddObserver(kPrefDnsNotifyResolution
, this, false);
872 AddPrefObserver(prefs
);
875 nsDNSPrefetch::Initialize(this);
877 RegisterWeakMemoryReporter(this);
879 nsCOMPtr
<nsIObliviousHttpService
> ohttpService(
880 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
882 mTrrService
= new TRRService();
883 if (NS_FAILED(mTrrService
->Init())) {
884 mTrrService
= nullptr;
887 nsCOMPtr
<nsIIDNService
> idn
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
894 nsDNSService::Shutdown() {
895 UnregisterWeakMemoryReporter(this);
897 RefPtr
<nsHostResolver
> res
;
899 MutexAutoLock
lock(mLock
);
900 res
= std::move(mResolver
);
903 // Shutdown outside lock.
907 nsCOMPtr
<nsIObserverService
> observerService
=
908 mozilla::services::GetObserverService();
909 if (observerService
) {
910 observerService
->RemoveObserver(this, NS_NETWORK_LINK_TOPIC
);
911 observerService
->RemoveObserver(this, "last-pb-context-exited");
912 observerService
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
918 bool nsDNSService::GetOffline() const {
919 bool offline
= false;
920 nsCOMPtr
<nsIIOService
> io
= do_GetService(NS_IOSERVICE_CONTRACTID
);
922 io
->GetOffline(&offline
);
928 nsDNSService::GetPrefetchEnabled(bool* outVal
) {
929 MutexAutoLock
lock(mLock
);
930 *outVal
= !mDisablePrefetch
;
935 nsDNSService::SetPrefetchEnabled(bool inVal
) {
936 MutexAutoLock
lock(mLock
);
937 mDisablePrefetch
= !inVal
;
941 already_AddRefed
<nsHostResolver
> nsDNSService::GetResolverLocked() {
942 MutexAutoLock
lock(mLock
);
943 return do_AddRef(mResolver
);
946 nsresult
nsDNSService::PreprocessHostname(bool aLocalDomain
,
947 const nsACString
& aInput
,
951 if (mBlockDotOnion
&& StringEndsWith(aInput
, ".onion"_ns
)) {
952 return NS_ERROR_UNKNOWN_HOST
;
956 aACE
.AssignLiteral("localhost");
960 if (mTrrService
&& mTrrService
->MaybeBootstrap(aInput
, aACE
)) {
964 if (mForceResolveOn
) {
965 MutexAutoLock
lock(mLock
);
966 if (!aInput
.LowerCaseEqualsASCII("localhost") &&
967 !aInput
.LowerCaseEqualsASCII("127.0.0.1")) {
968 aACE
.Assign(mForceResolve
);
973 if (!aIDN
|| IsAscii(aInput
)) {
978 if (!(IsUtf8(aInput
) && NS_SUCCEEDED(aIDN
->ConvertUTF8toACE(aInput
, aACE
)))) {
979 return NS_ERROR_FAILURE
;
984 nsresult
nsDNSService::AsyncResolveInternal(
985 const nsACString
& aHostname
, uint16_t type
, nsIDNSService::DNSFlags flags
,
986 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
,
987 nsIEventTarget
* target_
, const OriginAttributes
& aOriginAttributes
,
988 nsICancelable
** result
) {
989 // grab reference to global host resolver and IDN service. beware
990 // simultaneous shutdown!!
991 RefPtr
<nsHostResolver
> res
;
992 nsCOMPtr
<nsIIDNService
> idn
;
993 nsCOMPtr
<nsIEventTarget
> target
= target_
;
994 nsCOMPtr
<nsIDNSListener
> listener
= aListener
;
995 bool localDomain
= false;
997 MutexAutoLock
lock(mLock
);
999 if (mDisablePrefetch
&& (flags
& RESOLVE_SPECULATE
)) {
1000 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1005 localDomain
= mLocalDomains
.Contains(aHostname
);
1008 if (mNotifyResolution
) {
1009 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1013 return NS_ERROR_OFFLINE
;
1016 if ((type
!= RESOLVE_TYPE_DEFAULT
) && (type
!= RESOLVE_TYPE_TXT
) &&
1017 (type
!= RESOLVE_TYPE_HTTPSSVC
)) {
1018 return NS_ERROR_INVALID_ARG
;
1021 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1022 // nsHostResolver returns NS_ERROR_UNKNOWN_HOST for lots of reasons.
1023 // We use a different error code to differentiate this failure and to make
1024 // it clear(er) where this error comes from.
1025 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1029 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1030 if (NS_FAILED(rv
)) {
1035 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1036 flags
|= RESOLVE_OFFLINE
;
1039 // make sure JS callers get notification on the main thread
1040 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedListener
= do_QueryInterface(listener
);
1041 if (wrappedListener
&& !target
) {
1042 target
= GetMainThreadSerialEventTarget();
1046 listener
= new DNSListenerProxy(listener
, target
);
1050 (type
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, flags
);
1052 MOZ_ASSERT(listener
);
1053 RefPtr
<nsDNSAsyncRequest
> req
=
1054 new nsDNSAsyncRequest(res
, hostname
, DNSAdditionalInfo::URL(aInfo
), type
,
1055 aOriginAttributes
, listener
, flags
, af
);
1057 return NS_ERROR_OUT_OF_MEMORY
;
1060 rv
= res
->ResolveHost(req
->mHost
, DNSAdditionalInfo::URL(aInfo
),
1061 DNSAdditionalInfo::Port(aInfo
), type
,
1062 req
->mOriginAttributes
, flags
, af
, req
);
1067 nsresult
nsDNSService::CancelAsyncResolveInternal(
1068 const nsACString
& aHostname
, uint16_t aType
, nsIDNSService::DNSFlags aFlags
,
1069 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
, nsresult aReason
,
1070 const OriginAttributes
& aOriginAttributes
) {
1071 // grab reference to global host resolver and IDN service. beware
1072 // simultaneous shutdown!!
1073 RefPtr
<nsHostResolver
> res
;
1074 nsCOMPtr
<nsIIDNService
> idn
;
1075 bool localDomain
= false;
1077 MutexAutoLock
lock(mLock
);
1079 if (mDisablePrefetch
&& (aFlags
& RESOLVE_SPECULATE
)) {
1080 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1085 localDomain
= mLocalDomains
.Contains(aHostname
);
1088 return NS_ERROR_OFFLINE
;
1092 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1093 if (NS_FAILED(rv
)) {
1098 (aType
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, aFlags
);
1100 res
->CancelAsyncRequest(hostname
, DNSAdditionalInfo::URL(aInfo
), aType
,
1101 aOriginAttributes
, aFlags
, af
, aListener
, aReason
);
1106 nsDNSService::AsyncResolve(const nsACString
& aHostname
,
1107 nsIDNSService::ResolveType aType
,
1108 nsIDNSService::DNSFlags flags
,
1109 nsIDNSAdditionalInfo
* aInfo
,
1110 nsIDNSListener
* listener
, nsIEventTarget
* target_
,
1111 JS::Handle
<JS::Value
> aOriginAttributes
,
1112 JSContext
* aCx
, uint8_t aArgc
,
1113 nsICancelable
** result
) {
1114 OriginAttributes attrs
;
1117 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1118 return NS_ERROR_INVALID_ARG
;
1122 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, listener
, target_
,
1127 nsDNSService::AsyncResolveNative(
1128 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1129 nsIDNSService::DNSFlags flags
, nsIDNSAdditionalInfo
* aInfo
,
1130 nsIDNSListener
* aListener
, nsIEventTarget
* target_
,
1131 const OriginAttributes
& aOriginAttributes
, nsICancelable
** result
) {
1132 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, aListener
,
1133 target_
, aOriginAttributes
, result
);
1137 nsDNSService::NewAdditionalInfo(const nsACString
& aTrrURL
, int32_t aPort
,
1138 nsIDNSAdditionalInfo
** aInfo
) {
1139 RefPtr
<DNSAdditionalInfo
> res
= new DNSAdditionalInfo(aTrrURL
, aPort
);
1145 nsDNSService::CancelAsyncResolve(const nsACString
& aHostname
,
1146 nsIDNSService::ResolveType aType
,
1147 nsIDNSService::DNSFlags aFlags
,
1148 nsIDNSAdditionalInfo
* aInfo
,
1149 nsIDNSListener
* aListener
, nsresult aReason
,
1150 JS::Handle
<JS::Value
> aOriginAttributes
,
1151 JSContext
* aCx
, uint8_t aArgc
) {
1152 OriginAttributes attrs
;
1155 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1156 return NS_ERROR_INVALID_ARG
;
1160 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1165 nsDNSService::CancelAsyncResolveNative(
1166 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1167 nsIDNSService::DNSFlags aFlags
, nsIDNSAdditionalInfo
* aInfo
,
1168 nsIDNSListener
* aListener
, nsresult aReason
,
1169 const OriginAttributes
& aOriginAttributes
) {
1170 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1171 aReason
, aOriginAttributes
);
1175 nsDNSService::Resolve(const nsACString
& aHostname
,
1176 nsIDNSService::DNSFlags flags
,
1177 JS::Handle
<JS::Value
> aOriginAttributes
, JSContext
* aCx
,
1178 uint8_t aArgc
, nsIDNSRecord
** result
) {
1179 OriginAttributes attrs
;
1182 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1183 return NS_ERROR_INVALID_ARG
;
1187 return ResolveNative(aHostname
, flags
, attrs
, result
);
1191 nsDNSService::ResolveNative(const nsACString
& aHostname
,
1192 nsIDNSService::DNSFlags flags
,
1193 const OriginAttributes
& aOriginAttributes
,
1194 nsIDNSRecord
** result
) {
1195 // Synchronous resolution is not available on the main thread.
1196 if (NS_IsMainThread()) {
1197 return NS_ERROR_NOT_AVAILABLE
;
1200 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1203 nsresult
nsDNSService::DeprecatedSyncResolve(
1204 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1205 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1206 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1209 nsresult
nsDNSService::ResolveInternal(
1210 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1211 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1212 // grab reference to global host resolver and IDN service. beware
1213 // simultaneous shutdown!!
1214 RefPtr
<nsHostResolver
> res
;
1215 nsCOMPtr
<nsIIDNService
> idn
;
1216 bool localDomain
= false;
1218 MutexAutoLock
lock(mLock
);
1221 localDomain
= mLocalDomains
.Contains(aHostname
);
1224 if (mNotifyResolution
) {
1225 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1228 NS_ENSURE_TRUE(res
, NS_ERROR_OFFLINE
);
1231 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, idn
, hostname
);
1232 if (NS_FAILED(rv
)) {
1237 (!mOfflineLocalhost
|| !hostname
.LowerCaseEqualsASCII("localhost"))) {
1238 flags
|= RESOLVE_OFFLINE
;
1241 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1242 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1246 // sync resolve: since the host resolver only works asynchronously, we need
1247 // to use a mutex and a condvar to wait for the result. however, since the
1248 // result may be in the resolvers cache, we might get called back recursively
1249 // on the same thread. so, our mutex needs to be re-entrant. in other words,
1250 // we need to use a monitor! ;-)
1253 PRMonitor
* mon
= PR_NewMonitor();
1255 return NS_ERROR_OUT_OF_MEMORY
;
1258 PR_EnterMonitor(mon
);
1259 RefPtr
<nsDNSSyncRequest
> syncReq
= new nsDNSSyncRequest(mon
);
1261 uint16_t af
= GetAFForLookup(hostname
, flags
);
1263 // TRR uses the main thread for the HTTPS channel to the DoH server.
1264 // If this were to block the main thread while waiting for TRR it would
1265 // likely cause a deadlock. Instead we intentionally choose to not use TRR
1267 if (NS_IsMainThread()) {
1268 flags
|= RESOLVE_DISABLE_TRR
;
1271 rv
= res
->ResolveHost(hostname
, ""_ns
, -1, RESOLVE_TYPE_DEFAULT
,
1272 aOriginAttributes
, flags
, af
, syncReq
);
1273 if (NS_SUCCEEDED(rv
)) {
1275 while (!syncReq
->mDone
) {
1276 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
1279 if (NS_FAILED(syncReq
->mStatus
)) {
1280 rv
= syncReq
->mStatus
;
1282 NS_ASSERTION(syncReq
->mHostRecord
, "no host record");
1283 RefPtr
<nsDNSRecord
> rec
= new nsDNSRecord(syncReq
->mHostRecord
);
1288 PR_ExitMonitor(mon
);
1289 PR_DestroyMonitor(mon
);
1294 nsDNSService::GetMyHostName(nsACString
& result
) {
1296 if (PR_GetSystemInfo(PR_SI_HOSTNAME
, name
, sizeof(name
)) == PR_SUCCESS
) {
1300 return NS_ERROR_FAILURE
;
1304 nsDNSService::Observe(nsISupports
* subject
, const char* topic
,
1305 const char16_t
* data
) {
1306 bool flushCache
= false;
1307 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1309 if (!strcmp(topic
, NS_NETWORK_LINK_TOPIC
)) {
1310 nsAutoCString converted
= NS_ConvertUTF16toUTF8(data
);
1311 if (!strcmp(converted
.get(), NS_NETWORK_LINK_DATA_CHANGED
)) {
1314 } else if (!strcmp(topic
, "last-pb-context-exited")) {
1316 } else if (!strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
1317 ReadPrefs(NS_ConvertUTF16toUTF8(data
).get());
1318 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1319 if (mResolverPrefsUpdated
&& resolver
) {
1320 resolver
->SetCacheLimits(mResCacheEntries
, mResCacheExpiration
,
1323 } else if (!strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
1327 if (flushCache
&& resolver
) {
1328 resolver
->FlushCache(false);
1335 uint16_t nsDNSService::GetAFForLookup(const nsACString
& host
,
1336 nsIDNSService::DNSFlags flags
) {
1337 if (mDisableIPv6
|| (flags
& RESOLVE_DISABLE_IPV6
)) {
1341 MutexAutoLock
lock(mLock
);
1343 uint16_t af
= PR_AF_UNSPEC
;
1345 if (!mIPv4OnlyDomains
.IsEmpty()) {
1346 const char *domain
, *domainEnd
, *end
;
1347 uint32_t hostLen
, domainLen
;
1349 // see if host is in one of the IPv4-only domains
1350 domain
= mIPv4OnlyDomains
.BeginReading();
1351 domainEnd
= mIPv4OnlyDomains
.EndReading();
1353 nsACString::const_iterator hostStart
;
1354 host
.BeginReading(hostStart
);
1355 hostLen
= host
.Length();
1358 // skip any whitespace
1359 while (*domain
== ' ' || *domain
== '\t') {
1363 // find end of this domain in the string
1364 end
= strchr(domain
, ',');
1369 // to see if the hostname is in the domain, check if the domain
1370 // matches the end of the hostname.
1371 domainLen
= end
- domain
;
1372 if (domainLen
&& hostLen
>= domainLen
) {
1373 const char* hostTail
= hostStart
.get() + hostLen
- domainLen
;
1374 if (nsCRT::strncasecmp(domain
, hostTail
, domainLen
) == 0) {
1375 // now, make sure either that the hostname is a direct match or
1376 // that the hostname begins with a dot.
1377 if (hostLen
== domainLen
|| *hostTail
== '.' ||
1378 *(hostTail
- 1) == '.') {
1389 if ((af
!= PR_AF_INET
) && (flags
& RESOLVE_DISABLE_IPV4
)) {
1397 nsDNSService::GetDNSCacheEntries(
1398 nsTArray
<mozilla::net::DNSCacheEntries
>* args
) {
1399 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1400 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1401 resolver
->GetDNSCacheEntries(args
);
1406 nsDNSService::ClearCache(bool aTrrToo
) {
1407 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1408 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1409 resolver
->FlushCache(aTrrToo
);
1414 nsDNSService::ReloadParentalControlEnabled() {
1416 mTrrService
->mParentalControlEnabled
=
1417 TRRService::GetParentalControlEnabledInternal();
1423 nsDNSService::SetDetectedTrrURI(const nsACString
& aURI
) {
1425 mTrrService
->SetDetectedTrrURI(aURI
);
1431 nsDNSService::SetHeuristicDetectionResult(nsITRRSkipReason::value aValue
) {
1433 mTrrService
->SetHeuristicDetectionResult(aValue
);
1439 nsDNSService::GetHeuristicDetectionResult(nsITRRSkipReason::value
* aValue
) {
1441 return NS_ERROR_NOT_AVAILABLE
;
1444 *aValue
= mTrrService
->GetHeuristicDetectionResult();
1449 nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue
,
1450 nsACString
& aName
) {
1451 return mozilla::net::GetTRRSkipReasonName(aValue
, aName
);
1455 nsDNSService::GetCurrentTrrURI(nsACString
& aURI
) {
1457 mTrrService
->GetURI(aURI
);
1463 nsDNSService::GetCurrentTrrMode(nsIDNSService::ResolverMode
* aMode
) {
1464 *aMode
= nsIDNSService::MODE_NATIVEONLY
; // The default mode.
1466 *aMode
= mTrrService
->Mode();
1472 nsDNSService::GetCurrentTrrConfirmationState(uint32_t* aConfirmationState
) {
1473 *aConfirmationState
= uint32_t(TRRService::CONFIRM_OFF
);
1475 *aConfirmationState
= mTrrService
->ConfirmationState();
1481 nsDNSService::GetTrrDomain(nsACString
& aTRRDomain
) {
1482 aTRRDomain
.Truncate();
1485 mTrrService
->GetURI(url
);
1487 nsCOMPtr
<nsIURI
> uri
;
1488 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), url
);
1489 if (NS_FAILED(rv
)) {
1490 // An empty TRR domain in case of invalid URL.
1493 return uri
->GetHost(aTRRDomain
);
1496 nsresult
nsDNSService::GetTRRDomainKey(nsACString
& aTRRDomain
) {
1497 aTRRDomain
= TRRService::ProviderKey();
1501 size_t nsDNSService::SizeOfIncludingThis(
1502 mozilla::MallocSizeOf mallocSizeOf
) const {
1503 // Measurement of the following members may be added later if DMD finds it
1508 size_t n
= mallocSizeOf(this);
1509 n
+= mResolver
? mResolver
->SizeOfIncludingThis(mallocSizeOf
) : 0;
1510 n
+= mIPv4OnlyDomains
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1511 n
+= mLocalDomains
.SizeOfExcludingThis(mallocSizeOf
);
1512 n
+= mFailedSVCDomainNames
.ShallowSizeOfExcludingThis(mallocSizeOf
);
1513 for (const auto& data
: mFailedSVCDomainNames
.Values()) {
1514 n
+= data
->ShallowSizeOfExcludingThis(mallocSizeOf
);
1515 for (const auto& name
: *data
) {
1516 n
+= name
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1522 MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf
)
1525 nsDNSService::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1526 nsISupports
* aData
, bool aAnonymize
) {
1527 MOZ_COLLECT_REPORT("explicit/network/dns-service", KIND_HEAP
, UNITS_BYTES
,
1528 SizeOfIncludingThis(DNSServiceMallocSizeOf
),
1529 "Memory used for the DNS service.");
1535 nsDNSService::ReportFailedSVCDomainName(const nsACString
& aOwnerName
,
1536 const nsACString
& aSVCDomainName
) {
1537 MutexAutoLock
lock(mLock
);
1539 mFailedSVCDomainNames
.GetOrInsertNew(aOwnerName
, 1)
1540 ->AppendElement(aSVCDomainName
);
1545 nsDNSService::IsSVCDomainNameFailed(const nsACString
& aOwnerName
,
1546 const nsACString
& aSVCDomainName
,
1548 NS_ENSURE_ARG(aResult
);
1550 MutexAutoLock
lock(mLock
);
1552 nsTArray
<nsCString
>* failedList
= mFailedSVCDomainNames
.Get(aOwnerName
);
1557 *aResult
= failedList
->Contains(aSVCDomainName
);
1562 nsDNSService::ResetExcludedSVCDomainName(const nsACString
& aOwnerName
) {
1563 MutexAutoLock
lock(mLock
);
1564 mFailedSVCDomainNames
.Remove(aOwnerName
);
1569 nsDNSService::GetLastConfirmationStatus(nsresult
* aConfirmationStatus
) {
1571 return NS_ERROR_NOT_AVAILABLE
;
1573 *aConfirmationStatus
= mTrrService
->LastConfirmationStatus();
1577 NS_IMETHODIMP
nsDNSService::GetLastConfirmationSkipReason(
1578 TRRSkippedReason
* aSkipReason
) {
1580 return NS_ERROR_NOT_AVAILABLE
;
1582 *aSkipReason
= mTrrService
->LastConfirmationSkipReason();
1586 namespace mozilla::net
{
1587 nsresult
GetTRRSkipReasonName(TRRSkippedReason aReason
, nsACString
& aName
) {
1588 static_assert(TRRSkippedReason::TRR_UNSET
== 0);
1589 static_assert(TRRSkippedReason::TRR_OK
== 1);
1590 static_assert(TRRSkippedReason::TRR_NO_GSERVICE
== 2);
1591 static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL
== 3);
1592 static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT
== 4);
1593 static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED
== 5);
1594 static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED
== 6);
1595 static_assert(TRRSkippedReason::TRR_FAILED
== 7);
1596 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
== 8);
1597 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
== 9);
1598 static_assert(TRRSkippedReason::TRR_DISABLED_FLAG
== 10);
1599 static_assert(TRRSkippedReason::TRR_TIMEOUT
== 11);
1600 static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
== 12);
1601 static_assert(TRRSkippedReason::TRR_IS_OFFLINE
== 13);
1602 static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED
== 14);
1603 static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
== 15);
1604 static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
== 16);
1605 static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
== 17);
1606 static_assert(TRRSkippedReason::TRR_SEND_FAILED
== 18);
1607 static_assert(TRRSkippedReason::TRR_NET_RESET
== 19);
1608 static_assert(TRRSkippedReason::TRR_NET_TIMEOUT
== 20);
1609 static_assert(TRRSkippedReason::TRR_NET_REFUSED
== 21);
1610 static_assert(TRRSkippedReason::TRR_NET_INTERRUPT
== 22);
1611 static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
== 23);
1612 static_assert(TRRSkippedReason::TRR_NO_ANSWERS
== 24);
1613 static_assert(TRRSkippedReason::TRR_DECODE_FAILED
== 25);
1614 static_assert(TRRSkippedReason::TRR_EXCLUDED
== 26);
1615 static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
== 27);
1616 static_assert(TRRSkippedReason::TRR_RCODE_FAIL
== 28);
1617 static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY
== 29);
1618 static_assert(TRRSkippedReason::TRR_NXDOMAIN
== 30);
1619 static_assert(TRRSkippedReason::TRR_REQ_CANCELLED
== 31);
1620 static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE
== 32);
1621 static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
== 33);
1622 static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
== 34);
1623 static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED
== 35);
1624 static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED
== 36);
1625 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
==
1627 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
==
1629 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
== 39);
1630 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
== 40);
1631 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
== 41);
1632 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
==
1634 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
==
1636 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
==
1638 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
== 45);
1639 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
== 46);
1640 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
== 47);
1643 case TRRSkippedReason::TRR_UNSET
:
1644 aName
= "TRR_UNSET"_ns
;
1646 case TRRSkippedReason::TRR_OK
:
1647 aName
= "TRR_OK"_ns
;
1649 case TRRSkippedReason::TRR_NO_GSERVICE
:
1650 aName
= "TRR_NO_GSERVICE"_ns
;
1652 case TRRSkippedReason::TRR_PARENTAL_CONTROL
:
1653 aName
= "TRR_PARENTAL_CONTROL"_ns
;
1655 case TRRSkippedReason::TRR_OFF_EXPLICIT
:
1656 aName
= "TRR_OFF_EXPLICIT"_ns
;
1658 case TRRSkippedReason::TRR_REQ_MODE_DISABLED
:
1659 aName
= "TRR_REQ_MODE_DISABLED"_ns
;
1661 case TRRSkippedReason::TRR_MODE_NOT_ENABLED
:
1662 aName
= "TRR_MODE_NOT_ENABLED"_ns
;
1664 case TRRSkippedReason::TRR_FAILED
:
1665 aName
= "TRR_FAILED"_ns
;
1667 case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
:
1668 aName
= "TRR_MODE_UNHANDLED_DEFAULT"_ns
;
1670 case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
:
1671 aName
= "TRR_MODE_UNHANDLED_DISABLED"_ns
;
1673 case TRRSkippedReason::TRR_DISABLED_FLAG
:
1674 aName
= "TRR_DISABLED_FLAG"_ns
;
1676 case TRRSkippedReason::TRR_TIMEOUT
:
1677 aName
= "TRR_TIMEOUT"_ns
;
1679 case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
:
1680 aName
= "TRR_CHANNEL_DNS_FAIL"_ns
;
1682 case TRRSkippedReason::TRR_IS_OFFLINE
:
1683 aName
= "TRR_IS_OFFLINE"_ns
;
1685 case TRRSkippedReason::TRR_NOT_CONFIRMED
:
1686 aName
= "TRR_NOT_CONFIRMED"_ns
;
1688 case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
:
1689 aName
= "TRR_DID_NOT_MAKE_QUERY"_ns
;
1691 case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
:
1692 aName
= "TRR_UNKNOWN_CHANNEL_FAILURE"_ns
;
1694 case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
:
1695 aName
= "TRR_HOST_BLOCKED_TEMPORARY"_ns
;
1697 case TRRSkippedReason::TRR_SEND_FAILED
:
1698 aName
= "TRR_SEND_FAILED"_ns
;
1700 case TRRSkippedReason::TRR_NET_RESET
:
1701 aName
= "TRR_NET_RESET"_ns
;
1703 case TRRSkippedReason::TRR_NET_TIMEOUT
:
1704 aName
= "TRR_NET_TIMEOUT"_ns
;
1706 case TRRSkippedReason::TRR_NET_REFUSED
:
1707 aName
= "TRR_NET_REFUSED"_ns
;
1709 case TRRSkippedReason::TRR_NET_INTERRUPT
:
1710 aName
= "TRR_NET_INTERRUPT"_ns
;
1712 case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
:
1713 aName
= "TRR_NET_INADEQ_SEQURITY"_ns
;
1715 case TRRSkippedReason::TRR_NO_ANSWERS
:
1716 aName
= "TRR_NO_ANSWERS"_ns
;
1718 case TRRSkippedReason::TRR_DECODE_FAILED
:
1719 aName
= "TRR_DECODE_FAILED"_ns
;
1721 case TRRSkippedReason::TRR_EXCLUDED
:
1722 aName
= "TRR_EXCLUDED"_ns
;
1724 case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
:
1725 aName
= "TRR_SERVER_RESPONSE_ERR"_ns
;
1727 case TRRSkippedReason::TRR_RCODE_FAIL
:
1728 aName
= "TRR_RCODE_FAIL"_ns
;
1730 case TRRSkippedReason::TRR_NO_CONNECTIVITY
:
1731 aName
= "TRR_NO_CONNECTIVITY"_ns
;
1733 case TRRSkippedReason::TRR_NXDOMAIN
:
1734 aName
= "TRR_NXDOMAIN"_ns
;
1736 case TRRSkippedReason::TRR_REQ_CANCELLED
:
1737 aName
= "TRR_REQ_CANCELLED"_ns
;
1739 case TRRSkippedReason::ODOH_KEY_NOT_USABLE
:
1740 aName
= "ODOH_KEY_NOT_USABLE"_ns
;
1742 case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
:
1743 aName
= "ODOH_UPDATE_KEY_FAILED"_ns
;
1745 case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
:
1746 aName
= "ODOH_KEY_NOT_AVAILABLE"_ns
;
1748 case TRRSkippedReason::ODOH_ENCRYPTION_FAILED
:
1749 aName
= "ODOH_ENCRYPTION_FAILED"_ns
;
1751 case TRRSkippedReason::ODOH_DECRYPTION_FAILED
:
1752 aName
= "ODOH_DECRYPTION_FAILED"_ns
;
1754 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
:
1755 aName
= "TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH"_ns
;
1757 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
:
1758 aName
= "TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH"_ns
;
1760 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
:
1761 aName
= "TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY"_ns
;
1763 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
:
1764 aName
= "TRR_HEURISTIC_TRIPPED_CANARY"_ns
;
1766 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
:
1767 aName
= "TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS"_ns
;
1769 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
:
1770 aName
= "TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS"_ns
;
1772 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
:
1773 aName
= "TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS"_ns
;
1775 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
:
1776 aName
= "TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY"_ns
;
1778 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
:
1779 aName
= "TRR_HEURISTIC_TRIPPED_VPN"_ns
;
1781 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
:
1782 aName
= "TRR_HEURISTIC_TRIPPED_PROXY"_ns
;
1784 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
:
1785 aName
= "TRR_HEURISTIC_TRIPPED_NRPT"_ns
;
1788 MOZ_ASSERT(false, "Unknown value");
1793 } // namespace mozilla::net