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 "nsNetUtil.h"
32 #include "nsProxyRelease.h"
33 #include "nsQueryObject.h"
34 #include "nsIObserverService.h"
35 #include "nsINetworkLinkService.h"
36 #include "DNSAdditionalInfo.h"
37 #include "TRRService.h"
39 #include "mozilla/Attributes.h"
40 #include "mozilla/ClearOnShutdown.h"
41 #include "mozilla/net/NeckoCommon.h"
42 #include "mozilla/net/ChildDNSService.h"
43 #include "mozilla/net/DNSListenerProxy.h"
44 #include "mozilla/Services.h"
45 #include "mozilla/StaticPrefs_network.h"
46 #include "mozilla/StaticPtr.h"
47 #include "mozilla/SyncRunnable.h"
48 #include "mozilla/TextUtils.h"
49 #include "mozilla/Utf8.h"
51 using namespace mozilla
;
52 using namespace mozilla::net
;
54 static const char kPrefDnsCacheEntries
[] = "network.dnsCacheEntries";
55 static const char kPrefDnsCacheExpiration
[] = "network.dnsCacheExpiration";
56 static const char kPrefDnsCacheGrace
[] =
57 "network.dnsCacheExpirationGracePeriod";
58 static const char kPrefIPv4OnlyDomains
[] = "network.dns.ipv4OnlyDomains";
59 static const char kPrefDnsLocalDomains
[] = "network.dns.localDomains";
60 static const char kPrefDnsForceResolve
[] = "network.dns.forceResolve";
61 static const char kPrefDnsNotifyResolution
[] = "network.dns.notifyResolution";
62 static const char kPrefDnsMockHTTPSRRDomain
[] =
63 "network.dns.mock_HTTPS_RR_domain";
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
& nsIDNSService::RESOLVE_CANONICAL_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 *addr
= *mHostRecord
->addr
;
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 *addr
= *mHostRecord
->addr
;
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::GetServiceModeRecordWithCname(bool aNoHttp2
, bool aNoHttp3
,
420 const nsACString
& aCname
,
421 nsISVCBRecord
** aRecord
) {
422 return mHostRecord
->GetServiceModeRecordWithCname(aNoHttp2
, aNoHttp3
, aCname
,
427 nsDNSByTypeRecord::IsTRR(bool* aResult
) { return mHostRecord
->IsTRR(aResult
); }
430 nsDNSByTypeRecord::GetAllRecords(bool aNoHttp2
, bool aNoHttp3
,
431 const nsACString
& aCname
,
432 nsTArray
<RefPtr
<nsISVCBRecord
>>& aResult
) {
433 return mHostRecord
->GetAllRecords(aNoHttp2
, aNoHttp3
, aCname
, aResult
);
437 nsDNSByTypeRecord::GetAllRecordsWithEchConfig(
438 bool aNoHttp2
, bool aNoHttp3
, const nsACString
& aCname
,
439 bool* aAllRecordsHaveEchConfig
, bool* aAllRecordsInH3ExcludedList
,
440 nsTArray
<RefPtr
<nsISVCBRecord
>>& aResult
) {
441 return mHostRecord
->GetAllRecordsWithEchConfig(
442 aNoHttp2
, aNoHttp3
, aCname
, aAllRecordsHaveEchConfig
,
443 aAllRecordsInH3ExcludedList
, aResult
);
447 nsDNSByTypeRecord::GetHasIPAddresses(bool* aResult
) {
448 return mHostRecord
->GetHasIPAddresses(aResult
);
452 nsDNSByTypeRecord::GetAllRecordsExcluded(bool* aResult
) {
453 return mHostRecord
->GetAllRecordsExcluded(aResult
);
457 nsDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType
* aResults
) {
458 *aResults
= mHostRecord
->GetResults();
463 nsDNSByTypeRecord::GetTtl(uint32_t* aTtl
) { return mHostRecord
->GetTtl(aTtl
); }
465 //-----------------------------------------------------------------------------
467 class nsDNSAsyncRequest final
: public nsResolveHostCallback
,
468 public nsICancelable
{
470 NS_DECL_THREADSAFE_ISUPPORTS
471 NS_DECL_NSICANCELABLE
473 nsDNSAsyncRequest(nsHostResolver
* res
, const nsACString
& host
,
474 const nsACString
& trrServer
, uint16_t type
,
475 const OriginAttributes
& attrs
, nsIDNSListener
* listener
,
476 nsIDNSService::DNSFlags flags
, uint16_t af
)
479 mTrrServer(trrServer
),
481 mOriginAttributes(attrs
),
486 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
487 // Returns TRUE if the DNS listener arg is the same as the member listener
488 // Used in Cancellations to remove DNS requests associated with a
489 // particular hostname and nsIDNSListener
490 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
492 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
494 RefPtr
<nsHostResolver
> mResolver
;
495 nsCString mHost
; // hostname we're resolving
496 nsCString mTrrServer
; // A trr server to be used.
498 const OriginAttributes
499 mOriginAttributes
; // The originAttributes for this resolving
500 nsCOMPtr
<nsIDNSListener
> mListener
;
501 nsIDNSService::DNSFlags mFlags
= nsIDNSService::RESOLVE_DEFAULT_FLAGS
;
505 virtual ~nsDNSAsyncRequest() = default;
508 NS_IMPL_ISUPPORTS(nsDNSAsyncRequest
, nsICancelable
)
510 void nsDNSAsyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
511 nsHostRecord
* hostRecord
,
513 // need to have an owning ref when we issue the callback to enable
514 // the caller to be able to addref/release multiple times without
515 // destroying the record prematurely.
516 nsCOMPtr
<nsIDNSRecord
> rec
;
517 if (NS_SUCCEEDED(status
) ||
518 mFlags
& nsIDNSService::RESOLVE_WANT_RECORD_ON_ERROR
) {
519 MOZ_ASSERT(hostRecord
, "no host record");
521 mListener
->OnLookupComplete(this, nullptr, NS_ERROR_UNKNOWN_HOST
);
525 if (hostRecord
->type
!= nsDNSService::RESOLVE_TYPE_DEFAULT
) {
526 rec
= new nsDNSByTypeRecord(hostRecord
);
528 rec
= new nsDNSRecord(hostRecord
);
532 mListener
->OnLookupComplete(this, rec
, status
);
536 bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
537 uintptr_t originalListenerAddr
= reinterpret_cast<uintptr_t>(mListener
.get());
538 RefPtr
<DNSListenerProxy
> wrapper
= do_QueryObject(mListener
);
540 originalListenerAddr
= wrapper
->GetOriginalListenerAddress();
543 uintptr_t listenerAddr
= reinterpret_cast<uintptr_t>(aListener
);
544 return (listenerAddr
== originalListenerAddr
);
547 size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
548 size_t n
= mallocSizeOf(this);
550 // The following fields aren't measured.
551 // - mHost, because it's a non-owning pointer
552 // - mResolver, because it's a non-owning pointer
553 // - mListener, because it's a non-owning pointer
559 nsDNSAsyncRequest::Cancel(nsresult reason
) {
560 NS_ENSURE_ARG(NS_FAILED(reason
));
561 MOZ_DIAGNOSTIC_ASSERT(mResolver
, "mResolver should not be null");
562 mResolver
->DetachCallback(mHost
, mTrrServer
, mType
, mOriginAttributes
, mFlags
,
567 //-----------------------------------------------------------------------------
569 class nsDNSSyncRequest
: public nsResolveHostCallback
{
570 NS_DECL_THREADSAFE_ISUPPORTS
572 explicit nsDNSSyncRequest(PRMonitor
* mon
) : mMonitor(mon
) {}
574 void OnResolveHostComplete(nsHostResolver
*, nsHostRecord
*, nsresult
) override
;
575 bool EqualsAsyncListener(nsIDNSListener
* aListener
) override
;
576 size_t SizeOfIncludingThis(mozilla::MallocSizeOf
) const override
;
579 nsresult mStatus
= NS_OK
;
580 RefPtr
<nsHostRecord
> mHostRecord
;
583 virtual ~nsDNSSyncRequest() = default;
585 PRMonitor
* mMonitor
= nullptr;
588 NS_IMPL_ISUPPORTS0(nsDNSSyncRequest
)
590 void nsDNSSyncRequest::OnResolveHostComplete(nsHostResolver
* resolver
,
591 nsHostRecord
* hostRecord
,
593 // store results, and wake up nsDNSService::Resolve to process results.
594 PR_EnterMonitor(mMonitor
);
597 mHostRecord
= hostRecord
;
599 PR_ExitMonitor(mMonitor
);
602 bool nsDNSSyncRequest::EqualsAsyncListener(nsIDNSListener
* aListener
) {
603 // Sync request: no listener to compare
607 size_t nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf
) const {
608 size_t n
= mallocSizeOf(this);
610 // The following fields aren't measured.
611 // - mHostRecord, because it's a non-owning pointer
613 // Measurement of the following members may be added later if DMD finds it
620 class NotifyDNSResolution
: public Runnable
{
622 explicit NotifyDNSResolution(const nsACString
& aHostname
)
623 : mozilla::Runnable("NotifyDNSResolution"), mHostname(aHostname
) {}
625 NS_IMETHOD
Run() override
{
626 MOZ_ASSERT(NS_IsMainThread());
627 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
629 obs
->NotifyObservers(nullptr, "dns-resolution-request",
630 NS_ConvertUTF8toUTF16(mHostname
).get());
639 //-----------------------------------------------------------------------------
641 static StaticRefPtr
<DNSServiceWrapper
> gDNSServiceWrapper
;
643 NS_IMPL_ISUPPORTS(DNSServiceWrapper
, nsIDNSService
, nsPIDNSService
)
646 already_AddRefed
<nsIDNSService
> DNSServiceWrapper::GetSingleton() {
647 if (!gDNSServiceWrapper
) {
648 gDNSServiceWrapper
= new DNSServiceWrapper();
649 gDNSServiceWrapper
->mDNSServiceInUse
= ChildDNSService::GetSingleton();
650 if (gDNSServiceWrapper
->mDNSServiceInUse
) {
651 ClearOnShutdown(&gDNSServiceWrapper
);
652 nsDNSPrefetch::Initialize(gDNSServiceWrapper
);
654 gDNSServiceWrapper
= nullptr;
658 return do_AddRef(gDNSServiceWrapper
);
662 void DNSServiceWrapper::SwitchToBackupDNSService() {
663 if (!gDNSServiceWrapper
) {
667 gDNSServiceWrapper
->mBackupDNSService
= nsDNSService::GetSingleton();
669 MutexAutoLock
lock(gDNSServiceWrapper
->mLock
);
670 gDNSServiceWrapper
->mBackupDNSService
.swap(
671 gDNSServiceWrapper
->mDNSServiceInUse
);
674 nsIDNSService
* DNSServiceWrapper::DNSService() {
675 MOZ_ASSERT(XRE_IsParentProcess());
677 MutexAutoLock
lock(mLock
);
678 return mDNSServiceInUse
.get();
681 nsPIDNSService
* DNSServiceWrapper::PIDNSService() {
682 MOZ_ASSERT(XRE_IsParentProcess());
684 nsCOMPtr
<nsPIDNSService
> service
= do_QueryInterface(DNSService());
685 return service
.get();
688 //-----------------------------------------------------------------------------
689 NS_IMPL_ISUPPORTS_INHERITED(nsDNSService
, DNSServiceBase
, nsIDNSService
,
690 nsPIDNSService
, nsIMemoryReporter
)
692 /******************************************************************************
694 * singleton instance ctor/dtor methods
695 ******************************************************************************/
696 static StaticRefPtr
<nsDNSService
> gDNSService
;
697 static Atomic
<bool> gInited(false);
699 already_AddRefed
<nsIDNSService
> GetOrInitDNSService() {
701 return nsDNSService::GetXPCOMSingleton();
704 nsCOMPtr
<nsIDNSService
> dns
= nullptr;
705 auto initTask
= [&dns
]() { dns
= do_GetService(NS_DNSSERVICE_CID
); };
706 if (!NS_IsMainThread()) {
707 // Forward to the main thread synchronously.
708 RefPtr
<nsIThread
> mainThread
= do_GetMainThread();
713 SyncRunnable::DispatchToThread(
714 mainThread
, NS_NewRunnableFunction("GetOrInitDNSService", initTask
));
722 already_AddRefed
<nsIDNSService
> nsDNSService::GetXPCOMSingleton() {
723 auto getDNSHelper
= []() -> already_AddRefed
<nsIDNSService
> {
724 if (nsIOService::UseSocketProcess()) {
725 if (XRE_IsSocketProcess()) {
726 return GetSingleton();
729 if (XRE_IsParentProcess()) {
730 return DNSServiceWrapper::GetSingleton();
733 if (XRE_IsContentProcess()) {
734 return ChildDNSService::GetSingleton();
740 if (XRE_IsParentProcess()) {
741 return GetSingleton();
744 if (XRE_IsContentProcess() || XRE_IsSocketProcess()) {
745 return ChildDNSService::GetSingleton();
752 return getDNSHelper();
755 nsCOMPtr
<nsIDNSService
> dns
= getDNSHelper();
762 already_AddRefed
<nsDNSService
> nsDNSService::GetSingleton() {
763 MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess());
764 MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), XRE_IsParentProcess());
767 if (!NS_IsMainThread()) {
770 gDNSService
= new nsDNSService();
771 if (NS_SUCCEEDED(gDNSService
->Init())) {
772 ClearOnShutdown(&gDNSService
);
774 gDNSService
= nullptr;
778 return do_AddRef(gDNSService
);
781 void nsDNSService::ReadPrefs(const char* name
) {
782 DNSServiceBase::ReadPrefs(name
);
787 if (!name
|| !strcmp(name
, kPrefDnsNotifyResolution
)) {
789 Preferences::GetBool(kPrefDnsNotifyResolution
, &tmpbool
))) {
790 mNotifyResolution
= tmpbool
;
793 if (!name
|| !strcmp(name
, kPrefIPv4OnlyDomains
)) {
794 Preferences::GetCString(kPrefIPv4OnlyDomains
, mIPv4OnlyDomains
);
796 if (!name
|| !strcmp(name
, kPrefDnsLocalDomains
)) {
797 nsCString localDomains
;
798 Preferences::GetCString(kPrefDnsLocalDomains
, localDomains
);
799 MutexAutoLock
lock(mLock
);
800 mLocalDomains
.Clear();
801 for (const auto& token
:
802 nsCCharSeparatedTokenizerTemplate
<NS_IsAsciiWhitespace
,
803 nsTokenizerFlags::SeparatorOptional
>(
806 mLocalDomains
.Insert(token
);
809 if (!name
|| !strcmp(name
, kPrefDnsForceResolve
)) {
810 Preferences::GetCString(kPrefDnsForceResolve
, mForceResolve
);
811 mForceResolveOn
= !mForceResolve
.IsEmpty();
813 if (!name
|| !strcmp(name
, kPrefDnsMockHTTPSRRDomain
)) {
814 nsCString mockHTTPSRRDomain
;
815 Preferences::GetCString(kPrefDnsMockHTTPSRRDomain
, mockHTTPSRRDomain
);
816 if (mockHTTPSRRDomain
.IsEmpty()) {
817 mHasMockHTTPSRRDomainSet
= false;
819 mHasMockHTTPSRRDomainSet
= true;
820 MutexAutoLock
lock(mLock
);
821 mMockHTTPSRRDomain
= mockHTTPSRRDomain
;
827 nsDNSService::Init() {
828 MOZ_ASSERT(!mResolver
);
829 MOZ_ASSERT(NS_IsMainThread());
833 nsCOMPtr
<nsIObserverService
> observerService
=
834 mozilla::services::GetObserverService();
835 if (observerService
) {
836 observerService
->AddObserver(this, "last-pb-context-exited", false);
837 observerService
->AddObserver(this, NS_NETWORK_LINK_TOPIC
, false);
838 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false);
841 RefPtr
<nsHostResolver
> res
;
842 nsresult rv
= nsHostResolver::Create(getter_AddRefs(res
));
843 if (NS_SUCCEEDED(rv
)) {
844 // now, set all of our member variables while holding the lock
845 MutexAutoLock
lock(mLock
);
849 nsCOMPtr
<nsIPrefBranch
> prefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
851 // register as prefs observer
852 prefs
->AddObserver(kPrefDnsCacheEntries
, this, false);
853 prefs
->AddObserver(kPrefDnsCacheExpiration
, this, false);
854 prefs
->AddObserver(kPrefDnsCacheGrace
, this, false);
855 prefs
->AddObserver(kPrefIPv4OnlyDomains
, this, false);
856 prefs
->AddObserver(kPrefDnsLocalDomains
, this, false);
857 prefs
->AddObserver(kPrefDnsForceResolve
, this, false);
858 prefs
->AddObserver(kPrefDnsNotifyResolution
, this, false);
859 prefs
->AddObserver(kPrefDnsMockHTTPSRRDomain
, this, false);
860 AddPrefObserver(prefs
);
863 nsDNSPrefetch::Initialize(this);
865 RegisterWeakMemoryReporter(this);
867 nsCOMPtr
<nsIObliviousHttpService
> ohttpService(
868 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
870 mTrrService
= new TRRService();
871 if (NS_FAILED(mTrrService
->Init(mResolver
->IsNativeHTTPSEnabled()))) {
872 mTrrService
= nullptr;
879 nsDNSService::Shutdown() {
880 UnregisterWeakMemoryReporter(this);
882 RefPtr
<nsHostResolver
> res
;
884 MutexAutoLock
lock(mLock
);
885 res
= std::move(mResolver
);
888 // Shutdown outside lock.
892 nsCOMPtr
<nsIObserverService
> observerService
=
893 mozilla::services::GetObserverService();
894 if (observerService
) {
895 observerService
->RemoveObserver(this, NS_NETWORK_LINK_TOPIC
);
896 observerService
->RemoveObserver(this, "last-pb-context-exited");
897 observerService
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
903 bool nsDNSService::GetOffline() const {
904 bool offline
= false;
905 nsCOMPtr
<nsIIOService
> io
= do_GetService(NS_IOSERVICE_CONTRACTID
);
907 io
->GetOffline(&offline
);
913 nsDNSService::GetPrefetchEnabled(bool* outVal
) {
914 MutexAutoLock
lock(mLock
);
915 *outVal
= !mDisablePrefetch
;
920 nsDNSService::SetPrefetchEnabled(bool inVal
) {
921 MutexAutoLock
lock(mLock
);
922 mDisablePrefetch
= !inVal
;
926 already_AddRefed
<nsHostResolver
> nsDNSService::GetResolverLocked() {
927 MutexAutoLock
lock(mLock
);
928 return do_AddRef(mResolver
);
931 nsresult
nsDNSService::PreprocessHostname(bool aLocalDomain
,
932 const nsACString
& aInput
,
935 if (StaticPrefs::network_dns_blockDotOnion() &&
936 StringEndsWith(aInput
, ".onion"_ns
)) {
937 return NS_ERROR_UNKNOWN_HOST
;
941 aACE
.AssignLiteral("localhost");
945 if (mTrrService
&& mTrrService
->MaybeBootstrap(aInput
, aACE
)) {
949 if (mForceResolveOn
) {
950 MutexAutoLock
lock(mLock
);
951 if (!aInput
.LowerCaseEqualsASCII("localhost") &&
952 !aInput
.LowerCaseEqualsASCII("127.0.0.1")) {
953 aACE
.Assign(mForceResolve
);
958 if (!NS_SUCCEEDED(NS_DomainToASCIIAllowAnyGlyphfulASCII(aInput
, aACE
))) {
959 return NS_ERROR_FAILURE
;
964 bool nsDNSService::IsLocalDomain(const nsACString
& aHostname
) const {
965 bool localDomain
= mLocalDomains
.Contains(aHostname
);
966 if (StringEndsWith(aHostname
, "."_ns
)) {
967 localDomain
= localDomain
|| mLocalDomains
.Contains(Substring(
968 aHostname
, 0, aHostname
.Length() - 1));
973 nsresult
nsDNSService::AsyncResolveInternal(
974 const nsACString
& aHostname
, uint16_t type
, nsIDNSService::DNSFlags flags
,
975 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
,
976 nsIEventTarget
* target_
, const OriginAttributes
& aOriginAttributes
,
977 nsICancelable
** result
) {
978 // grab reference to global host resolver and IDN service. beware
979 // simultaneous shutdown!!
980 RefPtr
<nsHostResolver
> res
;
981 nsCOMPtr
<nsIEventTarget
> target
= target_
;
982 nsCOMPtr
<nsIDNSListener
> listener
= aListener
;
983 bool localDomain
= false;
985 MutexAutoLock
lock(mLock
);
987 if (mDisablePrefetch
&& (flags
& RESOLVE_SPECULATE
)) {
988 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
993 localDomain
= IsLocalDomain(aHostname
);
996 if (mNotifyResolution
) {
997 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1001 return NS_ERROR_OFFLINE
;
1004 if ((type
!= RESOLVE_TYPE_DEFAULT
) && (type
!= RESOLVE_TYPE_TXT
) &&
1005 (type
!= RESOLVE_TYPE_HTTPSSVC
)) {
1006 return NS_ERROR_INVALID_ARG
;
1009 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1010 // nsHostResolver returns NS_ERROR_UNKNOWN_HOST for lots of reasons.
1011 // We use a different error code to differentiate this failure and to make
1012 // it clear(er) where this error comes from.
1013 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1017 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, hostname
);
1018 if (NS_FAILED(rv
)) {
1022 if (GetOffline() && (!StaticPrefs::network_dns_offline_localhost() ||
1023 !hostname
.LowerCaseEqualsASCII("localhost"))) {
1024 flags
|= RESOLVE_OFFLINE
;
1027 // make sure JS callers get notification on the main thread
1028 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedListener
= do_QueryInterface(listener
);
1029 if (wrappedListener
&& !target
) {
1030 target
= GetMainThreadSerialEventTarget();
1034 listener
= new DNSListenerProxy(listener
, target
);
1038 (type
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, flags
);
1040 MOZ_ASSERT(listener
);
1041 RefPtr
<nsDNSAsyncRequest
> req
=
1042 new nsDNSAsyncRequest(res
, hostname
, DNSAdditionalInfo::URL(aInfo
), type
,
1043 aOriginAttributes
, listener
, flags
, af
);
1045 return NS_ERROR_OUT_OF_MEMORY
;
1048 if (type
== RESOLVE_TYPE_HTTPSSVC
&& mHasMockHTTPSRRDomainSet
) {
1049 MutexAutoLock
lock(mLock
);
1050 if (req
->mHost
== mMockHTTPSRRDomain
) {
1051 flags
|= nsIDNSService::RESOLVE_CREATE_MOCK_HTTPS_RR
;
1055 rv
= res
->ResolveHost(req
->mHost
, DNSAdditionalInfo::URL(aInfo
),
1056 DNSAdditionalInfo::Port(aInfo
), type
,
1057 req
->mOriginAttributes
, flags
, af
, req
);
1062 nsresult
nsDNSService::CancelAsyncResolveInternal(
1063 const nsACString
& aHostname
, uint16_t aType
, nsIDNSService::DNSFlags aFlags
,
1064 nsIDNSAdditionalInfo
* aInfo
, nsIDNSListener
* aListener
, nsresult aReason
,
1065 const OriginAttributes
& aOriginAttributes
) {
1066 // grab reference to global host resolver and IDN service. beware
1067 // simultaneous shutdown!!
1068 RefPtr
<nsHostResolver
> res
;
1069 bool localDomain
= false;
1071 MutexAutoLock
lock(mLock
);
1073 if (mDisablePrefetch
&& (aFlags
& RESOLVE_SPECULATE
)) {
1074 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL
;
1078 localDomain
= IsLocalDomain(aHostname
);
1081 return NS_ERROR_OFFLINE
;
1085 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, hostname
);
1086 if (NS_FAILED(rv
)) {
1091 (aType
!= RESOLVE_TYPE_DEFAULT
) ? 0 : GetAFForLookup(hostname
, aFlags
);
1093 res
->CancelAsyncRequest(hostname
, DNSAdditionalInfo::URL(aInfo
), aType
,
1094 aOriginAttributes
, aFlags
, af
, aListener
, aReason
);
1099 nsDNSService::AsyncResolve(const nsACString
& aHostname
,
1100 nsIDNSService::ResolveType aType
,
1101 nsIDNSService::DNSFlags flags
,
1102 nsIDNSAdditionalInfo
* aInfo
,
1103 nsIDNSListener
* listener
, nsIEventTarget
* target_
,
1104 JS::Handle
<JS::Value
> aOriginAttributes
,
1105 JSContext
* aCx
, uint8_t aArgc
,
1106 nsICancelable
** result
) {
1107 OriginAttributes attrs
;
1110 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1111 return NS_ERROR_INVALID_ARG
;
1115 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, listener
, target_
,
1120 nsDNSService::AsyncResolveNative(
1121 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1122 nsIDNSService::DNSFlags flags
, nsIDNSAdditionalInfo
* aInfo
,
1123 nsIDNSListener
* aListener
, nsIEventTarget
* target_
,
1124 const OriginAttributes
& aOriginAttributes
, nsICancelable
** result
) {
1125 return AsyncResolveInternal(aHostname
, aType
, flags
, aInfo
, aListener
,
1126 target_
, aOriginAttributes
, result
);
1130 nsDNSService::NewAdditionalInfo(const nsACString
& aTrrURL
, int32_t aPort
,
1131 nsIDNSAdditionalInfo
** aInfo
) {
1132 RefPtr
<DNSAdditionalInfo
> res
= new DNSAdditionalInfo(aTrrURL
, aPort
);
1138 nsDNSService::CancelAsyncResolve(const nsACString
& aHostname
,
1139 nsIDNSService::ResolveType aType
,
1140 nsIDNSService::DNSFlags aFlags
,
1141 nsIDNSAdditionalInfo
* aInfo
,
1142 nsIDNSListener
* aListener
, nsresult aReason
,
1143 JS::Handle
<JS::Value
> aOriginAttributes
,
1144 JSContext
* aCx
, uint8_t aArgc
) {
1145 OriginAttributes attrs
;
1148 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1149 return NS_ERROR_INVALID_ARG
;
1153 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1158 nsDNSService::CancelAsyncResolveNative(
1159 const nsACString
& aHostname
, nsIDNSService::ResolveType aType
,
1160 nsIDNSService::DNSFlags aFlags
, nsIDNSAdditionalInfo
* aInfo
,
1161 nsIDNSListener
* aListener
, nsresult aReason
,
1162 const OriginAttributes
& aOriginAttributes
) {
1163 return CancelAsyncResolveInternal(aHostname
, aType
, aFlags
, aInfo
, aListener
,
1164 aReason
, aOriginAttributes
);
1168 nsDNSService::Resolve(const nsACString
& aHostname
,
1169 nsIDNSService::DNSFlags flags
,
1170 JS::Handle
<JS::Value
> aOriginAttributes
, JSContext
* aCx
,
1171 uint8_t aArgc
, nsIDNSRecord
** result
) {
1172 OriginAttributes attrs
;
1175 if (!aOriginAttributes
.isObject() || !attrs
.Init(aCx
, aOriginAttributes
)) {
1176 return NS_ERROR_INVALID_ARG
;
1180 return ResolveNative(aHostname
, flags
, attrs
, result
);
1184 nsDNSService::ResolveNative(const nsACString
& aHostname
,
1185 nsIDNSService::DNSFlags flags
,
1186 const OriginAttributes
& aOriginAttributes
,
1187 nsIDNSRecord
** result
) {
1188 // Synchronous resolution is not available on the main thread.
1189 if (NS_IsMainThread()) {
1190 return NS_ERROR_NOT_AVAILABLE
;
1193 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1196 nsresult
nsDNSService::DeprecatedSyncResolve(
1197 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1198 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1199 return ResolveInternal(aHostname
, flags
, aOriginAttributes
, result
);
1202 nsresult
nsDNSService::ResolveInternal(
1203 const nsACString
& aHostname
, nsIDNSService::DNSFlags flags
,
1204 const OriginAttributes
& aOriginAttributes
, nsIDNSRecord
** result
) {
1205 // grab reference to global host resolver and IDN service. beware
1206 // simultaneous shutdown!!
1207 RefPtr
<nsHostResolver
> res
;
1208 bool localDomain
= false;
1210 MutexAutoLock
lock(mLock
);
1212 localDomain
= IsLocalDomain(aHostname
);
1215 if (mNotifyResolution
) {
1216 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname
));
1219 NS_ENSURE_TRUE(res
, NS_ERROR_OFFLINE
);
1222 nsresult rv
= PreprocessHostname(localDomain
, aHostname
, hostname
);
1223 if (NS_FAILED(rv
)) {
1227 if (GetOffline() && (!StaticPrefs::network_dns_offline_localhost() ||
1228 !hostname
.LowerCaseEqualsASCII("localhost"))) {
1229 flags
|= RESOLVE_OFFLINE
;
1232 if (DNSForbiddenByActiveProxy(aHostname
, flags
)) {
1233 return NS_ERROR_UNKNOWN_PROXY_HOST
;
1237 // sync resolve: since the host resolver only works asynchronously, we need
1238 // to use a mutex and a condvar to wait for the result. however, since the
1239 // result may be in the resolvers cache, we might get called back recursively
1240 // on the same thread. so, our mutex needs to be re-entrant. in other words,
1241 // we need to use a monitor! ;-)
1244 PRMonitor
* mon
= PR_NewMonitor();
1246 return NS_ERROR_OUT_OF_MEMORY
;
1249 PR_EnterMonitor(mon
);
1250 RefPtr
<nsDNSSyncRequest
> syncReq
= new nsDNSSyncRequest(mon
);
1252 uint16_t af
= GetAFForLookup(hostname
, flags
);
1254 // TRR uses the main thread for the HTTPS channel to the DoH server.
1255 // If this were to block the main thread while waiting for TRR it would
1256 // likely cause a deadlock. Instead we intentionally choose to not use TRR
1258 if (NS_IsMainThread()) {
1259 flags
|= RESOLVE_DISABLE_TRR
;
1262 rv
= res
->ResolveHost(hostname
, ""_ns
, -1, RESOLVE_TYPE_DEFAULT
,
1263 aOriginAttributes
, flags
, af
, syncReq
);
1264 if (NS_SUCCEEDED(rv
)) {
1266 while (!syncReq
->mDone
) {
1267 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
1270 if (NS_FAILED(syncReq
->mStatus
)) {
1271 rv
= syncReq
->mStatus
;
1273 NS_ASSERTION(syncReq
->mHostRecord
, "no host record");
1274 RefPtr
<nsDNSRecord
> rec
= new nsDNSRecord(syncReq
->mHostRecord
);
1279 PR_ExitMonitor(mon
);
1280 PR_DestroyMonitor(mon
);
1285 nsDNSService::GetMyHostName(nsACString
& result
) {
1287 if (PR_GetSystemInfo(PR_SI_HOSTNAME
, name
, sizeof(name
)) == PR_SUCCESS
) {
1291 return NS_ERROR_FAILURE
;
1295 nsDNSService::Observe(nsISupports
* subject
, const char* topic
,
1296 const char16_t
* data
) {
1297 bool flushCache
= false;
1298 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1300 if (!strcmp(topic
, NS_NETWORK_LINK_TOPIC
)) {
1301 nsAutoCString converted
= NS_ConvertUTF16toUTF8(data
);
1302 if (!strcmp(converted
.get(), NS_NETWORK_LINK_DATA_CHANGED
)) {
1305 } else if (!strcmp(topic
, "last-pb-context-exited")) {
1307 } else if (!strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
1308 ReadPrefs(NS_ConvertUTF16toUTF8(data
).get());
1309 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1310 } else if (!strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
1314 if (flushCache
&& resolver
) {
1315 resolver
->FlushCache(false);
1322 uint16_t nsDNSService::GetAFForLookup(const nsACString
& host
,
1323 nsIDNSService::DNSFlags flags
) {
1324 if (StaticPrefs::network_dns_disableIPv6() ||
1325 (flags
& RESOLVE_DISABLE_IPV6
)) {
1329 MutexAutoLock
lock(mLock
);
1331 uint16_t af
= PR_AF_UNSPEC
;
1333 if (!mIPv4OnlyDomains
.IsEmpty()) {
1334 const char *domain
, *domainEnd
, *end
;
1335 uint32_t hostLen
, domainLen
;
1337 // see if host is in one of the IPv4-only domains
1338 domain
= mIPv4OnlyDomains
.BeginReading();
1339 domainEnd
= mIPv4OnlyDomains
.EndReading();
1341 nsACString::const_iterator hostStart
;
1342 host
.BeginReading(hostStart
);
1343 hostLen
= host
.Length();
1346 // skip any whitespace
1347 while (*domain
== ' ' || *domain
== '\t') {
1351 // find end of this domain in the string
1352 end
= strchr(domain
, ',');
1357 // to see if the hostname is in the domain, check if the domain
1358 // matches the end of the hostname.
1359 domainLen
= end
- domain
;
1360 if (domainLen
&& hostLen
>= domainLen
) {
1361 const char* hostTail
= hostStart
.get() + hostLen
- domainLen
;
1362 if (nsCRT::strncasecmp(domain
, hostTail
, domainLen
) == 0) {
1363 // now, make sure either that the hostname is a direct match or
1364 // that the hostname begins with a dot.
1365 if (hostLen
== domainLen
|| *hostTail
== '.' ||
1366 *(hostTail
- 1) == '.') {
1377 if ((af
!= PR_AF_INET
) && (flags
& RESOLVE_DISABLE_IPV4
)) {
1385 nsDNSService::GetDNSCacheEntries(
1386 nsTArray
<mozilla::net::DNSCacheEntries
>* args
) {
1387 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1388 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1389 resolver
->GetDNSCacheEntries(args
);
1394 nsDNSService::ClearCache(bool aTrrToo
) {
1395 RefPtr
<nsHostResolver
> resolver
= GetResolverLocked();
1396 NS_ENSURE_TRUE(resolver
, NS_ERROR_NOT_INITIALIZED
);
1397 resolver
->FlushCache(aTrrToo
);
1401 // For testing purposes only
1403 nsDNSService::ReloadParentalControlEnabled() {
1405 mTrrService
->mParentalControlEnabled
=
1406 TRRService::ReloadParentalControlsEnabled();
1412 nsDNSService::SetDetectedTrrURI(const nsACString
& aURI
) {
1414 mTrrService
->SetDetectedTrrURI(aURI
);
1420 nsDNSService::SetHeuristicDetectionResult(nsITRRSkipReason::value aValue
) {
1422 mTrrService
->SetHeuristicDetectionResult(aValue
);
1428 nsDNSService::GetHeuristicDetectionResult(nsITRRSkipReason::value
* aValue
) {
1430 return NS_ERROR_NOT_AVAILABLE
;
1433 *aValue
= mTrrService
->GetHeuristicDetectionResult();
1438 nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue
,
1439 nsACString
& aName
) {
1440 return mozilla::net::GetTRRSkipReasonName(aValue
, aName
);
1444 nsDNSService::GetCurrentTrrURI(nsACString
& aURI
) {
1446 mTrrService
->GetURI(aURI
);
1452 nsDNSService::GetCurrentTrrMode(nsIDNSService::ResolverMode
* aMode
) {
1453 *aMode
= nsIDNSService::MODE_NATIVEONLY
; // The default mode.
1455 *aMode
= mTrrService
->Mode();
1461 nsDNSService::GetCurrentTrrConfirmationState(uint32_t* aConfirmationState
) {
1462 *aConfirmationState
= uint32_t(TRRService::CONFIRM_OFF
);
1464 *aConfirmationState
= mTrrService
->ConfirmationState();
1470 nsDNSService::GetTrrDomain(nsACString
& aTRRDomain
) {
1471 aTRRDomain
.Truncate();
1474 mTrrService
->GetURI(url
);
1476 nsCOMPtr
<nsIURI
> uri
;
1477 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), url
);
1478 if (NS_FAILED(rv
)) {
1479 // An empty TRR domain in case of invalid URL.
1482 return uri
->GetHost(aTRRDomain
);
1485 nsresult
nsDNSService::GetTRRDomainKey(nsACString
& aTRRDomain
) {
1486 aTRRDomain
= TRRService::ProviderKey();
1490 size_t nsDNSService::SizeOfIncludingThis(
1491 mozilla::MallocSizeOf mallocSizeOf
) const {
1492 // Measurement of the following members may be added later if DMD finds it
1497 size_t n
= mallocSizeOf(this);
1498 n
+= mResolver
? mResolver
->SizeOfIncludingThis(mallocSizeOf
) : 0;
1499 n
+= mIPv4OnlyDomains
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1500 n
+= mLocalDomains
.SizeOfExcludingThis(mallocSizeOf
);
1501 n
+= mFailedSVCDomainNames
.ShallowSizeOfExcludingThis(mallocSizeOf
);
1502 for (const auto& data
: mFailedSVCDomainNames
.Values()) {
1503 n
+= data
->ShallowSizeOfExcludingThis(mallocSizeOf
);
1504 for (const auto& name
: *data
) {
1505 n
+= name
.SizeOfExcludingThisIfUnshared(mallocSizeOf
);
1511 MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf
)
1514 nsDNSService::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1515 nsISupports
* aData
, bool aAnonymize
) {
1516 MOZ_COLLECT_REPORT("explicit/network/dns-service", KIND_HEAP
, UNITS_BYTES
,
1517 SizeOfIncludingThis(DNSServiceMallocSizeOf
),
1518 "Memory used for the DNS service.");
1524 nsDNSService::ReportFailedSVCDomainName(const nsACString
& aOwnerName
,
1525 const nsACString
& aSVCDomainName
) {
1526 MutexAutoLock
lock(mLock
);
1528 mFailedSVCDomainNames
.GetOrInsertNew(aOwnerName
, 1)
1529 ->AppendElement(aSVCDomainName
);
1534 nsDNSService::IsSVCDomainNameFailed(const nsACString
& aOwnerName
,
1535 const nsACString
& aSVCDomainName
,
1537 NS_ENSURE_ARG(aResult
);
1539 MutexAutoLock
lock(mLock
);
1541 nsTArray
<nsCString
>* failedList
= mFailedSVCDomainNames
.Get(aOwnerName
);
1546 *aResult
= failedList
->Contains(aSVCDomainName
);
1551 nsDNSService::ResetExcludedSVCDomainName(const nsACString
& aOwnerName
) {
1552 MutexAutoLock
lock(mLock
);
1553 mFailedSVCDomainNames
.Remove(aOwnerName
);
1558 nsDNSService::GetLastConfirmationStatus(nsresult
* aConfirmationStatus
) {
1560 return NS_ERROR_NOT_AVAILABLE
;
1562 *aConfirmationStatus
= mTrrService
->LastConfirmationStatus();
1566 NS_IMETHODIMP
nsDNSService::GetLastConfirmationSkipReason(
1567 TRRSkippedReason
* aSkipReason
) {
1569 return NS_ERROR_NOT_AVAILABLE
;
1571 *aSkipReason
= mTrrService
->LastConfirmationSkipReason();
1575 namespace mozilla::net
{
1576 nsresult
GetTRRSkipReasonName(TRRSkippedReason aReason
, nsACString
& aName
) {
1577 static_assert(TRRSkippedReason::TRR_UNSET
== 0);
1578 static_assert(TRRSkippedReason::TRR_OK
== 1);
1579 static_assert(TRRSkippedReason::TRR_NO_GSERVICE
== 2);
1580 static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL
== 3);
1581 static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT
== 4);
1582 static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED
== 5);
1583 static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED
== 6);
1584 static_assert(TRRSkippedReason::TRR_FAILED
== 7);
1585 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
== 8);
1586 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
== 9);
1587 static_assert(TRRSkippedReason::TRR_DISABLED_FLAG
== 10);
1588 static_assert(TRRSkippedReason::TRR_TIMEOUT
== 11);
1589 static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
== 12);
1590 static_assert(TRRSkippedReason::TRR_BROWSER_IS_OFFLINE
== 13);
1591 static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED
== 14);
1592 static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
== 15);
1593 static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
== 16);
1594 static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
== 17);
1595 static_assert(TRRSkippedReason::TRR_SEND_FAILED
== 18);
1596 static_assert(TRRSkippedReason::TRR_NET_RESET
== 19);
1597 static_assert(TRRSkippedReason::TRR_NET_TIMEOUT
== 20);
1598 static_assert(TRRSkippedReason::TRR_NET_REFUSED
== 21);
1599 static_assert(TRRSkippedReason::TRR_NET_INTERRUPT
== 22);
1600 static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
== 23);
1601 static_assert(TRRSkippedReason::TRR_NO_ANSWERS
== 24);
1602 static_assert(TRRSkippedReason::TRR_DECODE_FAILED
== 25);
1603 static_assert(TRRSkippedReason::TRR_EXCLUDED
== 26);
1604 static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
== 27);
1605 static_assert(TRRSkippedReason::TRR_RCODE_FAIL
== 28);
1606 static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY
== 29);
1607 static_assert(TRRSkippedReason::TRR_NXDOMAIN
== 30);
1608 static_assert(TRRSkippedReason::TRR_REQ_CANCELLED
== 31);
1609 static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE
== 32);
1610 static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
== 33);
1611 static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
== 34);
1612 static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED
== 35);
1613 static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED
== 36);
1614 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
==
1616 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
==
1618 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
== 39);
1619 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
== 40);
1620 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
== 41);
1621 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
==
1623 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
==
1625 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
==
1627 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
== 45);
1628 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
== 46);
1629 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
== 47);
1630 static_assert(TRRSkippedReason::TRR_BAD_URL
== 48);
1631 static_assert(TRRSkippedReason::TRR_SYSTEM_SLEEP_MODE
== 49);
1634 case TRRSkippedReason::TRR_UNSET
:
1635 aName
= "TRR_UNSET"_ns
;
1637 case TRRSkippedReason::TRR_OK
:
1638 aName
= "TRR_OK"_ns
;
1640 case TRRSkippedReason::TRR_NO_GSERVICE
:
1641 aName
= "TRR_NO_GSERVICE"_ns
;
1643 case TRRSkippedReason::TRR_PARENTAL_CONTROL
:
1644 aName
= "TRR_PARENTAL_CONTROL"_ns
;
1646 case TRRSkippedReason::TRR_OFF_EXPLICIT
:
1647 aName
= "TRR_OFF_EXPLICIT"_ns
;
1649 case TRRSkippedReason::TRR_REQ_MODE_DISABLED
:
1650 aName
= "TRR_REQ_MODE_DISABLED"_ns
;
1652 case TRRSkippedReason::TRR_MODE_NOT_ENABLED
:
1653 aName
= "TRR_MODE_NOT_ENABLED"_ns
;
1655 case TRRSkippedReason::TRR_FAILED
:
1656 aName
= "TRR_FAILED"_ns
;
1658 case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT
:
1659 aName
= "TRR_MODE_UNHANDLED_DEFAULT"_ns
;
1661 case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED
:
1662 aName
= "TRR_MODE_UNHANDLED_DISABLED"_ns
;
1664 case TRRSkippedReason::TRR_DISABLED_FLAG
:
1665 aName
= "TRR_DISABLED_FLAG"_ns
;
1667 case TRRSkippedReason::TRR_TIMEOUT
:
1668 aName
= "TRR_TIMEOUT"_ns
;
1670 case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL
:
1671 aName
= "TRR_CHANNEL_DNS_FAIL"_ns
;
1673 case TRRSkippedReason::TRR_BROWSER_IS_OFFLINE
:
1674 aName
= "TRR_BROWSER_IS_OFFLINE"_ns
;
1676 case TRRSkippedReason::TRR_NOT_CONFIRMED
:
1677 aName
= "TRR_NOT_CONFIRMED"_ns
;
1679 case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY
:
1680 aName
= "TRR_DID_NOT_MAKE_QUERY"_ns
;
1682 case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE
:
1683 aName
= "TRR_UNKNOWN_CHANNEL_FAILURE"_ns
;
1685 case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY
:
1686 aName
= "TRR_HOST_BLOCKED_TEMPORARY"_ns
;
1688 case TRRSkippedReason::TRR_SEND_FAILED
:
1689 aName
= "TRR_SEND_FAILED"_ns
;
1691 case TRRSkippedReason::TRR_NET_RESET
:
1692 aName
= "TRR_NET_RESET"_ns
;
1694 case TRRSkippedReason::TRR_NET_TIMEOUT
:
1695 aName
= "TRR_NET_TIMEOUT"_ns
;
1697 case TRRSkippedReason::TRR_NET_REFUSED
:
1698 aName
= "TRR_NET_REFUSED"_ns
;
1700 case TRRSkippedReason::TRR_NET_INTERRUPT
:
1701 aName
= "TRR_NET_INTERRUPT"_ns
;
1703 case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY
:
1704 aName
= "TRR_NET_INADEQ_SEQURITY"_ns
;
1706 case TRRSkippedReason::TRR_NO_ANSWERS
:
1707 aName
= "TRR_NO_ANSWERS"_ns
;
1709 case TRRSkippedReason::TRR_DECODE_FAILED
:
1710 aName
= "TRR_DECODE_FAILED"_ns
;
1712 case TRRSkippedReason::TRR_EXCLUDED
:
1713 aName
= "TRR_EXCLUDED"_ns
;
1715 case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR
:
1716 aName
= "TRR_SERVER_RESPONSE_ERR"_ns
;
1718 case TRRSkippedReason::TRR_RCODE_FAIL
:
1719 aName
= "TRR_RCODE_FAIL"_ns
;
1721 case TRRSkippedReason::TRR_NO_CONNECTIVITY
:
1722 aName
= "TRR_NO_CONNECTIVITY"_ns
;
1724 case TRRSkippedReason::TRR_NXDOMAIN
:
1725 aName
= "TRR_NXDOMAIN"_ns
;
1727 case TRRSkippedReason::TRR_REQ_CANCELLED
:
1728 aName
= "TRR_REQ_CANCELLED"_ns
;
1730 case TRRSkippedReason::ODOH_KEY_NOT_USABLE
:
1731 aName
= "ODOH_KEY_NOT_USABLE"_ns
;
1733 case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED
:
1734 aName
= "ODOH_UPDATE_KEY_FAILED"_ns
;
1736 case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE
:
1737 aName
= "ODOH_KEY_NOT_AVAILABLE"_ns
;
1739 case TRRSkippedReason::ODOH_ENCRYPTION_FAILED
:
1740 aName
= "ODOH_ENCRYPTION_FAILED"_ns
;
1742 case TRRSkippedReason::ODOH_DECRYPTION_FAILED
:
1743 aName
= "ODOH_DECRYPTION_FAILED"_ns
;
1745 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH
:
1746 aName
= "TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH"_ns
;
1748 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH
:
1749 aName
= "TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH"_ns
;
1751 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY
:
1752 aName
= "TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY"_ns
;
1754 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY
:
1755 aName
= "TRR_HEURISTIC_TRIPPED_CANARY"_ns
;
1757 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS
:
1758 aName
= "TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS"_ns
;
1760 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS
:
1761 aName
= "TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS"_ns
;
1763 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS
:
1764 aName
= "TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS"_ns
;
1766 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY
:
1767 aName
= "TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY"_ns
;
1769 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN
:
1770 aName
= "TRR_HEURISTIC_TRIPPED_VPN"_ns
;
1772 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY
:
1773 aName
= "TRR_HEURISTIC_TRIPPED_PROXY"_ns
;
1775 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT
:
1776 aName
= "TRR_HEURISTIC_TRIPPED_NRPT"_ns
;
1778 case TRRSkippedReason::TRR_BAD_URL
:
1779 aName
= "TRR_BAD_URL"_ns
;
1781 case TRRSkippedReason::TRR_SYSTEM_SLEEP_MODE
:
1782 aName
= "TRR_SYSTEM_SLEEP_MODE"_ns
;
1785 MOZ_ASSERT(false, "Unknown value");
1790 } // namespace mozilla::net