From c56863a35767b3dcf119af67341ed6c331b28aba Mon Sep 17 00:00:00 2001 From: Valentin Gosu Date: Fri, 23 Dec 2022 09:26:15 +0000 Subject: [PATCH] Bug 1596845 - Pass TRR skip reason to child channel r=necko-reviewers,kershaw Moves the TRRSkipReasons to nsITRRSkipReason.idl so they are available to JS. Depends on D164345 Differential Revision: https://phabricator.services.mozilla.com/D164348 --- netwerk/dns/ChildDNSService.cpp | 6 + netwerk/dns/DNSRequestChild.cpp | 7 + netwerk/dns/TRR.h | 2 +- netwerk/dns/TRRSkippedReason.h | 103 ----------- netwerk/dns/moz.build | 1 + netwerk/dns/nsDNSService2.cpp | 172 ++++++++++++++++++ netwerk/dns/nsHostRecord.cpp | 1 - netwerk/dns/nsHostRecord.h | 3 +- netwerk/dns/nsIDNSRecord.idl | 7 + netwerk/dns/nsIDNSService.idl | 3 + netwerk/dns/nsITRRSkipReason.idl | 109 +++++++++++ netwerk/docs/dns/trr-skip-reasons.md | 2 +- netwerk/ipc/NeckoMessageUtils.h | 18 ++ netwerk/protocol/http/HttpBaseChannel.cpp | 6 + netwerk/protocol/http/HttpBaseChannel.h | 2 + netwerk/protocol/http/HttpChannelChild.cpp | 1 + netwerk/protocol/http/HttpChannelParams.ipdlh | 2 + netwerk/protocol/http/HttpChannelParent.cpp | 4 + netwerk/protocol/http/nsHttpChannel.cpp | 1 + .../protocol/http/nsIHttpChannelInternal.idl | 7 + 20 files changed, 350 insertions(+), 107 deletions(-) delete mode 100644 netwerk/dns/TRRSkippedReason.h create mode 100644 netwerk/dns/nsITRRSkipReason.idl diff --git a/netwerk/dns/ChildDNSService.cpp b/netwerk/dns/ChildDNSService.cpp index af2988a0200d..7f715e8ccaef 100644 --- a/netwerk/dns/ChildDNSService.cpp +++ b/netwerk/dns/ChildDNSService.cpp @@ -306,6 +306,12 @@ ChildDNSService::SetDetectedTrrURI(const nsACString& aURI) { return NS_OK; } +NS_IMETHODIMP +ChildDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue, + nsACString& aName) { + return mozilla::net::GetTRRSkipReasonName(aValue, aName); +} + NS_IMETHODIMP ChildDNSService::GetCurrentTrrURI(nsACString& aURI) { if (!mTRRServiceParent) { diff --git a/netwerk/dns/DNSRequestChild.cpp b/netwerk/dns/DNSRequestChild.cpp index 8f6ef1a34b52..2d8056d0a23a 100644 --- a/netwerk/dns/DNSRequestChild.cpp +++ b/netwerk/dns/DNSRequestChild.cpp @@ -56,6 +56,7 @@ class ChildDNSRecord : public nsIDNSAddrRecord { bool mIsTRR = false; bool mResolvedInSocketProcess = false; nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE; + nsITRRSkipReason::value mTRRSkipReason = nsITRRSkipReason::TRR_UNSET; uint32_t mTTL = 0; }; @@ -194,6 +195,12 @@ ChildDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode* aMode) { return NS_OK; } +NS_IMETHODIMP ChildDNSRecord::GetTrrSkipReason( + nsITRRSkipReason::value* aTrrSkipReason) { + *aTrrSkipReason = mTRRSkipReason; + return NS_OK; +} + NS_IMETHODIMP ChildDNSRecord::GetTtl(uint32_t* aTtl) { *aTtl = mTTL; diff --git a/netwerk/dns/TRR.h b/netwerk/dns/TRR.h index ede41f7f8ff4..f5a7a6d0af3d 100644 --- a/netwerk/dns/TRR.h +++ b/netwerk/dns/TRR.h @@ -17,7 +17,7 @@ #include "nsThreadUtils.h" #include "nsXULAppAPI.h" #include "DNSPacket.h" -#include "TRRSkippedReason.h" +#include "nsITRRSkipReason.h" class AHostResolver; class nsHostRecord; diff --git a/netwerk/dns/TRRSkippedReason.h b/netwerk/dns/TRRSkippedReason.h deleted file mode 100644 index 89cd4744d5dc..000000000000 --- a/netwerk/dns/TRRSkippedReason.h +++ /dev/null @@ -1,103 +0,0 @@ -/* vim:set ts=4 sw=2 sts=2 et cin: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_net_TRRSkippedReason_h__ -#define mozilla_net_TRRSkippedReason_h__ - -namespace mozilla { -namespace net { - -// IMPORTANT: when adding new values, always add them to the end, otherwise -// it will mess up telemetry. -// When adding a reason here, make sure it is documented in -// netwerk/docs/dns/trr-skip-reasons.md -enum class TRRSkippedReason : uint32_t { - TRR_UNSET = 0, - TRR_OK = 1, // Only set when we actually got a positive TRR result - TRR_NO_GSERVICE = 2, // no gService - TRR_PARENTAL_CONTROL = 3, // parental control is on - TRR_OFF_EXPLICIT = 4, // user has set mode5 - TRR_REQ_MODE_DISABLED = 5, // request has disabled flags set - TRR_MODE_NOT_ENABLED = 6, // mode0 - TRR_FAILED = 7, // unknown failure - TRR_MODE_UNHANDLED_DEFAULT = 8, // Unhandled case in ComputeEffectiveMode - TRR_MODE_UNHANDLED_DISABLED = 9, // Unhandled case in ComputeEffectiveMode - TRR_DISABLED_FLAG = 10, // the DISABLE_TRR flag was set - TRR_TIMEOUT = 11, // the TRR channel timed out - TRR_CHANNEL_DNS_FAIL = 12, // DoH server name failed to resolve - TRR_IS_OFFLINE = 13, // The browser is offline/no interfaces up - TRR_NOT_CONFIRMED = 14, // TRR confirmation is not done yet - TRR_DID_NOT_MAKE_QUERY = 15, // TrrLookup exited without doing a TRR query - TRR_UNKNOWN_CHANNEL_FAILURE = 16, // unknown channel failure reason - TRR_HOST_BLOCKED_TEMPORARY = 17, // host blocklisted - TRR_SEND_FAILED = 18, // The call to TRR::SendHTTPRequest failed - TRR_NET_RESET = 19, // NS_ERROR_NET_RESET - TRR_NET_TIMEOUT = 20, // NS_ERROR_NET_TIMEOUT - TRR_NET_REFUSED = 21, // NS_ERROR_CONNECTION_REFUSED - TRR_NET_INTERRUPT = 22, // NS_ERROR_NET_INTERRUPT - TRR_NET_INADEQ_SEQURITY = 23, // NS_ERROR_NET_INADEQUATE_SECURITY - TRR_NO_ANSWERS = 24, // TRR returned no answers - TRR_DECODE_FAILED = 25, // DohDecode failed - TRR_EXCLUDED = 26, // ExcludedFromTRR - TRR_SERVER_RESPONSE_ERR = 27, // Server responded with non-200 code - TRR_RCODE_FAIL = 28, // DNS response contains a non-NOERROR rcode - TRR_NO_CONNECTIVITY = 29, // Not confirmed because of no connectivity - TRR_NXDOMAIN = 30, // DNS response contains NXDOMAIN rcode (0x03) - TRR_REQ_CANCELLED = 31, // The request has been cancelled - ODOH_KEY_NOT_USABLE = 32, // We don't have a valid ODoHConfig to use. - ODOH_UPDATE_KEY_FAILED = 33, // Failed to update the ODoHConfigs. - ODOH_KEY_NOT_AVAILABLE = 34, // ODoH requests timeout because of no key. - ODOH_ENCRYPTION_FAILED = 35, // Failed to encrypt DNS packets. - ODOH_DECRYPTION_FAILED = 36, // Failed to decrypt DNS packets. -}; - -inline bool IsRelevantTRRSkipReason(TRRSkippedReason aReason) { - // - TRR_REQ_MODE_DISABLED - these requests are intentionally skipping TRR. - // These include DNS queries used to bootstrap the TRR connection, - // captive portal checks, connectivity checks, etc. - // Since we don't want to use TRR for these connections, we don't need - // to include them with other relevant skip reasons. - // - TRR_DISABLED_FLAG - This reason is used when retrying failed connections, - // sync DNS resolves on the main thread, or requests coming from - // webextensions that choose to skip TRR - // - TRR_EXCLUDED - This reason is used when a certain domain is excluded - // from TRR because it is explicitly set by the user, or because it - // is part of the user's DNS suffix list, indicating a host that is likely - // to be on the local network. - if (aReason == TRRSkippedReason::TRR_REQ_MODE_DISABLED || - aReason == TRRSkippedReason::TRR_DISABLED_FLAG || - aReason == TRRSkippedReason::TRR_EXCLUDED) { - return false; - } - return true; -} - -inline bool IsBlockedTRRRequest(TRRSkippedReason aReason) { - // See TRR::MaybeBlockRequest. These are the reasons that could block sending - // TRR requests. - return (aReason == TRRSkippedReason::TRR_EXCLUDED || - aReason == TRRSkippedReason::TRR_MODE_NOT_ENABLED || - aReason == TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY); -} - -inline bool IsNonRecoverableTRRSkipReason(TRRSkippedReason aReason) { - // These are non-recoverable reasons and we'll fallback to native without - // retrying. - return (aReason == TRRSkippedReason::TRR_NXDOMAIN || - aReason == TRRSkippedReason::TRR_NO_ANSWERS || - aReason == TRRSkippedReason::TRR_DISABLED_FLAG || - aReason == TRRSkippedReason::TRR_RCODE_FAIL); -} - -inline bool IsFailedConfirmationOrNoConnectivity(TRRSkippedReason aReason) { - // TRR is in non-confirmed state now, so we don't try to use TRR at all. - return (aReason == TRRSkippedReason::TRR_NOT_CONFIRMED || - aReason == TRRSkippedReason::TRR_NO_CONNECTIVITY); -} - -} // namespace net -} // namespace mozilla - -#endif // mozilla_net_TRRSkippedReason_h__ diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build index 3538707f7e57..66b12fce4475 100644 --- a/netwerk/dns/moz.build +++ b/netwerk/dns/moz.build @@ -18,6 +18,7 @@ XPIDL_SOURCES += [ "nsIEffectiveTLDService.idl", "nsIIDNService.idl", "nsINativeDNSResolverOverride.idl", + "nsITRRSkipReason.idl", "nsPIDNSService.idl", ] diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index b438d92cdff7..de33fbfc65b0 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -357,6 +357,12 @@ nsDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode* aMode) { return NS_OK; } +NS_IMETHODIMP nsDNSRecord::GetTrrSkipReason( + nsITRRSkipReason::value* aTrrSkipReason) { + *aTrrSkipReason = mHostRecord->TrrSkipReason(); + return NS_OK; +} + NS_IMETHODIMP nsDNSRecord::GetTtl(uint32_t* aTtl) { return mHostRecord->GetTtl(aTtl); } @@ -1426,6 +1432,12 @@ nsDNSService::SetDetectedTrrURI(const nsACString& aURI) { return NS_OK; } +NS_IMETHODIMP +nsDNSService::GetTRRSkipReasonName(nsITRRSkipReason::value aValue, + nsACString& aName) { + return mozilla::net::GetTRRSkipReasonName(aValue, aName); +} + NS_IMETHODIMP nsDNSService::GetCurrentTrrURI(nsACString& aURI) { if (mTrrService) { @@ -1518,3 +1530,163 @@ nsDNSService::ResetExcludedSVCDomainName(const nsACString& aOwnerName) { mFailedSVCDomainNames.Remove(aOwnerName); return NS_OK; } + +namespace mozilla::net { +nsresult GetTRRSkipReasonName(TRRSkippedReason aReason, nsACString& aName) { + static_assert(TRRSkippedReason::TRR_UNSET == 0); + static_assert(TRRSkippedReason::TRR_OK == 1); + static_assert(TRRSkippedReason::TRR_NO_GSERVICE == 2); + static_assert(TRRSkippedReason::TRR_PARENTAL_CONTROL == 3); + static_assert(TRRSkippedReason::TRR_OFF_EXPLICIT == 4); + static_assert(TRRSkippedReason::TRR_REQ_MODE_DISABLED == 5); + static_assert(TRRSkippedReason::TRR_MODE_NOT_ENABLED == 6); + static_assert(TRRSkippedReason::TRR_FAILED == 7); + static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT == 8); + static_assert(TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED == 9); + static_assert(TRRSkippedReason::TRR_DISABLED_FLAG == 10); + static_assert(TRRSkippedReason::TRR_TIMEOUT == 11); + static_assert(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL == 12); + static_assert(TRRSkippedReason::TRR_IS_OFFLINE == 13); + static_assert(TRRSkippedReason::TRR_NOT_CONFIRMED == 14); + static_assert(TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY == 15); + static_assert(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE == 16); + static_assert(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY == 17); + static_assert(TRRSkippedReason::TRR_SEND_FAILED == 18); + static_assert(TRRSkippedReason::TRR_NET_RESET == 19); + static_assert(TRRSkippedReason::TRR_NET_TIMEOUT == 20); + static_assert(TRRSkippedReason::TRR_NET_REFUSED == 21); + static_assert(TRRSkippedReason::TRR_NET_INTERRUPT == 22); + static_assert(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY == 23); + static_assert(TRRSkippedReason::TRR_NO_ANSWERS == 24); + static_assert(TRRSkippedReason::TRR_DECODE_FAILED == 25); + static_assert(TRRSkippedReason::TRR_EXCLUDED == 26); + static_assert(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR == 27); + static_assert(TRRSkippedReason::TRR_RCODE_FAIL == 28); + static_assert(TRRSkippedReason::TRR_NO_CONNECTIVITY == 29); + static_assert(TRRSkippedReason::TRR_NXDOMAIN == 30); + static_assert(TRRSkippedReason::TRR_REQ_CANCELLED == 31); + static_assert(TRRSkippedReason::ODOH_KEY_NOT_USABLE == 32); + static_assert(TRRSkippedReason::ODOH_UPDATE_KEY_FAILED == 33); + static_assert(TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE == 34); + static_assert(TRRSkippedReason::ODOH_ENCRYPTION_FAILED == 35); + static_assert(TRRSkippedReason::ODOH_DECRYPTION_FAILED == 36); + + switch (aReason) { + case TRRSkippedReason::TRR_UNSET: + aName = "TRR_UNSET"_ns; + break; + case TRRSkippedReason::TRR_OK: + aName = "TRR_OK"_ns; + break; + case TRRSkippedReason::TRR_NO_GSERVICE: + aName = "TRR_NO_GSERVICE"_ns; + break; + case TRRSkippedReason::TRR_PARENTAL_CONTROL: + aName = "TRR_PARENTAL_CONTROL"_ns; + break; + case TRRSkippedReason::TRR_OFF_EXPLICIT: + aName = "TRR_OFF_EXPLICIT"_ns; + break; + case TRRSkippedReason::TRR_REQ_MODE_DISABLED: + aName = "TRR_REQ_MODE_DISABLED"_ns; + break; + case TRRSkippedReason::TRR_MODE_NOT_ENABLED: + aName = "TRR_MODE_NOT_ENABLED"_ns; + break; + case TRRSkippedReason::TRR_FAILED: + aName = "TRR_FAILED"_ns; + break; + case TRRSkippedReason::TRR_MODE_UNHANDLED_DEFAULT: + aName = "TRR_MODE_UNHANDLED_DEFAULT"_ns; + break; + case TRRSkippedReason::TRR_MODE_UNHANDLED_DISABLED: + aName = "TRR_MODE_UNHANDLED_DISABLED"_ns; + break; + case TRRSkippedReason::TRR_DISABLED_FLAG: + aName = "TRR_DISABLED_FLAG"_ns; + break; + case TRRSkippedReason::TRR_TIMEOUT: + aName = "TRR_TIMEOUT"_ns; + break; + case TRRSkippedReason::TRR_CHANNEL_DNS_FAIL: + aName = "TRR_CHANNEL_DNS_FAIL"_ns; + break; + case TRRSkippedReason::TRR_IS_OFFLINE: + aName = "TRR_IS_OFFLINE"_ns; + break; + case TRRSkippedReason::TRR_NOT_CONFIRMED: + aName = "TRR_NOT_CONFIRMED"_ns; + break; + case TRRSkippedReason::TRR_DID_NOT_MAKE_QUERY: + aName = "TRR_DID_NOT_MAKE_QUERY"_ns; + break; + case TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE: + aName = "TRR_UNKNOWN_CHANNEL_FAILURE"_ns; + break; + case TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY: + aName = "TRR_HOST_BLOCKED_TEMPORARY"_ns; + break; + case TRRSkippedReason::TRR_SEND_FAILED: + aName = "TRR_SEND_FAILED"_ns; + break; + case TRRSkippedReason::TRR_NET_RESET: + aName = "TRR_NET_RESET"_ns; + break; + case TRRSkippedReason::TRR_NET_TIMEOUT: + aName = "TRR_NET_TIMEOUT"_ns; + break; + case TRRSkippedReason::TRR_NET_REFUSED: + aName = "TRR_NET_REFUSED"_ns; + break; + case TRRSkippedReason::TRR_NET_INTERRUPT: + aName = "TRR_NET_INTERRUPT"_ns; + break; + case TRRSkippedReason::TRR_NET_INADEQ_SEQURITY: + aName = "TRR_NET_INADEQ_SEQURITY"_ns; + break; + case TRRSkippedReason::TRR_NO_ANSWERS: + aName = "TRR_NO_ANSWERS"_ns; + break; + case TRRSkippedReason::TRR_DECODE_FAILED: + aName = "TRR_DECODE_FAILED"_ns; + break; + case TRRSkippedReason::TRR_EXCLUDED: + aName = "TRR_EXCLUDED"_ns; + break; + case TRRSkippedReason::TRR_SERVER_RESPONSE_ERR: + aName = "TRR_SERVER_RESPONSE_ERR"_ns; + break; + case TRRSkippedReason::TRR_RCODE_FAIL: + aName = "TRR_RCODE_FAIL"_ns; + break; + case TRRSkippedReason::TRR_NO_CONNECTIVITY: + aName = "TRR_NO_CONNECTIVITY"_ns; + break; + case TRRSkippedReason::TRR_NXDOMAIN: + aName = "TRR_NXDOMAIN"_ns; + break; + case TRRSkippedReason::TRR_REQ_CANCELLED: + aName = "TRR_REQ_CANCELLED"_ns; + break; + case TRRSkippedReason::ODOH_KEY_NOT_USABLE: + aName = "ODOH_KEY_NOT_USABLE"_ns; + break; + case TRRSkippedReason::ODOH_UPDATE_KEY_FAILED: + aName = "ODOH_UPDATE_KEY_FAILED"_ns; + break; + case TRRSkippedReason::ODOH_KEY_NOT_AVAILABLE: + aName = "ODOH_KEY_NOT_AVAILABLE"_ns; + break; + case TRRSkippedReason::ODOH_ENCRYPTION_FAILED: + aName = "ODOH_ENCRYPTION_FAILED"_ns; + break; + case TRRSkippedReason::ODOH_DECRYPTION_FAILED: + aName = "ODOH_DECRYPTION_FAILED"_ns; + break; + default: + MOZ_ASSERT(false, "Unknown value"); + } + + return NS_OK; +} +} // namespace mozilla::net diff --git a/netwerk/dns/nsHostRecord.cpp b/netwerk/dns/nsHostRecord.cpp index edcc92e0da88..cf10c50f363b 100644 --- a/netwerk/dns/nsHostRecord.cpp +++ b/netwerk/dns/nsHostRecord.cpp @@ -7,7 +7,6 @@ #include "TRRQuery.h" // Put DNSLogging.h at the end to avoid LOG being overwritten by other headers. #include "DNSLogging.h" -#include "TRRSkippedReason.h" #include "mozilla/StaticPrefs_network.h" #include "mozilla/Telemetry.h" #include "TRRService.h" diff --git a/netwerk/dns/nsHostRecord.h b/netwerk/dns/nsHostRecord.h index 8be9b23b35ff..95a2108903c2 100644 --- a/netwerk/dns/nsHostRecord.h +++ b/netwerk/dns/nsHostRecord.h @@ -13,7 +13,7 @@ #include "nsIDNSService.h" #include "nsIDNSByTypeRecord.h" #include "PLDHashTable.h" -#include "TRRSkippedReason.h" +#include "nsITRRSkipReason.h" class nsHostRecord; class nsHostResolver; @@ -269,6 +269,7 @@ class AddrHostRecord final : public nsHostRecord { size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override; nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; } + nsITRRSkipReason::value TrrSkipReason() const { return mTRRSkippedReason; } nsresult GetTtl(uint32_t* aResult); diff --git a/netwerk/dns/nsIDNSRecord.idl b/netwerk/dns/nsIDNSRecord.idl index 886006b2ef72..82682bd9007e 100644 --- a/netwerk/dns/nsIDNSRecord.idl +++ b/netwerk/dns/nsIDNSRecord.idl @@ -4,6 +4,7 @@ #include "nsISupports.idl" #include "nsIRequest.idl" +#include "nsITRRSkipReason.idl" %{ C++ namespace mozilla { @@ -140,6 +141,12 @@ interface nsIDNSAddrRecord : nsIDNSRecord */ readonly attribute nsIRequest_TRRMode effectiveTRRMode; + /** + * If the DNS request didn't use TRR, this value + * contains the reason why that was skipped. + */ + readonly attribute nsITRRSkipReason_value trrSkipReason; + /** * Returns the ttl of this record. */ diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 35ed5523b9cf..6d3f7519ebd7 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -4,6 +4,7 @@ #include "nsISupports.idl" #include "nsIRequest.idl" +#include "nsITRRSkipReason.idl" %{ C++ #include "mozilla/BasePrincipal.h" @@ -207,6 +208,8 @@ interface nsIDNSService : nsISupports */ void setDetectedTrrURI(in AUTF8String aURI); + ACString getTRRSkipReasonName(in nsITRRSkipReason_value value); + /** * Notifies the DNS service that we failed to connect to this alternative * endpoint. diff --git a/netwerk/dns/nsITRRSkipReason.idl b/netwerk/dns/nsITRRSkipReason.idl new file mode 100644 index 000000000000..567ce9e411b6 --- /dev/null +++ b/netwerk/dns/nsITRRSkipReason.idl @@ -0,0 +1,109 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +[scriptable, uuid(e61b5d39-f6d6-4ed3-aead-1213b24c6f27)] +interface nsITRRSkipReason: nsISupports +{ + // IMPORTANT: when adding new values, always add them to the end, otherwise + // it will mess up telemetry. + // When adding a reason here, make sure it is documented in + // netwerk/docs/dns/trr-skip-reasons.md + cenum value: 8 { + TRR_UNSET = 0, + TRR_OK = 1, // Only set when we actually got a positive TRR result + TRR_NO_GSERVICE = 2, // no gService + TRR_PARENTAL_CONTROL = 3, // parental control is on + TRR_OFF_EXPLICIT = 4, // user has set mode5 + TRR_REQ_MODE_DISABLED = 5, // request has disabled flags set + TRR_MODE_NOT_ENABLED = 6, // mode0 + TRR_FAILED = 7, // unknown failure + TRR_MODE_UNHANDLED_DEFAULT = 8, // Unhandled case in ComputeEffectiveMode + TRR_MODE_UNHANDLED_DISABLED = 9, // Unhandled case in ComputeEffectiveMode + TRR_DISABLED_FLAG = 10, // the DISABLE_TRR flag was set + TRR_TIMEOUT = 11, // the TRR channel timed out + TRR_CHANNEL_DNS_FAIL = 12, // DoH server name failed to resolve + TRR_IS_OFFLINE = 13, // The browser is offline/no interfaces up + TRR_NOT_CONFIRMED = 14, // TRR confirmation is not done yet + TRR_DID_NOT_MAKE_QUERY = 15, // TrrLookup exited without doing a TRR query + TRR_UNKNOWN_CHANNEL_FAILURE = 16, // unknown channel failure reason + TRR_HOST_BLOCKED_TEMPORARY = 17, // host blocklisted + TRR_SEND_FAILED = 18, // The call to TRR::SendHTTPRequest failed + TRR_NET_RESET = 19, // NS_ERROR_NET_RESET + TRR_NET_TIMEOUT = 20, // NS_ERROR_NET_TIMEOUT + TRR_NET_REFUSED = 21, // NS_ERROR_CONNECTION_REFUSED + TRR_NET_INTERRUPT = 22, // NS_ERROR_NET_INTERRUPT + TRR_NET_INADEQ_SEQURITY = 23, // NS_ERROR_NET_INADEQUATE_SECURITY + TRR_NO_ANSWERS = 24, // TRR returned no answers + TRR_DECODE_FAILED = 25, // DohDecode failed + TRR_EXCLUDED = 26, // ExcludedFromTRR + TRR_SERVER_RESPONSE_ERR = 27, // Server responded with non-200 code + TRR_RCODE_FAIL = 28, // DNS response contains a non-NOERROR rcode + TRR_NO_CONNECTIVITY = 29, // Not confirmed because of no connectivity + TRR_NXDOMAIN = 30, // DNS response contains NXDOMAIN rcode (0x03) + TRR_REQ_CANCELLED = 31, // The request has been cancelled + ODOH_KEY_NOT_USABLE = 32, // We don't have a valid ODoHConfig to use. + ODOH_UPDATE_KEY_FAILED = 33, // Failed to update the ODoHConfigs. + ODOH_KEY_NOT_AVAILABLE = 34, // ODoH requests timeout because of no key. + ODOH_ENCRYPTION_FAILED = 35, // Failed to encrypt DNS packets. + ODOH_DECRYPTION_FAILED = 36, // Failed to decrypt DNS packets. + }; +}; + +%{ C++ +namespace mozilla { +namespace net { + +using TRRSkippedReason = nsITRRSkipReason::value; + +inline bool IsRelevantTRRSkipReason(TRRSkippedReason aReason) { + // - TRR_REQ_MODE_DISABLED - these requests are intentionally skipping TRR. + // These include DNS queries used to bootstrap the TRR connection, + // captive portal checks, connectivity checks, etc. + // Since we don't want to use TRR for these connections, we don't need + // to include them with other relevant skip reasons. + // - TRR_DISABLED_FLAG - This reason is used when retrying failed connections, + // sync DNS resolves on the main thread, or requests coming from + // webextensions that choose to skip TRR + // - TRR_EXCLUDED - This reason is used when a certain domain is excluded + // from TRR because it is explicitly set by the user, or because it + // is part of the user's DNS suffix list, indicating a host that is likely + // to be on the local network. + if (aReason == TRRSkippedReason::TRR_REQ_MODE_DISABLED || + aReason == TRRSkippedReason::TRR_DISABLED_FLAG || + aReason == TRRSkippedReason::TRR_EXCLUDED) { + return false; + } + return true; +} + +inline bool IsBlockedTRRRequest(TRRSkippedReason aReason) { + // See TRR::MaybeBlockRequest. These are the reasons that could block sending + // TRR requests. + return (aReason == TRRSkippedReason::TRR_EXCLUDED || + aReason == TRRSkippedReason::TRR_MODE_NOT_ENABLED || + aReason == TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY); +} + +inline bool IsNonRecoverableTRRSkipReason(TRRSkippedReason aReason) { + // These are non-recoverable reasons and we'll fallback to native without + // retrying. + return (aReason == TRRSkippedReason::TRR_NXDOMAIN || + aReason == TRRSkippedReason::TRR_NO_ANSWERS || + aReason == TRRSkippedReason::TRR_DISABLED_FLAG || + aReason == TRRSkippedReason::TRR_RCODE_FAIL); +} + +inline bool IsFailedConfirmationOrNoConnectivity(TRRSkippedReason aReason) { + // TRR is in non-confirmed state now, so we don't try to use TRR at all. + return (aReason == TRRSkippedReason::TRR_NOT_CONFIRMED || + aReason == TRRSkippedReason::TRR_NO_CONNECTIVITY); +} + +extern nsresult GetTRRSkipReasonName(TRRSkippedReason aReason, nsACString& aName); + +} // net +} // mozilla +%} diff --git a/netwerk/docs/dns/trr-skip-reasons.md b/netwerk/docs/dns/trr-skip-reasons.md index 1125344a65a1..5f7defd998be 100644 --- a/netwerk/docs/dns/trr-skip-reasons.md +++ b/netwerk/docs/dns/trr-skip-reasons.md @@ -1,6 +1,6 @@ # TRRSkippedReasons -These values are defined in [TRRSkippedReason.h](https://searchfox.org/mozilla-central/source/netwerk/dns/TRRSkippedReason.h) and are recorded on _nsHostRecord_ for each resolution. +These values are defined in [TRRSkippedReason.h](https://searchfox.org/mozilla-central/source/netwerk/dns/nsITRRSkipReason.idl) and are recorded on _nsHostRecord_ for each resolution. We normally use them for telemetry or to determine the cause of a TRR failure. diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index e05838a443da..712f9737d94c 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -17,6 +17,7 @@ #include "prio.h" #include "mozilla/net/DNS.h" #include "ipc/IPCMessageUtilsSpecializations.h" +#include "nsITRRSkipReason.h" namespace IPC { @@ -142,6 +143,23 @@ struct ParamTraits { } }; +template <> +struct ParamTraits { + static void Write(MessageWriter* aWriter, + const nsITRRSkipReason::value& aParam) { + WriteParam(aWriter, (uint8_t)aParam); + } + static bool Read(MessageReader* aReader, nsITRRSkipReason::value* aResult) { + uint8_t reason; + if (!ReadParam(aReader, &reason)) { + return false; + } + // TODO: sanity check + *aResult = static_cast(reason); + return true; + } +}; + } // namespace IPC #endif // mozilla_net_NeckoMessageUtils_h diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index b10ea7e30de0..3fb60a1764b4 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -3606,6 +3606,12 @@ HttpBaseChannel::GetEffectiveTRRMode(nsIRequest::TRRMode* aEffectiveTRRMode) { return NS_OK; } +NS_IMETHODIMP +HttpBaseChannel::GetTrrSkipReason(nsITRRSkipReason::value* aTrrSkipReason) { + *aTrrSkipReason = mTRRSkipReason; + return NS_OK; +} + NS_IMETHODIMP HttpBaseChannel::GetIsLoadedBySocketProcess(bool* aResult) { NS_ENSURE_ARG_POINTER(aResult); diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index d2f4e4ed074a..f902f7ca9bc1 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -283,6 +283,7 @@ class HttpBaseChannel : public nsHashPropertyBag, NS_IMETHOD GetIsResolvedByTRR(bool* aResolvedByTRR) override; NS_IMETHOD GetEffectiveTRRMode( nsIRequest::TRRMode* aEffectiveTRRMode) override; + NS_IMETHOD GetTrrSkipReason(nsITRRSkipReason::value* aTrrSkipReason) override; NS_IMETHOD GetIsLoadedBySocketProcess(bool* aResult) override; NS_IMETHOD GetIsOCSP(bool* value) override; NS_IMETHOD SetIsOCSP(bool value) override; @@ -794,6 +795,7 @@ class HttpBaseChannel : public nsHashPropertyBag, // Is initially set to TRR_DEFAULT_MODE, but should be updated to the actual // mode used by the request nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE; + TRRSkippedReason mTRRSkipReason = TRRSkippedReason::TRR_UNSET; public: void SetEarlyHints( diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 77b7810cbb54..465207231526 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -433,6 +433,7 @@ void HttpChannelChild::OnStartRequest( mAltDataLength = aArgs.altDataLength(); StoreResolvedByTRR(aArgs.isResolvedByTRR()); mEffectiveTRRMode = aArgs.effectiveTRRMode(); + mTRRSkipReason = aArgs.trrSkipReason(); SetApplyConversion(aArgs.applyConversion()); diff --git a/netwerk/protocol/http/HttpChannelParams.ipdlh b/netwerk/protocol/http/HttpChannelParams.ipdlh index cce95c0c5728..e85dd8f13c29 100644 --- a/netwerk/protocol/http/HttpChannelParams.ipdlh +++ b/netwerk/protocol/http/HttpChannelParams.ipdlh @@ -20,6 +20,7 @@ using nsILoadInfo::CrossOriginOpenerPolicy from "nsILoadInfo.h"; [RefCounted] using class nsIReferrerInfo from "nsIReferrerInfo.h"; [RefCounted] using class nsITransportSecurityInfo from "nsITransportSecurityInfo.h"; using nsIRequest::TRRMode from "nsIRequest.h"; +using TRRSkippedReason from "nsITRRSkipReason.h"; namespace mozilla { namespace net { @@ -57,6 +58,7 @@ struct HttpChannelOnStartRequestArgs bool hasHTTPSRR; bool isProxyUsed; TRRMode effectiveTRRMode; + TRRSkippedReason trrSkipReason; }; struct HttpChannelAltDataStream diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 32283138c110..8cee60cf3e2b 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -1263,6 +1263,10 @@ HttpChannelParent::OnStartRequest(nsIRequest* aRequest) { mChannel->GetEffectiveTRRMode(&effectiveMode); args.effectiveTRRMode() = effectiveMode; + TRRSkippedReason reason = TRRSkippedReason::TRR_UNSET; + mChannel->GetTrrSkipReason(&reason); + args.trrSkipReason() = reason; + if (mIPCClosed || !mBgParent->OnStartRequest( *responseHead, useResponseHead, diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 3d66fd23ff52..3a5592530050 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -8531,6 +8531,7 @@ nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec, if (nsCOMPtr r = do_QueryInterface(rec)) { r->GetEffectiveTRRMode(&mEffectiveTRRMode); + r->GetTrrSkipReason(&mTRRSkipReason); } LOG( diff --git a/netwerk/protocol/http/nsIHttpChannelInternal.idl b/netwerk/protocol/http/nsIHttpChannelInternal.idl index 404bb5ff2324..2f04b967241f 100644 --- a/netwerk/protocol/http/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl @@ -6,6 +6,7 @@ #include "nsISupports.idl" #include "nsILoadInfo.idl" #include "nsIRequest.idl" +#include "nsITRRSkipReason.idl" %{C++ #include "nsStringFwd.h" @@ -293,6 +294,12 @@ interface nsIHttpChannelInternal : nsISupports */ [must_use] readonly attribute nsIRequest_TRRMode effectiveTRRMode; + /** + * If the DNS request triggered by this channel didn't use TRR, this value + * contains the reason why that was skipped. + */ + [must_use] readonly attribute nsITRRSkipReason_value trrSkipReason; + /** * True if channel is loaded by socket process. */