nsDNSService2.cpp (57153B)
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/. */ 6 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" 17 #include "nsString.h" 18 #include "nsCRT.h" 19 #include "nsNetCID.h" 20 #include "nsError.h" 21 #include "nsDNSPrefetch.h" 22 #include "nsThreadUtils.h" 23 #include "nsIProtocolProxyService.h" 24 #include "nsIObliviousHttp.h" 25 #include "prsystem.h" 26 #include "prnetdb.h" 27 #include "prmon.h" 28 #include "prio.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" 38 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 // Put DNSLogging.h at the end to avoid LOG being overwritten by other headers. 48 #include "DNSLogging.h" 49 50 using namespace mozilla; 51 using namespace mozilla::net; 52 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 kPrefDnsLocalDomains[] = "network.dns.localDomains"; 59 static const char kPrefDnsForceResolve[] = "network.dns.forceResolve"; 60 static const char kPrefDnsNotifyResolution[] = "network.dns.notifyResolution"; 61 static const char kPrefDnsMockHTTPSRRDomain[] = 62 "network.dns.mock_HTTPS_RR_domain"; 63 64 //----------------------------------------------------------------------------- 65 66 class nsDNSRecord : public nsIDNSAddrRecord { 67 public: 68 NS_DECL_THREADSAFE_ISUPPORTS 69 NS_DECL_NSIDNSRECORD 70 NS_DECL_NSIDNSADDRRECORD 71 72 explicit nsDNSRecord(nsHostRecord* hostRecord) { 73 mHostRecord = do_QueryObject(hostRecord); 74 } 75 76 private: 77 virtual ~nsDNSRecord() = default; 78 79 RefPtr<AddrHostRecord> mHostRecord; 80 // Since mIter is holding a weak reference to the NetAddr array we must 81 // make sure it is not released. So we also keep a RefPtr to the AddrInfo 82 // which is immutable. 83 RefPtr<AddrInfo> mAddrInfo; 84 nsTArray<NetAddr>::const_iterator mIter; 85 const NetAddr* iter() { 86 if (!mIter.GetArray()) { 87 return nullptr; 88 } 89 if (mIter.GetArray()->end() == mIter) { 90 return nullptr; 91 } 92 return &*mIter; 93 } 94 95 int mIterGenCnt = -1; // the generation count of 96 // mHostRecord->addr_info when we 97 // start iterating 98 bool mDone = false; 99 }; 100 101 NS_IMPL_ISUPPORTS(nsDNSRecord, nsIDNSRecord, nsIDNSAddrRecord) 102 103 NS_IMETHODIMP 104 nsDNSRecord::GetCanonicalName(nsACString& result) { 105 // this method should only be called if we have a CNAME 106 NS_ENSURE_TRUE(mHostRecord->flags & nsIDNSService::RESOLVE_CANONICAL_NAME, 107 NS_ERROR_NOT_AVAILABLE); 108 109 MutexAutoLock lock(mHostRecord->addr_info_lock); 110 111 // if the record is for an IP address literal, then the canonical 112 // host name is the IP address literal. 113 if (!mHostRecord->addr_info) { 114 result = mHostRecord->host; 115 return NS_OK; 116 } 117 118 if (mHostRecord->addr_info->CanonicalHostname().IsEmpty()) { 119 result = mHostRecord->addr_info->Hostname(); 120 } else { 121 result = mHostRecord->addr_info->CanonicalHostname(); 122 } 123 return NS_OK; 124 } 125 126 NS_IMETHODIMP 127 nsDNSRecord::IsTRR(bool* retval) { 128 MutexAutoLock lock(mHostRecord->addr_info_lock); 129 if (mHostRecord->addr_info) { 130 *retval = mHostRecord->addr_info->IsTRR(); 131 } else { 132 *retval = false; 133 } 134 return NS_OK; 135 } 136 137 NS_IMETHODIMP 138 nsDNSRecord::ResolvedInSocketProcess(bool* retval) { 139 *retval = false; 140 return NS_OK; 141 } 142 143 NS_IMETHODIMP 144 nsDNSRecord::GetTrrFetchDuration(double* aTime) { 145 MutexAutoLock lock(mHostRecord->addr_info_lock); 146 if (mHostRecord->addr_info && mHostRecord->addr_info->IsTRR()) { 147 *aTime = mHostRecord->addr_info->GetTrrFetchDuration(); 148 } else { 149 *aTime = 0; 150 } 151 return NS_OK; 152 } 153 154 NS_IMETHODIMP 155 nsDNSRecord::GetTrrFetchDurationNetworkOnly(double* aTime) { 156 MutexAutoLock lock(mHostRecord->addr_info_lock); 157 if (mHostRecord->addr_info && mHostRecord->addr_info->IsTRR()) { 158 *aTime = mHostRecord->addr_info->GetTrrFetchDurationNetworkOnly(); 159 } else { 160 *aTime = 0; 161 } 162 return NS_OK; 163 } 164 165 NS_IMETHODIMP 166 nsDNSRecord::GetNextAddr(uint16_t port, NetAddr* addr) { 167 if (mDone) { 168 return NS_ERROR_NOT_AVAILABLE; 169 } 170 171 mHostRecord->addr_info_lock.Lock(); 172 if (mHostRecord->addr_info) { 173 if (mIterGenCnt != mHostRecord->addr_info_gencnt) { 174 // mHostRecord->addr_info has changed, restart the iteration. 175 mIter = nsTArray<NetAddr>::const_iterator(); 176 mIterGenCnt = mHostRecord->addr_info_gencnt; 177 // Make sure to hold a RefPtr to the AddrInfo so we can iterate through 178 // the NetAddr array. 179 mAddrInfo = mHostRecord->addr_info; 180 } 181 182 bool startedFresh = !iter(); 183 184 do { 185 if (!iter()) { 186 mIter = mAddrInfo->Addresses().begin(); 187 } else { 188 mIter++; 189 } 190 } while (iter() && mHostRecord->Blocklisted(iter())); 191 192 if (!iter() && startedFresh) { 193 // If everything was blocklisted we want to reset the blocklist (and 194 // likely relearn it) and return the first address. That is better 195 // than nothing. 196 mHostRecord->ResetBlocklist(); 197 mIter = mAddrInfo->Addresses().begin(); 198 } 199 200 if (iter()) { 201 *addr = *mIter; 202 } 203 204 mHostRecord->addr_info_lock.Unlock(); 205 206 if (!iter()) { 207 mDone = true; 208 mIter = nsTArray<NetAddr>::const_iterator(); 209 mAddrInfo = nullptr; 210 mIterGenCnt = -1; 211 return NS_ERROR_NOT_AVAILABLE; 212 } 213 } else { 214 mHostRecord->addr_info_lock.Unlock(); 215 216 if (!mHostRecord->addr) { 217 // Both mHostRecord->addr_info and mHostRecord->addr are null. 218 // This can happen if mHostRecord->addr_info expired and the 219 // attempt to reresolve it failed. 220 return NS_ERROR_NOT_AVAILABLE; 221 } 222 *addr = *mHostRecord->addr; 223 mDone = true; 224 } 225 226 // set given port 227 port = htons(port); 228 if (addr->raw.family == AF_INET) { 229 addr->inet.port = port; 230 } else if (addr->raw.family == AF_INET6) { 231 addr->inet6.port = port; 232 } 233 234 return NS_OK; 235 } 236 237 NS_IMETHODIMP 238 nsDNSRecord::GetAddresses(nsTArray<NetAddr>& aAddressArray) { 239 if (mDone) { 240 return NS_ERROR_NOT_AVAILABLE; 241 } 242 243 mHostRecord->addr_info_lock.Lock(); 244 if (mHostRecord->addr_info) { 245 for (const auto& address : mHostRecord->addr_info->Addresses()) { 246 if (mHostRecord->Blocklisted(&address)) { 247 continue; 248 } 249 NetAddr* addr = aAddressArray.AppendElement(address); 250 if (addr->raw.family == AF_INET) { 251 addr->inet.port = 0; 252 } else if (addr->raw.family == AF_INET6) { 253 addr->inet6.port = 0; 254 } 255 } 256 mHostRecord->addr_info_lock.Unlock(); 257 } else { 258 mHostRecord->addr_info_lock.Unlock(); 259 260 if (!mHostRecord->addr) { 261 return NS_ERROR_NOT_AVAILABLE; 262 } 263 NetAddr* addr = aAddressArray.AppendElement(NetAddr()); 264 *addr = *mHostRecord->addr; 265 if (addr->raw.family == AF_INET) { 266 addr->inet.port = 0; 267 } else if (addr->raw.family == AF_INET6) { 268 addr->inet6.port = 0; 269 } 270 } 271 return NS_OK; 272 } 273 274 NS_IMETHODIMP 275 nsDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr** result) { 276 NetAddr addr; 277 nsresult rv = GetNextAddr(port, &addr); 278 if (NS_FAILED(rv)) { 279 return rv; 280 } 281 282 RefPtr<nsNetAddr> netaddr = new nsNetAddr(&addr); 283 netaddr.forget(result); 284 285 return NS_OK; 286 } 287 288 NS_IMETHODIMP 289 nsDNSRecord::GetNextAddrAsString(nsACString& result) { 290 NetAddr addr; 291 nsresult rv = GetNextAddr(0, &addr); 292 if (NS_FAILED(rv)) { 293 return rv; 294 } 295 296 char buf[kIPv6CStrBufSize]; 297 if (addr.ToStringBuffer(buf, sizeof(buf))) { 298 result.Assign(buf); 299 return NS_OK; 300 } 301 NS_ERROR("NetAddrToString failed unexpectedly"); 302 return NS_ERROR_FAILURE; // conversion failed for some reason 303 } 304 305 NS_IMETHODIMP 306 nsDNSRecord::HasMore(bool* result) { 307 if (mDone) { 308 *result = false; 309 return NS_OK; 310 } 311 312 nsTArray<NetAddr>::const_iterator iterCopy = mIter; 313 int iterGenCntCopy = mIterGenCnt; 314 315 NetAddr addr; 316 *result = NS_SUCCEEDED(GetNextAddr(0, &addr)); 317 318 mIter = iterCopy; 319 mIterGenCnt = iterGenCntCopy; 320 mDone = false; 321 322 return NS_OK; 323 } 324 325 NS_IMETHODIMP 326 nsDNSRecord::Rewind() { 327 mIter = nsTArray<NetAddr>::const_iterator(); 328 mIterGenCnt = -1; 329 mDone = false; 330 return NS_OK; 331 } 332 333 NS_IMETHODIMP 334 nsDNSRecord::ReportUnusable(uint16_t aPort) { 335 // right now we don't use the port in the blocklist 336 337 MutexAutoLock lock(mHostRecord->addr_info_lock); 338 339 // Check that we are using a real addr_info (as opposed to a single 340 // constant address), and that the generation count is valid. Otherwise, 341 // ignore the report. 342 343 if (mHostRecord->addr_info && mIterGenCnt == mHostRecord->addr_info_gencnt && 344 iter()) { 345 mHostRecord->ReportUnusable(iter()); 346 } 347 348 return NS_OK; 349 } 350 351 NS_IMETHODIMP 352 nsDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode* aMode) { 353 *aMode = mHostRecord->EffectiveTRRMode(); 354 return NS_OK; 355 } 356 357 NS_IMETHODIMP nsDNSRecord::GetTrrSkipReason( 358 nsITRRSkipReason::value* aTrrSkipReason) { 359 *aTrrSkipReason = mHostRecord->TrrSkipReason(); 360 return NS_OK; 361 } 362 363 NS_IMETHODIMP 364 nsDNSRecord::GetTtl(uint32_t* aTtl) { return mHostRecord->GetTtl(aTtl); } 365 366 NS_IMETHODIMP 367 nsDNSRecord::GetLastUpdate(mozilla::TimeStamp* aLastUpdate) { 368 MutexAutoLock lock(mHostRecord->addr_info_lock); 369 return mHostRecord->GetLastUpdate(aLastUpdate); 370 } 371 372 class nsDNSByTypeRecord : public nsIDNSByTypeRecord, 373 public nsIDNSTXTRecord, 374 public nsIDNSHTTPSSVCRecord { 375 public: 376 NS_DECL_THREADSAFE_ISUPPORTS 377 NS_DECL_NSIDNSRECORD 378 NS_DECL_NSIDNSBYTYPERECORD 379 NS_DECL_NSIDNSTXTRECORD 380 NS_DECL_NSIDNSHTTPSSVCRECORD 381 382 explicit nsDNSByTypeRecord(nsHostRecord* hostRecord) { 383 mHostRecord = do_QueryObject(hostRecord); 384 } 385 386 private: 387 virtual ~nsDNSByTypeRecord() = default; 388 RefPtr<TypeHostRecord> mHostRecord; 389 }; 390 391 NS_IMPL_ISUPPORTS(nsDNSByTypeRecord, nsIDNSRecord, nsIDNSByTypeRecord, 392 nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord) 393 394 NS_IMETHODIMP 395 nsDNSByTypeRecord::GetType(uint32_t* aType) { 396 *aType = mHostRecord->GetType(); 397 return NS_OK; 398 } 399 400 NS_IMETHODIMP 401 nsDNSByTypeRecord::GetRecords(CopyableTArray<nsCString>& aRecords) { 402 // deep copy 403 return mHostRecord->GetRecords(aRecords); 404 } 405 406 NS_IMETHODIMP 407 nsDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) { 408 // deep copy 409 return mHostRecord->GetRecordsAsOneString(aRecords); 410 } 411 412 NS_IMETHODIMP 413 nsDNSByTypeRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) { 414 return mHostRecord->GetRecords(aRecords); 415 } 416 417 NS_IMETHODIMP 418 nsDNSByTypeRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3, 419 nsISVCBRecord** aRecord) { 420 return mHostRecord->GetServiceModeRecord(aNoHttp2, aNoHttp3, aRecord); 421 } 422 423 NS_IMETHODIMP 424 nsDNSByTypeRecord::GetServiceModeRecordWithCname(bool aNoHttp2, bool aNoHttp3, 425 const nsACString& aCname, 426 nsISVCBRecord** aRecord) { 427 return mHostRecord->GetServiceModeRecordWithCname(aNoHttp2, aNoHttp3, aCname, 428 aRecord); 429 } 430 431 NS_IMETHODIMP 432 nsDNSByTypeRecord::IsTRR(bool* aResult) { return mHostRecord->IsTRR(aResult); } 433 434 NS_IMETHODIMP 435 nsDNSByTypeRecord::GetAllRecords(bool aNoHttp2, bool aNoHttp3, 436 const nsACString& aCname, 437 nsTArray<RefPtr<nsISVCBRecord>>& aResult) { 438 return mHostRecord->GetAllRecords(aNoHttp2, aNoHttp3, aCname, aResult); 439 } 440 441 NS_IMETHODIMP 442 nsDNSByTypeRecord::GetAllRecordsWithEchConfig( 443 bool aNoHttp2, bool aNoHttp3, const nsACString& aCname, 444 bool* aAllRecordsHaveEchConfig, bool* aAllRecordsInH3ExcludedList, 445 nsTArray<RefPtr<nsISVCBRecord>>& aResult) { 446 return mHostRecord->GetAllRecordsWithEchConfig( 447 aNoHttp2, aNoHttp3, aCname, aAllRecordsHaveEchConfig, 448 aAllRecordsInH3ExcludedList, aResult); 449 } 450 451 NS_IMETHODIMP 452 nsDNSByTypeRecord::GetHasIPAddresses(bool* aResult) { 453 return mHostRecord->GetHasIPAddresses(aResult); 454 } 455 456 NS_IMETHODIMP 457 nsDNSByTypeRecord::GetAllRecordsExcluded(bool* aResult) { 458 return mHostRecord->GetAllRecordsExcluded(aResult); 459 } 460 461 NS_IMETHODIMP 462 nsDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType* aResults) { 463 *aResults = mHostRecord->GetResults(); 464 return NS_OK; 465 } 466 467 NS_IMETHODIMP 468 nsDNSByTypeRecord::GetTtl(uint32_t* aTtl) { return mHostRecord->GetTtl(aTtl); } 469 470 //----------------------------------------------------------------------------- 471 472 class nsDNSAsyncRequest final : public nsResolveHostCallback, 473 public nsICancelable { 474 public: 475 NS_DECL_THREADSAFE_ISUPPORTS 476 NS_DECL_NSICANCELABLE 477 478 nsDNSAsyncRequest(nsHostResolver* res, const nsACString& host, 479 const nsACString& trrServer, uint16_t type, 480 const OriginAttributes& attrs, nsIDNSListener* listener, 481 nsIDNSService::DNSFlags flags, uint16_t af) 482 : mResolver(res), 483 mHost(host), 484 mTrrServer(trrServer), 485 mType(type), 486 mOriginAttributes(attrs), 487 mListener(listener), 488 mFlags(flags), 489 mAF(af) {} 490 491 void OnResolveHostComplete(nsHostResolver*, nsHostRecord*, nsresult) override; 492 // Returns TRUE if the DNS listener arg is the same as the member listener 493 // Used in Cancellations to remove DNS requests associated with a 494 // particular hostname and nsIDNSListener 495 bool EqualsAsyncListener(nsIDNSListener* aListener) override; 496 497 size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const override; 498 499 RefPtr<nsHostResolver> mResolver; 500 nsCString mHost; // hostname we're resolving 501 nsCString mTrrServer; // A trr server to be used. 502 uint16_t mType = 0; 503 const OriginAttributes 504 mOriginAttributes; // The originAttributes for this resolving 505 nsCOMPtr<nsIDNSListener> mListener; 506 nsIDNSService::DNSFlags mFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS; 507 uint16_t mAF = 0; 508 509 private: 510 virtual ~nsDNSAsyncRequest() = default; 511 }; 512 513 NS_IMPL_ISUPPORTS(nsDNSAsyncRequest, nsICancelable) 514 515 void nsDNSAsyncRequest::OnResolveHostComplete(nsHostResolver* resolver, 516 nsHostRecord* hostRecord, 517 nsresult status) { 518 // need to have an owning ref when we issue the callback to enable 519 // the caller to be able to addref/release multiple times without 520 // destroying the record prematurely. 521 nsCOMPtr<nsIDNSRecord> rec; 522 if (NS_SUCCEEDED(status) || 523 mFlags & nsIDNSService::RESOLVE_WANT_RECORD_ON_ERROR) { 524 MOZ_ASSERT(hostRecord, "no host record"); 525 if (!hostRecord) { 526 mListener->OnLookupComplete(this, nullptr, NS_ERROR_UNKNOWN_HOST); 527 mListener = nullptr; 528 return; 529 } 530 if (hostRecord->type != nsDNSService::RESOLVE_TYPE_DEFAULT) { 531 rec = new nsDNSByTypeRecord(hostRecord); 532 } else { 533 rec = new nsDNSRecord(hostRecord); 534 } 535 } 536 537 LOG(("OnResolveHostComplete: %s", mHost.get())); 538 mListener->OnLookupComplete(this, rec, status); 539 mListener = nullptr; 540 } 541 542 bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener* aListener) { 543 uintptr_t originalListenerAddr = reinterpret_cast<uintptr_t>(mListener.get()); 544 RefPtr<DNSListenerProxy> wrapper = do_QueryObject(mListener); 545 if (wrapper) { 546 originalListenerAddr = wrapper->GetOriginalListenerAddress(); 547 } 548 549 uintptr_t listenerAddr = reinterpret_cast<uintptr_t>(aListener); 550 return (listenerAddr == originalListenerAddr); 551 } 552 553 size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const { 554 size_t n = mallocSizeOf(this); 555 556 // The following fields aren't measured. 557 // - mHost, because it's a non-owning pointer 558 // - mResolver, because it's a non-owning pointer 559 // - mListener, because it's a non-owning pointer 560 561 return n; 562 } 563 564 NS_IMETHODIMP 565 nsDNSAsyncRequest::Cancel(nsresult reason) { 566 NS_ENSURE_ARG(NS_FAILED(reason)); 567 MOZ_DIAGNOSTIC_ASSERT(mResolver, "mResolver should not be null"); 568 mResolver->DetachCallback(mHost, mTrrServer, mType, mOriginAttributes, mFlags, 569 mAF, this, reason); 570 return NS_OK; 571 } 572 573 //----------------------------------------------------------------------------- 574 575 class DNSCacheRequest : public nsResolveHostCallback { 576 public: 577 NS_DECL_THREADSAFE_ISUPPORTS 578 579 DNSCacheRequest() = default; 580 581 void OnResolveHostComplete(nsHostResolver* resolver, nsHostRecord* hostRecord, 582 nsresult status) override { 583 mStatus = status; 584 mHostRecord = hostRecord; 585 } 586 587 bool EqualsAsyncListener(nsIDNSListener* aListener) override { 588 // Sync request: no listener to compare 589 return false; 590 } 591 592 size_t SizeOfIncludingThis( 593 mozilla::MallocSizeOf mallocSizeOf) const override { 594 size_t n = mallocSizeOf(this); 595 596 // The following fields aren't measured. 597 // - mHostRecord, because it's a non-owning pointer 598 599 // Measurement of the following members may be added later if DMD finds it 600 // is worthwhile: 601 // - nsDNSSyncRequest::mMonitor 602 603 return n; 604 } 605 606 nsresult mStatus = NS_OK; 607 RefPtr<nsHostRecord> mHostRecord; 608 609 protected: 610 virtual ~DNSCacheRequest() = default; 611 }; 612 613 NS_IMPL_ISUPPORTS0(DNSCacheRequest) 614 615 class nsDNSSyncRequest : public DNSCacheRequest { 616 public: 617 explicit nsDNSSyncRequest(PRMonitor* mon) : mMonitor(mon) {} 618 619 void OnResolveHostComplete(nsHostResolver*, nsHostRecord*, nsresult) override; 620 621 bool mDone = false; 622 623 private: 624 virtual ~nsDNSSyncRequest() = default; 625 626 PRMonitor* mMonitor = nullptr; 627 }; 628 629 void nsDNSSyncRequest::OnResolveHostComplete(nsHostResolver* resolver, 630 nsHostRecord* hostRecord, 631 nsresult status) { 632 // store results, and wake up nsDNSService::Resolve to process results. 633 PR_EnterMonitor(mMonitor); 634 mDone = true; 635 DNSCacheRequest::OnResolveHostComplete(resolver, hostRecord, status); 636 PR_Notify(mMonitor); 637 PR_ExitMonitor(mMonitor); 638 } 639 640 class NotifyDNSResolution : public Runnable { 641 public: 642 explicit NotifyDNSResolution(const nsACString& aHostname) 643 : mozilla::Runnable("NotifyDNSResolution"), mHostname(aHostname) {} 644 645 NS_IMETHOD Run() override { 646 MOZ_ASSERT(NS_IsMainThread()); 647 nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); 648 if (obs) { 649 obs->NotifyObservers(nullptr, "dns-resolution-request", 650 NS_ConvertUTF8toUTF16(mHostname).get()); 651 } 652 return NS_OK; 653 } 654 655 private: 656 nsCString mHostname; 657 }; 658 659 //----------------------------------------------------------------------------- 660 661 static StaticRefPtr<DNSServiceWrapper> gDNSServiceWrapper; 662 663 NS_IMPL_ISUPPORTS(DNSServiceWrapper, nsIDNSService, nsPIDNSService) 664 665 // static 666 already_AddRefed<nsIDNSService> DNSServiceWrapper::GetSingleton() { 667 if (!gDNSServiceWrapper) { 668 gDNSServiceWrapper = new DNSServiceWrapper(); 669 // Not strictly needed, but simple and avoids bypassing lock-checking 670 MutexAutoLock lock(gDNSServiceWrapper->mLock); 671 gDNSServiceWrapper->mDNSServiceInUse = ChildDNSService::GetSingleton(); 672 if (gDNSServiceWrapper->mDNSServiceInUse) { 673 ClearOnShutdown(&gDNSServiceWrapper); 674 nsDNSPrefetch::Initialize(gDNSServiceWrapper); 675 } else { 676 MutexAutoUnlock unlock( 677 gDNSServiceWrapper->mLock); // don't destroy with held lock 678 gDNSServiceWrapper = nullptr; 679 } 680 } 681 682 return do_AddRef(gDNSServiceWrapper); 683 } 684 685 // static 686 void DNSServiceWrapper::SwitchToBackupDNSService() { 687 if (!gDNSServiceWrapper) { 688 return; 689 } 690 691 gDNSServiceWrapper->mBackupDNSService = nsDNSService::GetSingleton(); 692 693 MutexAutoLock lock(gDNSServiceWrapper->mLock); 694 gDNSServiceWrapper->mBackupDNSService.swap( 695 gDNSServiceWrapper->mDNSServiceInUse); 696 } 697 698 nsIDNSService* DNSServiceWrapper::DNSService() { 699 MOZ_ASSERT(XRE_IsParentProcess()); 700 701 MutexAutoLock lock(mLock); 702 return mDNSServiceInUse.get(); 703 } 704 705 nsPIDNSService* DNSServiceWrapper::PIDNSService() { 706 MOZ_ASSERT(XRE_IsParentProcess()); 707 708 nsCOMPtr<nsPIDNSService> service = do_QueryInterface(DNSService()); 709 return service.get(); 710 } 711 712 //----------------------------------------------------------------------------- 713 NS_IMPL_ISUPPORTS_INHERITED(nsDNSService, DNSServiceBase, nsIDNSService, 714 nsPIDNSService, nsIMemoryReporter) 715 716 /****************************************************************************** 717 * nsDNSService impl: 718 * singleton instance ctor/dtor methods 719 ******************************************************************************/ 720 static StaticRefPtr<nsDNSService> gDNSService; 721 static Atomic<bool> gInited(false); 722 723 // Note: be careful of races! Called from multiple threads 724 already_AddRefed<nsIDNSService> GetOrInitDNSService() { 725 if (gInited) { 726 return nsDNSService::GetXPCOMSingleton(); 727 } 728 729 nsCOMPtr<nsIDNSService> dns = nullptr; 730 auto initTask = [&dns]() { 731 // In case someone inited it while we were waiting 732 if (gInited) { 733 dns = nsDNSService::GetXPCOMSingleton(); 734 return; 735 } 736 dns = do_GetService(NS_DNSSERVICE_CID); 737 }; 738 if (!NS_IsMainThread()) { 739 // Forward to the main thread synchronously. 740 RefPtr<nsIThread> mainThread = do_GetMainThread(); 741 if (!mainThread) { 742 return nullptr; 743 } 744 745 SyncRunnable::DispatchToThread( 746 mainThread, NS_NewRunnableFunction("GetOrInitDNSService", initTask)); 747 } else { 748 initTask(); 749 } 750 751 return dns.forget(); 752 } 753 754 already_AddRefed<nsIDNSService> nsDNSService::GetXPCOMSingleton() { 755 auto getDNSHelper = []() -> already_AddRefed<nsIDNSService> { 756 if (nsIOService::UseSocketProcess()) { 757 if (XRE_IsSocketProcess()) { 758 return GetSingleton(); 759 } 760 761 if (XRE_IsParentProcess()) { 762 return DNSServiceWrapper::GetSingleton(); 763 } 764 765 if (XRE_IsContentProcess()) { 766 return ChildDNSService::GetSingleton(); 767 } 768 769 return nullptr; 770 } 771 772 if (XRE_IsParentProcess()) { 773 return GetSingleton(); 774 } 775 776 if (XRE_IsContentProcess() || XRE_IsSocketProcess()) { 777 return ChildDNSService::GetSingleton(); 778 } 779 780 return nullptr; 781 }; 782 783 if (gInited) { 784 return getDNSHelper(); 785 } 786 787 nsCOMPtr<nsIDNSService> dns = getDNSHelper(); 788 if (dns) { 789 gInited = true; 790 } 791 return dns.forget(); 792 } 793 794 already_AddRefed<nsDNSService> nsDNSService::GetSingleton() { 795 MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess()); 796 MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), XRE_IsParentProcess()); 797 798 if (!gDNSService) { 799 if (!NS_IsMainThread()) { 800 return nullptr; 801 } 802 gDNSService = new nsDNSService(); 803 if (NS_SUCCEEDED(gDNSService->Init())) { 804 ClearOnShutdown(&gDNSService); 805 } else { 806 gDNSService = nullptr; 807 } 808 } 809 810 return do_AddRef(gDNSService); 811 } 812 813 void nsDNSService::ReadPrefs(const char* name) { 814 DNSServiceBase::ReadPrefs(name); 815 816 bool tmpbool; 817 818 // DNSservice prefs 819 if (!name || !strcmp(name, kPrefDnsNotifyResolution)) { 820 if (NS_SUCCEEDED( 821 Preferences::GetBool(kPrefDnsNotifyResolution, &tmpbool))) { 822 mNotifyResolution = tmpbool; 823 } 824 } 825 if (!name || !strcmp(name, kPrefIPv4OnlyDomains)) { 826 MutexAutoLock lock(mLock); 827 Preferences::GetCString(kPrefIPv4OnlyDomains, mIPv4OnlyDomains); 828 } 829 if (!name || !strcmp(name, kPrefDnsLocalDomains)) { 830 nsCString localDomains; 831 Preferences::GetCString(kPrefDnsLocalDomains, localDomains); 832 MutexAutoLock lock(mLock); 833 mLocalDomains.Clear(); 834 for (const auto& token : 835 nsCCharSeparatedTokenizerTemplate<NS_IsAsciiWhitespace, 836 nsTokenizerFlags::SeparatorOptional>( 837 localDomains, ',') 838 .ToRange()) { 839 mLocalDomains.Insert(token); 840 } 841 } 842 if (!name || !strcmp(name, kPrefDnsForceResolve)) { 843 Preferences::GetCString(kPrefDnsForceResolve, mForceResolve); 844 mForceResolveOn = !mForceResolve.IsEmpty(); 845 } 846 if (!name || !strcmp(name, kPrefDnsMockHTTPSRRDomain)) { 847 nsCString mockHTTPSRRDomain; 848 Preferences::GetCString(kPrefDnsMockHTTPSRRDomain, mockHTTPSRRDomain); 849 if (mockHTTPSRRDomain.IsEmpty()) { 850 mHasMockHTTPSRRDomainSet = false; 851 } else { 852 mHasMockHTTPSRRDomainSet = true; 853 MutexAutoLock lock(mLock); 854 mMockHTTPSRRDomain = mockHTTPSRRDomain; 855 } 856 } 857 } 858 859 NS_IMETHODIMP 860 nsDNSService::Init() { 861 MOZ_ASSERT(NS_IsMainThread()); 862 863 ReadPrefs(nullptr); 864 865 nsCOMPtr<nsIObserverService> observerService = 866 mozilla::services::GetObserverService(); 867 if (observerService) { 868 observerService->AddObserver(this, "last-pb-context-exited", false); 869 observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false); 870 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); 871 } 872 873 RefPtr<nsHostResolver> res; 874 nsresult rv = nsHostResolver::Create(getter_AddRefs(res)); 875 if (NS_SUCCEEDED(rv)) { 876 // now, set all of our member variables while holding the lock 877 MutexAutoLock lock(mLock); 878 MOZ_ASSERT(!mResolver); 879 mResolver = res; 880 } 881 882 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 883 if (prefs) { 884 // register as prefs observer 885 prefs->AddObserver(kPrefDnsCacheEntries, this, false); 886 prefs->AddObserver(kPrefDnsCacheExpiration, this, false); 887 prefs->AddObserver(kPrefDnsCacheGrace, this, false); 888 prefs->AddObserver(kPrefIPv4OnlyDomains, this, false); 889 prefs->AddObserver(kPrefDnsLocalDomains, this, false); 890 prefs->AddObserver(kPrefDnsForceResolve, this, false); 891 prefs->AddObserver(kPrefDnsNotifyResolution, this, false); 892 prefs->AddObserver(kPrefDnsMockHTTPSRRDomain, this, false); 893 AddPrefObserver(prefs); 894 } 895 896 nsDNSPrefetch::Initialize(this); 897 898 RegisterWeakMemoryReporter(this); 899 900 nsCOMPtr<nsIObliviousHttpService> ohttpService( 901 do_GetService("@mozilla.org/network/oblivious-http-service;1")); 902 903 mTrrService = new TRRService(); 904 bool httpsEnabled; 905 { 906 MutexAutoLock lock(mLock); 907 httpsEnabled = mResolver->IsNativeHTTPSEnabled(); 908 } 909 if (NS_FAILED(mTrrService->Init(httpsEnabled))) { 910 mTrrService = nullptr; 911 } 912 913 return NS_OK; 914 } 915 916 NS_IMETHODIMP 917 nsDNSService::Shutdown() { 918 UnregisterWeakMemoryReporter(this); 919 920 RefPtr<nsHostResolver> res; 921 { 922 MutexAutoLock lock(mLock); 923 res = std::move(mResolver); 924 } 925 if (res) { 926 // Shutdown outside lock. 927 res->Shutdown(); 928 } 929 930 nsCOMPtr<nsIObserverService> observerService = 931 mozilla::services::GetObserverService(); 932 if (observerService) { 933 observerService->RemoveObserver(this, NS_NETWORK_LINK_TOPIC); 934 observerService->RemoveObserver(this, "last-pb-context-exited"); 935 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); 936 } 937 938 return NS_OK; 939 } 940 941 bool nsDNSService::GetOffline() const { 942 bool offline = false; 943 nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID); 944 if (io) { 945 io->GetOffline(&offline); 946 } 947 return offline; 948 } 949 950 NS_IMETHODIMP 951 nsDNSService::GetPrefetchEnabled(bool* outVal) { 952 MutexAutoLock lock(mLock); 953 *outVal = !mDisablePrefetch; 954 return NS_OK; 955 } 956 957 NS_IMETHODIMP 958 nsDNSService::SetPrefetchEnabled(bool inVal) { 959 MutexAutoLock lock(mLock); 960 mDisablePrefetch = !inVal; 961 return NS_OK; 962 } 963 964 already_AddRefed<nsHostResolver> nsDNSService::GetResolverLocked() { 965 MutexAutoLock lock(mLock); 966 return do_AddRef(mResolver); 967 } 968 969 nsresult nsDNSService::PreprocessHostname(bool aLocalDomain, 970 const nsACString& aInput, 971 nsACString& aACE) { 972 // Enforce RFC 7686 973 if (StaticPrefs::network_dns_blockDotOnion() && 974 StringEndsWith(aInput, ".onion"_ns)) { 975 return NS_ERROR_UNKNOWN_HOST; 976 } 977 978 if (aLocalDomain) { 979 aACE.AssignLiteral("localhost"); 980 return NS_OK; 981 } 982 983 if (mTrrService && mTrrService->MaybeBootstrap(aInput, aACE)) { 984 return NS_OK; 985 } 986 987 if (mForceResolveOn) { 988 MutexAutoLock lock(mLock); 989 if (!aInput.LowerCaseEqualsASCII("localhost") && 990 !aInput.LowerCaseEqualsASCII("127.0.0.1")) { 991 aACE.Assign(mForceResolve); 992 return NS_OK; 993 } 994 } 995 996 if (!NS_SUCCEEDED(NS_DomainToASCIIAllowAnyGlyphfulASCII(aInput, aACE))) { 997 return NS_ERROR_FAILURE; 998 } 999 return NS_OK; 1000 } 1001 1002 bool nsDNSService::IsLocalDomain(const nsACString& aHostname) const { 1003 bool localDomain = mLocalDomains.Contains(aHostname); 1004 if (StringEndsWith(aHostname, "."_ns)) { 1005 localDomain = localDomain || mLocalDomains.Contains(Substring( 1006 aHostname, 0, aHostname.Length() - 1)); 1007 } 1008 return localDomain; 1009 } 1010 1011 nsresult nsDNSService::AsyncResolveInternal( 1012 const nsACString& aHostname, uint16_t type, nsIDNSService::DNSFlags flags, 1013 nsIDNSAdditionalInfo* aInfo, nsIDNSListener* aListener, 1014 nsIEventTarget* target_, const OriginAttributes& aOriginAttributes, 1015 nsICancelable** result) { 1016 // grab reference to global host resolver and IDN service. beware 1017 // simultaneous shutdown!! 1018 RefPtr<nsHostResolver> res; 1019 nsCOMPtr<nsIEventTarget> target = target_; 1020 nsCOMPtr<nsIDNSListener> listener = aListener; 1021 bool localDomain = false; 1022 { 1023 MutexAutoLock lock(mLock); 1024 1025 if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) { 1026 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL; 1027 } 1028 1029 res = mResolver; 1030 1031 localDomain = IsLocalDomain(aHostname); 1032 } 1033 1034 if (mNotifyResolution) { 1035 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname)); 1036 } 1037 1038 if (!res) { 1039 return NS_ERROR_OFFLINE; 1040 } 1041 1042 if ((type != RESOLVE_TYPE_DEFAULT) && (type != RESOLVE_TYPE_TXT) && 1043 (type != RESOLVE_TYPE_HTTPSSVC)) { 1044 return NS_ERROR_INVALID_ARG; 1045 } 1046 1047 if (DNSForbiddenByActiveProxy(aHostname, flags)) { 1048 // nsHostResolver returns NS_ERROR_UNKNOWN_HOST for lots of reasons. 1049 // We use a different error code to differentiate this failure and to make 1050 // it clear(er) where this error comes from. 1051 return NS_ERROR_UNKNOWN_PROXY_HOST; 1052 } 1053 1054 nsCString hostname; 1055 nsresult rv = PreprocessHostname(localDomain, aHostname, hostname); 1056 if (NS_FAILED(rv)) { 1057 return rv; 1058 } 1059 1060 if (GetOffline() && (!StaticPrefs::network_dns_offline_localhost() || 1061 !hostname.LowerCaseEqualsASCII("localhost"))) { 1062 flags |= RESOLVE_OFFLINE; 1063 } 1064 1065 // make sure JS callers get notification on the main thread 1066 nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener); 1067 if (wrappedListener && !target) { 1068 target = GetMainThreadSerialEventTarget(); 1069 } 1070 1071 if (target) { 1072 listener = new DNSListenerProxy(listener, target); 1073 } 1074 1075 uint16_t af = 1076 (type != RESOLVE_TYPE_DEFAULT) ? 0 : GetAFForLookup(hostname, flags); 1077 1078 MOZ_ASSERT(listener); 1079 RefPtr<nsDNSAsyncRequest> req = 1080 new nsDNSAsyncRequest(res, hostname, DNSAdditionalInfo::URL(aInfo), type, 1081 aOriginAttributes, listener, flags, af); 1082 if (!req) { 1083 return NS_ERROR_OUT_OF_MEMORY; 1084 } 1085 1086 if (type == RESOLVE_TYPE_HTTPSSVC && mHasMockHTTPSRRDomainSet) { 1087 MutexAutoLock lock(mLock); 1088 if (req->mHost == mMockHTTPSRRDomain) { 1089 flags |= nsIDNSService::RESOLVE_CREATE_MOCK_HTTPS_RR; 1090 } 1091 } 1092 1093 rv = res->ResolveHost(req->mHost, DNSAdditionalInfo::URL(aInfo), 1094 DNSAdditionalInfo::Port(aInfo), type, 1095 req->mOriginAttributes, flags, af, req); 1096 req.forget(result); 1097 return rv; 1098 } 1099 1100 nsresult nsDNSService::CancelAsyncResolveInternal( 1101 const nsACString& aHostname, uint16_t aType, nsIDNSService::DNSFlags aFlags, 1102 nsIDNSAdditionalInfo* aInfo, nsIDNSListener* aListener, nsresult aReason, 1103 const OriginAttributes& aOriginAttributes) { 1104 // grab reference to global host resolver and IDN service. beware 1105 // simultaneous shutdown!! 1106 RefPtr<nsHostResolver> res; 1107 bool localDomain = false; 1108 { 1109 MutexAutoLock lock(mLock); 1110 1111 if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) { 1112 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL; 1113 } 1114 1115 res = mResolver; 1116 localDomain = IsLocalDomain(aHostname); 1117 } 1118 if (!res) { 1119 return NS_ERROR_OFFLINE; 1120 } 1121 1122 nsCString hostname; 1123 nsresult rv = PreprocessHostname(localDomain, aHostname, hostname); 1124 if (NS_FAILED(rv)) { 1125 return rv; 1126 } 1127 1128 uint16_t af = 1129 (aType != RESOLVE_TYPE_DEFAULT) ? 0 : GetAFForLookup(hostname, aFlags); 1130 1131 res->CancelAsyncRequest(hostname, DNSAdditionalInfo::URL(aInfo), aType, 1132 aOriginAttributes, aFlags, af, aListener, aReason); 1133 return NS_OK; 1134 } 1135 1136 NS_IMETHODIMP 1137 nsDNSService::AsyncResolve(const nsACString& aHostname, 1138 nsIDNSService::ResolveType aType, 1139 nsIDNSService::DNSFlags flags, 1140 nsIDNSAdditionalInfo* aInfo, 1141 nsIDNSListener* listener, nsIEventTarget* target_, 1142 JS::Handle<JS::Value> aOriginAttributes, 1143 JSContext* aCx, uint8_t aArgc, 1144 nsICancelable** result) { 1145 OriginAttributes attrs; 1146 1147 LOG(("DNSService::AsyncResolve %s", PromiseFlatCString(aHostname).get())); 1148 if (aArgc == 1) { 1149 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { 1150 return NS_ERROR_INVALID_ARG; 1151 } 1152 } 1153 1154 return AsyncResolveInternal(aHostname, aType, flags, aInfo, listener, target_, 1155 attrs, result); 1156 } 1157 1158 NS_IMETHODIMP 1159 nsDNSService::AsyncResolveNative( 1160 const nsACString& aHostname, nsIDNSService::ResolveType aType, 1161 nsIDNSService::DNSFlags flags, nsIDNSAdditionalInfo* aInfo, 1162 nsIDNSListener* aListener, nsIEventTarget* target_, 1163 const OriginAttributes& aOriginAttributes, nsICancelable** result) { 1164 return AsyncResolveInternal(aHostname, aType, flags, aInfo, aListener, 1165 target_, aOriginAttributes, result); 1166 } 1167 1168 NS_IMETHODIMP 1169 nsDNSService::NewAdditionalInfo(const nsACString& aTrrURL, int32_t aPort, 1170 nsIDNSAdditionalInfo** aInfo) { 1171 RefPtr<DNSAdditionalInfo> res = new DNSAdditionalInfo(aTrrURL, aPort); 1172 res.forget(aInfo); 1173 return NS_OK; 1174 } 1175 1176 NS_IMETHODIMP 1177 nsDNSService::CancelAsyncResolve(const nsACString& aHostname, 1178 nsIDNSService::ResolveType aType, 1179 nsIDNSService::DNSFlags aFlags, 1180 nsIDNSAdditionalInfo* aInfo, 1181 nsIDNSListener* aListener, nsresult aReason, 1182 JS::Handle<JS::Value> aOriginAttributes, 1183 JSContext* aCx, uint8_t aArgc) { 1184 OriginAttributes attrs; 1185 1186 if (aArgc == 1) { 1187 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { 1188 return NS_ERROR_INVALID_ARG; 1189 } 1190 } 1191 1192 return CancelAsyncResolveInternal(aHostname, aType, aFlags, aInfo, aListener, 1193 aReason, attrs); 1194 } 1195 1196 NS_IMETHODIMP 1197 nsDNSService::CancelAsyncResolveNative( 1198 const nsACString& aHostname, nsIDNSService::ResolveType aType, 1199 nsIDNSService::DNSFlags aFlags, nsIDNSAdditionalInfo* aInfo, 1200 nsIDNSListener* aListener, nsresult aReason, 1201 const OriginAttributes& aOriginAttributes) { 1202 return CancelAsyncResolveInternal(aHostname, aType, aFlags, aInfo, aListener, 1203 aReason, aOriginAttributes); 1204 } 1205 1206 NS_IMETHODIMP 1207 nsDNSService::Resolve(const nsACString& aHostname, 1208 nsIDNSService::DNSFlags flags, 1209 JS::Handle<JS::Value> aOriginAttributes, JSContext* aCx, 1210 uint8_t aArgc, nsIDNSRecord** result) { 1211 OriginAttributes attrs; 1212 1213 if (aArgc == 1) { 1214 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { 1215 return NS_ERROR_INVALID_ARG; 1216 } 1217 } 1218 1219 return ResolveNative(aHostname, flags, attrs, result); 1220 } 1221 1222 NS_IMETHODIMP 1223 nsDNSService::ResolveNative(const nsACString& aHostname, 1224 nsIDNSService::DNSFlags flags, 1225 const OriginAttributes& aOriginAttributes, 1226 nsIDNSRecord** result) { 1227 // Synchronous resolution is not allowed on the main thread. 1228 // However, if RESOLVE_OFFLINE is set, we're only reading from the DNS cache, 1229 // so it's safe to allow this on the main thread. 1230 if (NS_IsMainThread() && !(flags & nsIDNSService::RESOLVE_OFFLINE)) { 1231 return NS_ERROR_NOT_AVAILABLE; 1232 } 1233 1234 return ResolveInternal(aHostname, flags, aOriginAttributes, result); 1235 } 1236 1237 nsresult nsDNSService::DeprecatedSyncResolve( 1238 const nsACString& aHostname, nsIDNSService::DNSFlags flags, 1239 const OriginAttributes& aOriginAttributes, nsIDNSRecord** result) { 1240 return ResolveInternal(aHostname, flags, aOriginAttributes, result); 1241 } 1242 1243 nsresult nsDNSService::ResolveInternal( 1244 const nsACString& aHostname, nsIDNSService::DNSFlags flags, 1245 const OriginAttributes& aOriginAttributes, nsIDNSRecord** result) { 1246 // grab reference to global host resolver and IDN service. beware 1247 // simultaneous shutdown!! 1248 RefPtr<nsHostResolver> res; 1249 bool localDomain = false; 1250 { 1251 MutexAutoLock lock(mLock); 1252 res = mResolver; 1253 localDomain = IsLocalDomain(aHostname); 1254 } 1255 1256 if (mNotifyResolution) { 1257 NS_DispatchToMainThread(new NotifyDNSResolution(aHostname)); 1258 } 1259 1260 NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE); 1261 1262 nsCString hostname; 1263 nsresult rv = PreprocessHostname(localDomain, aHostname, hostname); 1264 if (NS_FAILED(rv)) { 1265 return rv; 1266 } 1267 1268 if (GetOffline() && (!StaticPrefs::network_dns_offline_localhost() || 1269 !hostname.LowerCaseEqualsASCII("localhost"))) { 1270 flags |= RESOLVE_OFFLINE; 1271 } 1272 1273 if (DNSForbiddenByActiveProxy(aHostname, flags)) { 1274 return NS_ERROR_UNKNOWN_PROXY_HOST; 1275 } 1276 1277 // Since RESOLVE_OFFLINE is set, we can use DNSCacheRequest to retrieve the 1278 // cached result directly. 1279 if (flags & RESOLVE_OFFLINE) { 1280 RefPtr<DNSCacheRequest> req = new DNSCacheRequest(); 1281 uint16_t af = GetAFForLookup(hostname, flags); 1282 rv = res->ResolveHost(hostname, ""_ns, -1, RESOLVE_TYPE_DEFAULT, 1283 aOriginAttributes, flags, af, req); 1284 if (NS_SUCCEEDED(rv)) { 1285 RefPtr<nsDNSRecord> rec = new nsDNSRecord(req->mHostRecord); 1286 rec.forget(result); 1287 } 1288 return rv; 1289 } 1290 1291 // 1292 // sync resolve: since the host resolver only works asynchronously, we need 1293 // to use a mutex and a condvar to wait for the result. however, since the 1294 // result may be in the resolvers cache, we might get called back recursively 1295 // on the same thread. so, our mutex needs to be re-entrant. in other words, 1296 // we need to use a monitor! ;-) 1297 // 1298 1299 PRMonitor* mon = PR_NewMonitor(); 1300 if (!mon) { 1301 return NS_ERROR_OUT_OF_MEMORY; 1302 } 1303 1304 PR_EnterMonitor(mon); 1305 RefPtr<nsDNSSyncRequest> syncReq = new nsDNSSyncRequest(mon); 1306 1307 uint16_t af = GetAFForLookup(hostname, flags); 1308 1309 // TRR uses the main thread for the HTTPS channel to the DoH server. 1310 // If this were to block the main thread while waiting for TRR it would 1311 // likely cause a deadlock. Instead we intentionally choose to not use TRR 1312 // for this. 1313 if (NS_IsMainThread()) { 1314 flags |= RESOLVE_DISABLE_TRR; 1315 } 1316 1317 rv = res->ResolveHost(hostname, ""_ns, -1, RESOLVE_TYPE_DEFAULT, 1318 aOriginAttributes, flags, af, syncReq); 1319 if (NS_SUCCEEDED(rv)) { 1320 // wait for result 1321 while (!syncReq->mDone) { 1322 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); 1323 } 1324 1325 if (NS_FAILED(syncReq->mStatus)) { 1326 rv = syncReq->mStatus; 1327 } else { 1328 NS_ASSERTION(syncReq->mHostRecord, "no host record"); 1329 RefPtr<nsDNSRecord> rec = new nsDNSRecord(syncReq->mHostRecord); 1330 rec.forget(result); 1331 } 1332 } 1333 1334 PR_ExitMonitor(mon); 1335 PR_DestroyMonitor(mon); 1336 return rv; 1337 } 1338 1339 NS_IMETHODIMP 1340 nsDNSService::GetMyHostName(nsACString& result) { 1341 char name[100]; 1342 if (PR_GetSystemInfo(PR_SI_HOSTNAME, name, sizeof(name)) == PR_SUCCESS) { 1343 result = name; 1344 return NS_OK; 1345 } 1346 return NS_ERROR_FAILURE; 1347 } 1348 1349 NS_IMETHODIMP 1350 nsDNSService::Observe(nsISupports* subject, const char* topic, 1351 const char16_t* data) { 1352 bool flushCache = false; 1353 RefPtr<nsHostResolver> resolver = GetResolverLocked(); 1354 1355 if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) { 1356 nsAutoCString converted = NS_ConvertUTF16toUTF8(data); 1357 if (!strcmp(converted.get(), NS_NETWORK_LINK_DATA_CHANGED)) { 1358 flushCache = true; 1359 } 1360 } else if (!strcmp(topic, "last-pb-context-exited")) { 1361 flushCache = true; 1362 } else if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { 1363 ReadPrefs(NS_ConvertUTF16toUTF8(data).get()); 1364 NS_ENSURE_TRUE(resolver, NS_ERROR_NOT_INITIALIZED); 1365 } else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { 1366 Shutdown(); 1367 } 1368 1369 if (flushCache && resolver) { 1370 resolver->FlushCache(false); 1371 return NS_OK; 1372 } 1373 1374 return NS_OK; 1375 } 1376 1377 uint16_t nsDNSService::GetAFForLookup(const nsACString& host, 1378 nsIDNSService::DNSFlags flags) { 1379 if (StaticPrefs::network_dns_disableIPv6() || 1380 (flags & RESOLVE_DISABLE_IPV6)) { 1381 return PR_AF_INET; 1382 } 1383 1384 MutexAutoLock lock(mLock); 1385 1386 uint16_t af = PR_AF_UNSPEC; 1387 1388 if (!mIPv4OnlyDomains.IsEmpty()) { 1389 const char *domain, *domainEnd, *end; 1390 uint32_t hostLen, domainLen; 1391 1392 // see if host is in one of the IPv4-only domains 1393 domain = mIPv4OnlyDomains.BeginReading(); 1394 domainEnd = mIPv4OnlyDomains.EndReading(); 1395 1396 nsACString::const_iterator hostStart; 1397 host.BeginReading(hostStart); 1398 hostLen = host.Length(); 1399 1400 do { 1401 // skip any whitespace 1402 while (*domain == ' ' || *domain == '\t') { 1403 ++domain; 1404 } 1405 1406 // find end of this domain in the string 1407 end = strchr(domain, ','); 1408 if (!end) { 1409 end = domainEnd; 1410 } 1411 1412 // to see if the hostname is in the domain, check if the domain 1413 // matches the end of the hostname. 1414 domainLen = end - domain; 1415 if (domainLen && hostLen >= domainLen) { 1416 const char* hostTail = hostStart.get() + hostLen - domainLen; 1417 if (nsCRT::strncasecmp(domain, hostTail, domainLen) == 0) { 1418 // now, make sure either that the hostname is a direct match or 1419 // that the hostname begins with a dot. 1420 if (hostLen == domainLen || *hostTail == '.' || 1421 *(hostTail - 1) == '.') { 1422 af = PR_AF_INET; 1423 break; 1424 } 1425 } 1426 } 1427 1428 domain = end + 1; 1429 } while (*end); 1430 } 1431 1432 if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) { 1433 af = PR_AF_INET6; 1434 } 1435 1436 return af; 1437 } 1438 1439 NS_IMETHODIMP 1440 nsDNSService::GetDNSCacheEntries( 1441 nsTArray<mozilla::net::DNSCacheEntries>* args) { 1442 RefPtr<nsHostResolver> resolver = GetResolverLocked(); 1443 NS_ENSURE_TRUE(resolver, NS_ERROR_NOT_INITIALIZED); 1444 resolver->GetDNSCacheEntries(args); 1445 return NS_OK; 1446 } 1447 1448 NS_IMETHODIMP 1449 nsDNSService::ClearCache(bool aTrrToo) { 1450 RefPtr<nsHostResolver> resolver = GetResolverLocked(); 1451 NS_ENSURE_TRUE(resolver, NS_ERROR_NOT_INITIALIZED); 1452 resolver->FlushCache(aTrrToo, true); 1453 return NS_OK; 1454 } 1455 1456 // For testing purposes only 1457 NS_IMETHODIMP 1458 nsDNSService::ReloadParentalControlEnabled() { 1459 if (mTrrService) { 1460 mTrrService->mParentalControlEnabled = 1461 TRRService::ReloadParentalControlsEnabled(); 1462 } 1463 return NS_OK; 1464 } 1465 1466 NS_IMETHODIMP 1467 nsDNSService::SetDetectedTrrURI(const nsACString& aURI) { 1468 if (mTrrService) { 1469 mTrrService->SetDetectedTrrURI(aURI); 1470 } 1471 return NS_OK; 1472 } 1473 1474 NS_IMETHODIMP 1475 nsDNSService::SetHeuristicDetectionResult(nsITRRSkipReason::value aValue) { 1476 if (mTrrService) { 1477 mTrrService->SetHeuristicDetectionResult(aValue); 1478 } 1479 return NS_OK; 1480 } 1481 1482 NS_IMETHODIMP 1483 nsDNSService::GetHeuristicDetectionResult(nsITRRSkipReason::value* aValue) { 1484 if (!mTrrService) { 1485 return NS_ERROR_NOT_AVAILABLE; 1486 } 1487 1488 *aValue = mTrrService->GetHeuristicDetectionResult(); 1489 return NS_OK; 1490 } 1491 1492 NS_IMETHODIMP 1493 nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue, 1494 nsACString& aName) { 1495 return mozilla::net::GetTRRSkipReasonName(aValue, aName); 1496 } 1497 1498 NS_IMETHODIMP 1499 nsDNSService::GetCurrentTrrURI(nsACString& aURI) { 1500 if (mTrrService) { 1501 mTrrService->GetURI(aURI); 1502 } 1503 return NS_OK; 1504 } 1505 1506 NS_IMETHODIMP 1507 nsDNSService::GetCurrentTrrMode(nsIDNSService::ResolverMode* aMode) { 1508 *aMode = nsIDNSService::MODE_NATIVEONLY; // The default mode. 1509 if (mTrrService) { 1510 *aMode = mTrrService->Mode(); 1511 } 1512 return NS_OK; 1513 } 1514 1515 NS_IMETHODIMP 1516 nsDNSService::GetCurrentTrrConfirmationState(uint32_t* aConfirmationState) { 1517 *aConfirmationState = uint32_t(TRRService::CONFIRM_OFF); 1518 if (mTrrService) { 1519 *aConfirmationState = mTrrService->ConfirmationState(); 1520 } 1521 return NS_OK; 1522 } 1523 1524 NS_IMETHODIMP 1525 nsDNSService::GetTrrDomain(nsACString& aTRRDomain) { 1526 aTRRDomain.Truncate(); 1527 nsAutoCString url; 1528 if (mTrrService) { 1529 mTrrService->GetURI(url); 1530 } 1531 nsCOMPtr<nsIURI> uri; 1532 nsresult rv = NS_NewURI(getter_AddRefs(uri), url); 1533 if (NS_FAILED(rv)) { 1534 // An empty TRR domain in case of invalid URL. 1535 return NS_OK; 1536 } 1537 return uri->GetHost(aTRRDomain); 1538 } 1539 1540 nsresult nsDNSService::GetTRRDomainKey(nsACString& aTRRDomain) { 1541 aTRRDomain = TRRService::ProviderKey(); 1542 return NS_OK; 1543 } 1544 1545 size_t nsDNSService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { 1546 // Measurement of the following members may be added later if DMD finds it 1547 // is worthwhile: 1548 // - mIDN 1549 // - mLock 1550 1551 size_t n = mallocSizeOf(this); 1552 MutexAutoLock lock(mLock); 1553 n += mResolver ? mResolver->SizeOfIncludingThis(mallocSizeOf) : 0; 1554 n += mIPv4OnlyDomains.SizeOfExcludingThisIfUnshared(mallocSizeOf); 1555 n += mLocalDomains.SizeOfExcludingThis(mallocSizeOf); 1556 n += mFailedSVCDomainNames.ShallowSizeOfExcludingThis(mallocSizeOf); 1557 for (const auto& data : mFailedSVCDomainNames.Values()) { 1558 n += data->ShallowSizeOfExcludingThis(mallocSizeOf); 1559 for (const auto& name : *data) { 1560 n += name.SizeOfExcludingThisIfUnshared(mallocSizeOf); 1561 } 1562 } 1563 return n; 1564 } 1565 1566 MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf) 1567 1568 NS_IMETHODIMP 1569 nsDNSService::CollectReports(nsIHandleReportCallback* aHandleReport, 1570 nsISupports* aData, bool aAnonymize) { 1571 MOZ_COLLECT_REPORT("explicit/network/dns-service", KIND_HEAP, UNITS_BYTES, 1572 SizeOfIncludingThis(DNSServiceMallocSizeOf), 1573 "Memory used for the DNS service."); 1574 1575 return NS_OK; 1576 } 1577 1578 NS_IMETHODIMP 1579 nsDNSService::ReportFailedSVCDomainName(const nsACString& aOwnerName, 1580 const nsACString& aSVCDomainName) { 1581 MutexAutoLock lock(mLock); 1582 1583 mFailedSVCDomainNames.GetOrInsertNew(aOwnerName, 1) 1584 ->AppendElement(aSVCDomainName); 1585 return NS_OK; 1586 } 1587 1588 NS_IMETHODIMP 1589 nsDNSService::IsSVCDomainNameFailed(const nsACString& aOwnerName, 1590 const nsACString& aSVCDomainName, 1591 bool* aResult) { 1592 NS_ENSURE_ARG(aResult); 1593 1594 MutexAutoLock lock(mLock); 1595 *aResult = false; 1596 nsTArray<nsCString>* failedList = mFailedSVCDomainNames.Get(aOwnerName); 1597 if (!failedList) { 1598 return NS_OK; 1599 } 1600 1601 *aResult = failedList->Contains(aSVCDomainName); 1602 return NS_OK; 1603 } 1604 1605 NS_IMETHODIMP 1606 nsDNSService::ResetExcludedSVCDomainName(const nsACString& aOwnerName) { 1607 MutexAutoLock lock(mLock); 1608 mFailedSVCDomainNames.Remove(aOwnerName); 1609 return NS_OK; 1610 } 1611 1612 NS_IMETHODIMP 1613 nsDNSService::GetLastConfirmationStatus(nsresult* aConfirmationStatus) { 1614 if (!mTrrService) { 1615 return NS_ERROR_NOT_AVAILABLE; 1616 } 1617 *aConfirmationStatus = mTrrService->LastConfirmationStatus(); 1618 return NS_OK; 1619 } 1620 1621 NS_IMETHODIMP nsDNSService::GetLastConfirmationSkipReason( 1622 TRRSkippedReason* aSkipReason) { 1623 if (!mTrrService) { 1624 return NS_ERROR_NOT_AVAILABLE; 1625 } 1626 *aSkipReason = mTrrService->LastConfirmationSkipReason(); 1627 return NS_OK; 1628 } 1629 1630 namespace mozilla::net { 1631 nsresult GetTRRSkipReasonName(TRRSkippedReason aReason, nsACString& aName) { 1632 static_assert(TRRSkippedReason::TRR_UNSET == 0); 1633 static_assert(TRRSkippedReason::TRR_OK == 1); 1634 static_assert(TRRSkippedReason::TRR_NO_GSERVICE == 2); 1635 static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL == 3); 1636 static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT == 4); 1637 static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED == 5); 1638 static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED == 6); 1639 static_assert(TRRSkippedReason::TRR_FAILED == 7); 1640 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT == 8); 1641 static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED == 9); 1642 static_assert(TRRSkippedReason::TRR_DISABLED_FLAG == 10); 1643 static_assert(TRRSkippedReason::TRR_TIMEOUT == 11); 1644 static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL == 12); 1645 static_assert(TRRSkippedReason::TRR_BROWSER_IS_OFFLINE == 13); 1646 static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED == 14); 1647 static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY == 15); 1648 static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE == 16); 1649 static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY == 17); 1650 static_assert(TRRSkippedReason::TRR_SEND_FAILED == 18); 1651 static_assert(TRRSkippedReason::TRR_NET_RESET == 19); 1652 static_assert(TRRSkippedReason::TRR_NET_TIMEOUT == 20); 1653 static_assert(TRRSkippedReason::TRR_NET_REFUSED == 21); 1654 static_assert(TRRSkippedReason::TRR_NET_INTERRUPT == 22); 1655 static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY == 23); 1656 static_assert(TRRSkippedReason::TRR_NO_ANSWERS == 24); 1657 static_assert(TRRSkippedReason::TRR_DECODE_FAILED == 25); 1658 static_assert(TRRSkippedReason::TRR_EXCLUDED == 26); 1659 static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR == 27); 1660 static_assert(TRRSkippedReason::TRR_RCODE_FAIL == 28); 1661 static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY == 29); 1662 static_assert(TRRSkippedReason::TRR_NXDOMAIN == 30); 1663 static_assert(TRRSkippedReason::TRR_REQ_CANCELLED == 31); 1664 static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE == 32); 1665 static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED == 33); 1666 static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE == 34); 1667 static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED == 35); 1668 static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED == 36); 1669 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH == 1670 37); 1671 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH == 1672 38); 1673 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY == 39); 1674 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY == 40); 1675 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS == 41); 1676 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS == 1677 42); 1678 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS == 1679 43); 1680 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY == 1681 44); 1682 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN == 45); 1683 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY == 46); 1684 static_assert(TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT == 47); 1685 static_assert(TRRSkippedReason::TRR_BAD_URL == 48); 1686 static_assert(TRRSkippedReason::TRR_SYSTEM_SLEEP_MODE == 49); 1687 1688 switch (aReason) { 1689 case TRRSkippedReason::TRR_UNSET: 1690 aName = "TRR_UNSET"_ns; 1691 break; 1692 case TRRSkippedReason::TRR_OK: 1693 aName = "TRR_OK"_ns; 1694 break; 1695 case TRRSkippedReason::TRR_NO_GSERVICE: 1696 aName = "TRR_NO_GSERVICE"_ns; 1697 break; 1698 case TRRSkippedReason::TRR_PARENTAL_CONTROL: 1699 aName = "TRR_PARENTAL_CONTROL"_ns; 1700 break; 1701 case TRRSkippedReason::TRR_OFF_EXPLICIT: 1702 aName = "TRR_OFF_EXPLICIT"_ns; 1703 break; 1704 case TRRSkippedReason::TRR_REQ_MODE_DISABLED: 1705 aName = "TRR_REQ_MODE_DISABLED"_ns; 1706 break; 1707 case TRRSkippedReason::TRR_MODE_NOT_ENABLED: 1708 aName = "TRR_MODE_NOT_ENABLED"_ns; 1709 break; 1710 case TRRSkippedReason::TRR_FAILED: 1711 aName = "TRR_FAILED"_ns; 1712 break; 1713 case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT: 1714 aName = "TRR_MODE_UNHANDLED_DEFAULT"_ns; 1715 break; 1716 case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED: 1717 aName = "TRR_MODE_UNHANDLED_DISABLED"_ns; 1718 break; 1719 case TRRSkippedReason::TRR_DISABLED_FLAG: 1720 aName = "TRR_DISABLED_FLAG"_ns; 1721 break; 1722 case TRRSkippedReason::TRR_TIMEOUT: 1723 aName = "TRR_TIMEOUT"_ns; 1724 break; 1725 case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL: 1726 aName = "TRR_CHANNEL_DNS_FAIL"_ns; 1727 break; 1728 case TRRSkippedReason::TRR_BROWSER_IS_OFFLINE: 1729 aName = "TRR_BROWSER_IS_OFFLINE"_ns; 1730 break; 1731 case TRRSkippedReason::TRR_NOT_CONFIRMED: 1732 aName = "TRR_NOT_CONFIRMED"_ns; 1733 break; 1734 case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY: 1735 aName = "TRR_DID_NOT_MAKE_QUERY"_ns; 1736 break; 1737 case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE: 1738 aName = "TRR_UNKNOWN_CHANNEL_FAILURE"_ns; 1739 break; 1740 case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY: 1741 aName = "TRR_HOST_BLOCKED_TEMPORARY"_ns; 1742 break; 1743 case TRRSkippedReason::TRR_SEND_FAILED: 1744 aName = "TRR_SEND_FAILED"_ns; 1745 break; 1746 case TRRSkippedReason::TRR_NET_RESET: 1747 aName = "TRR_NET_RESET"_ns; 1748 break; 1749 case TRRSkippedReason::TRR_NET_TIMEOUT: 1750 aName = "TRR_NET_TIMEOUT"_ns; 1751 break; 1752 case TRRSkippedReason::TRR_NET_REFUSED: 1753 aName = "TRR_NET_REFUSED"_ns; 1754 break; 1755 case TRRSkippedReason::TRR_NET_INTERRUPT: 1756 aName = "TRR_NET_INTERRUPT"_ns; 1757 break; 1758 case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY: 1759 aName = "TRR_NET_INADEQ_SEQURITY"_ns; 1760 break; 1761 case TRRSkippedReason::TRR_NO_ANSWERS: 1762 aName = "TRR_NO_ANSWERS"_ns; 1763 break; 1764 case TRRSkippedReason::TRR_DECODE_FAILED: 1765 aName = "TRR_DECODE_FAILED"_ns; 1766 break; 1767 case TRRSkippedReason::TRR_EXCLUDED: 1768 aName = "TRR_EXCLUDED"_ns; 1769 break; 1770 case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR: 1771 aName = "TRR_SERVER_RESPONSE_ERR"_ns; 1772 break; 1773 case TRRSkippedReason::TRR_RCODE_FAIL: 1774 aName = "TRR_RCODE_FAIL"_ns; 1775 break; 1776 case TRRSkippedReason::TRR_NO_CONNECTIVITY: 1777 aName = "TRR_NO_CONNECTIVITY"_ns; 1778 break; 1779 case TRRSkippedReason::TRR_NXDOMAIN: 1780 aName = "TRR_NXDOMAIN"_ns; 1781 break; 1782 case TRRSkippedReason::TRR_REQ_CANCELLED: 1783 aName = "TRR_REQ_CANCELLED"_ns; 1784 break; 1785 case TRRSkippedReason::ODOH_KEY_NOT_USABLE: 1786 aName = "ODOH_KEY_NOT_USABLE"_ns; 1787 break; 1788 case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED: 1789 aName = "ODOH_UPDATE_KEY_FAILED"_ns; 1790 break; 1791 case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE: 1792 aName = "ODOH_KEY_NOT_AVAILABLE"_ns; 1793 break; 1794 case TRRSkippedReason::ODOH_ENCRYPTION_FAILED: 1795 aName = "ODOH_ENCRYPTION_FAILED"_ns; 1796 break; 1797 case TRRSkippedReason::ODOH_DECRYPTION_FAILED: 1798 aName = "ODOH_DECRYPTION_FAILED"_ns; 1799 break; 1800 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH: 1801 aName = "TRR_HEURISTIC_TRIPPED_GOOGLE_SAFESEARCH"_ns; 1802 break; 1803 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH: 1804 aName = "TRR_HEURISTIC_TRIPPED_YOUTUBE_SAFESEARCH"_ns; 1805 break; 1806 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY: 1807 aName = "TRR_HEURISTIC_TRIPPED_ZSCALER_CANARY"_ns; 1808 break; 1809 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_CANARY: 1810 aName = "TRR_HEURISTIC_TRIPPED_CANARY"_ns; 1811 break; 1812 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS: 1813 aName = "TRR_HEURISTIC_TRIPPED_MODIFIED_ROOTS"_ns; 1814 break; 1815 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS: 1816 aName = "TRR_HEURISTIC_TRIPPED_PARENTAL_CONTROLS"_ns; 1817 break; 1818 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS: 1819 aName = "TRR_HEURISTIC_TRIPPED_THIRD_PARTY_ROOTS"_ns; 1820 break; 1821 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY: 1822 aName = "TRR_HEURISTIC_TRIPPED_ENTERPRISE_POLICY"_ns; 1823 break; 1824 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_VPN: 1825 aName = "TRR_HEURISTIC_TRIPPED_VPN"_ns; 1826 break; 1827 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_PROXY: 1828 aName = "TRR_HEURISTIC_TRIPPED_PROXY"_ns; 1829 break; 1830 case TRRSkippedReason::TRR_HEURISTIC_TRIPPED_NRPT: 1831 aName = "TRR_HEURISTIC_TRIPPED_NRPT"_ns; 1832 break; 1833 case TRRSkippedReason::TRR_BAD_URL: 1834 aName = "TRR_BAD_URL"_ns; 1835 break; 1836 case TRRSkippedReason::TRR_SYSTEM_SLEEP_MODE: 1837 aName = "TRR_SYSTEM_SLEEP_MODE"_ns; 1838 break; 1839 default: 1840 MOZ_ASSERT(false, "Unknown value"); 1841 } 1842 1843 return NS_OK; 1844 } 1845 } // namespace mozilla::net