Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp
Warning:line 263, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_netwerk_dns0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ Unified_cpp_netwerk_dns0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:set ts=4 sw=2 sts=2 et cin: */
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 "DNS.h"
8#include "DNSUtils.h"
9#include "nsCharSeparatedTokenizer.h"
10#include "nsContentUtils.h"
11#include "nsHttpHandler.h"
12#include "nsHttpChannel.h"
13#include "nsHostResolver.h"
14#include "nsIHttpChannel.h"
15#include "nsIHttpChannelInternal.h"
16#include "nsIIOService.h"
17#include "nsIInputStream.h"
18#include "nsIObliviousHttp.h"
19#include "nsISupports.h"
20#include "nsISupportsUtils.h"
21#include "nsITimedChannel.h"
22#include "nsIUploadChannel2.h"
23#include "nsIURIMutator.h"
24#include "nsNetUtil.h"
25#include "nsQueryObject.h"
26#include "nsStringStream.h"
27#include "nsThreadUtils.h"
28#include "nsURLHelper.h"
29#include "ObliviousHttpChannel.h"
30#include "TRR.h"
31#include "TRRService.h"
32#include "TRRServiceChannel.h"
33#include "TRRLoadInfo.h"
34
35#include "mozilla/Base64.h"
36#include "mozilla/DebugOnly.h"
37#include "mozilla/Logging.h"
38#include "mozilla/Preferences.h"
39#include "mozilla/StaticPrefs_network.h"
40#include "mozilla/Telemetry.h"
41#include "mozilla/TimeStamp.h"
42#include "mozilla/Tokenizer.h"
43#include "mozilla/UniquePtr.h"
44// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
45#include "DNSLogging.h"
46#include "mozilla/glean/GleanMetrics.h"
47
48namespace mozilla {
49namespace net {
50
51NS_IMPL_ISUPPORTS(TRR, nsIHttpPushListener, nsIInterfaceRequestor,MozExternalRefCountType TRR::AddRef(void) { static_assert(!std
::is_destructible_v<TRR>, "Reference-counted class " "TRR"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
52; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 52; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef
((this), (count), ("TRR"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType TRR::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 52
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 52; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); const char* const nametmp = "TRR"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult TRR::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<TRR, nsIHttpPushListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpPushListener*>((TRR*)0x1000
)) - reinterpret_cast<char*>((TRR*)0x1000))}, {&mozilla
::detail::kImplementedIID<TRR, nsIInterfaceRequestor>, int32_t
( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIRunnable
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRunnable
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIHttpPushListener*>((TRR*)0x1000))
) - reinterpret_cast<char*>((TRR*)0x1000))}, { nullptr,
0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
52 nsIStreamListener, nsIRunnable, nsITimerCallback)MozExternalRefCountType TRR::AddRef(void) { static_assert(!std
::is_destructible_v<TRR>, "Reference-counted class " "TRR"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
52; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 52; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef
((this), (count), ("TRR"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType TRR::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 52
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("TRR" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("TRR" != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("\"TRR\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"TRR\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 52; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("TRR" " not thread-safe"); const char* const nametmp = "TRR"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult TRR::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 52); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<TRR, nsIHttpPushListener>, int32_t( reinterpret_cast
<char*>(static_cast<nsIHttpPushListener*>((TRR*)0x1000
)) - reinterpret_cast<char*>((TRR*)0x1000))}, {&mozilla
::detail::kImplementedIID<TRR, nsIInterfaceRequestor>, int32_t
( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsIRunnable
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRunnable
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((TRR*)0x1000)) - reinterpret_cast<char*>((TRR*)0x1000
))}, {&mozilla::detail::kImplementedIID<TRR, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIHttpPushListener*>((TRR*)0x1000))
) - reinterpret_cast<char*>((TRR*)0x1000))}, { nullptr,
0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
53
54// when firing off a normal A or AAAA query
55TRR::TRR(AHostResolver* aResolver, nsHostRecord* aRec, enum TrrType aType)
56 : mozilla::Runnable("TRR"),
57 mRec(aRec),
58 mHostResolver(aResolver),
59 mType(aType),
60 mOriginSuffix(aRec->originSuffix) {
61 mHost = aRec->host;
62 mPB = aRec->pb;
63 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 64); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 64; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
64 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 64); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 64; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
65}
66
67// when following CNAMEs
68TRR::TRR(AHostResolver* aResolver, nsHostRecord* aRec, nsCString& aHost,
69 enum TrrType& aType, unsigned int aLoopCount, bool aPB)
70 : mozilla::Runnable("TRR"),
71 mHost(aHost),
72 mRec(aRec),
73 mHostResolver(aResolver),
74 mType(aType),
75 mPB(aPB),
76 mCnameLoop(aLoopCount),
77 mOriginSuffix(aRec ? aRec->originSuffix : ""_ns) {
78 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 79); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 79; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
79 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 79); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 79; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
80}
81
82// used on push
83TRR::TRR(AHostResolver* aResolver, bool aPB)
84 : mozilla::Runnable("TRR"), mHostResolver(aResolver), mPB(aPB) {
85 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 86); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
86 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 86); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 86; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
87}
88
89// to verify a domain
90TRR::TRR(AHostResolver* aResolver, nsACString& aHost, enum TrrType aType,
91 const nsACString& aOriginSuffix, bool aPB, bool aUseFreshConnection)
92 : mozilla::Runnable("TRR"),
93 mHost(aHost),
94 mRec(nullptr),
95 mHostResolver(aResolver),
96 mType(aType),
97 mPB(aPB),
98 mOriginSuffix(aOriginSuffix),
99 mUseFreshConnection(aUseFreshConnection) {
100 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 101); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 101; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
101 "TRR must be in parent or socket process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess() || XRE_IsSocketProcess())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_IsParentProcess() || XRE_IsSocketProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess() || XRE_IsSocketProcess()"
" (" "TRR must be in parent or socket process" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 101); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess() || XRE_IsSocketProcess()"
") (" "TRR must be in parent or socket process" ")"); do { *
((volatile int*)__null) = 101; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
102}
103
104void TRR::HandleTimeout() {
105 mTimeout = nullptr;
106 RecordReason(TRRSkippedReason::TRR_TIMEOUT);
107 Cancel(NS_ERROR_NET_TIMEOUT_EXTERNAL);
108}
109
110NS_IMETHODIMPnsresult
111TRR::Notify(nsITimer* aTimer) {
112 if (aTimer == mTimeout) {
113 HandleTimeout();
114 } else {
115 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 115); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"
); do { *((volatile int*)__null) = 115; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
116 }
117
118 return NS_OK;
119}
120
121NS_IMETHODIMPnsresult
122TRR::Run() {
123 MOZ_ASSERT_IF(XRE_IsParentProcess() && TRRService::Get(),do { if (XRE_IsParentProcess() && TRRService::Get()) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
")"); do { *((volatile int*)__null) = 124; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
124 NS_IsMainThread() || TRRService::Get()->IsOnTRRThread())do { if (XRE_IsParentProcess() && TRRService::Get()) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || TRRService::Get()->IsOnTRRThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || TRRService::Get()->IsOnTRRThread()"
")"); do { *((volatile int*)__null) = 124; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
125 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread())do { if (XRE_IsSocketProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(NS_IsMainThread(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
126
127 if ((TRRService::Get() == nullptr) || NS_FAILED(SendHTTPRequest())((bool)(__builtin_expect(!!(NS_FAILED_impl(SendHTTPRequest())
), 0)))
) {
128 RecordReason(TRRSkippedReason::TRR_SEND_FAILED);
129 FailData(NS_ERROR_FAILURE);
130 // The dtor will now be run
131 }
132 return NS_OK;
133}
134
135DNSPacket* TRR::GetOrCreateDNSPacket() {
136 if (!mPacket) {
137 mPacket = MakeUnique<DNSPacket>();
138 }
139
140 return mPacket.get();
141}
142
143nsresult TRR::CreateQueryURI(nsIURI** aOutURI) {
144 nsAutoCString uri;
145 nsCOMPtr<nsIURI> dnsURI;
146 if (UseDefaultServer()) {
147 TRRService::Get()->GetURI(uri);
148 } else {
149 uri = mRec->mTrrServer;
150 }
151
152 nsresult rv = NS_NewURI(getter_AddRefs(dnsURI), uri);
153 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
154 RecordReason(TRRSkippedReason::TRR_BAD_URL);
155 return rv;
156 }
157
158 dnsURI.forget(aOutURI);
159 return NS_OK;
160}
161
162bool TRR::MaybeBlockRequest() {
163 if (((mType == TRRTYPE_A) || (mType == TRRTYPE_AAAA)) &&
164 mRec->mEffectiveTRRMode != nsIRequest::TRR_ONLY_MODE) {
165 // let NS resolves skip the blocklist check
166 // we also don't check the blocklist for TRR only requests
167 MOZ_ASSERT(mRec)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRec)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mRec))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mRec", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRec" ")"); do
{ *((volatile int*)__null) = 167; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
168
169 // If TRRService isn't enabled anymore for the req, don't do TRR.
170 if (!TRRService::Get()->Enabled(mRec->mEffectiveTRRMode)) {
171 RecordReason(TRRSkippedReason::TRR_MODE_NOT_ENABLED);
172 return true;
173 }
174
175 if (!StaticPrefs::network_trr_strict_native_fallback() &&
176 UseDefaultServer() &&
177 TRRService::Get()->IsTemporarilyBlocked(mHost, mOriginSuffix, mPB,
178 true)) {
179 if (mType == TRRTYPE_A) {
180 // count only blocklist for A records to avoid double counts
181 Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED3,
182 TRRService::ProviderKey(), true);
183 }
184
185 RecordReason(TRRSkippedReason::TRR_HOST_BLOCKED_TEMPORARY);
186 // not really an error but no TRR is issued
187 return true;
188 }
189
190 if (TRRService::Get()->IsExcludedFromTRR(mHost)) {
191 RecordReason(TRRSkippedReason::TRR_EXCLUDED);
192 return true;
193 }
194
195 if (UseDefaultServer() && (mType == TRRTYPE_A)) {
196 Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED3,
197 TRRService::ProviderKey(), false);
198 }
199 }
200
201 return false;
202}
203
204nsresult TRR::SendHTTPRequest() {
205 // This is essentially the "run" method - created from nsHostResolver
206 if (mCancelled) {
207 return NS_ERROR_FAILURE;
208 }
209
210 if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
211 (mType != TRRTYPE_NS) && (mType != TRRTYPE_TXT) &&
212 (mType != TRRTYPE_HTTPSSVC)) {
213 // limit the calling interface because nsHostResolver has explicit slots for
214 // these types
215 return NS_ERROR_FAILURE;
216 }
217
218 if (MaybeBlockRequest()) {
219 return NS_ERROR_UNKNOWN_HOST;
220 }
221
222 LOG(("TRR::SendHTTPRequest resolve %s type %u\n", mHost.get(), mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest resolve %s type %u\n", mHost.get(), mType
); } } while (0)
;
223
224 nsAutoCString body;
225 bool disableECS = StaticPrefs::network_trr_disable_ECS();
226 nsresult rv =
227 GetOrCreateDNSPacket()->EncodeRequest(body, mHost, mType, disableECS);
228 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
229 HandleEncodeError(rv);
230 return rv;
231 }
232
233 bool useGet = StaticPrefs::network_trr_useGET();
234 nsCOMPtr<nsIURI> dnsURI;
235 rv = CreateQueryURI(getter_AddRefs(dnsURI));
236 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
237 LOG(("TRR:SendHTTPRequest: NewURI failed!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:SendHTTPRequest: NewURI failed!\n"); } } while (0)
;
238 return rv;
239 }
240
241 if (useGet) {
242 /* For GET requests, the outgoing packet needs to be Base64url-encoded and
243 then appended to the end of the URI. */
244 nsAutoCString encoded;
245 rv = Base64URLEncode(body.Length(),
246 reinterpret_cast<const unsigned char*>(body.get()),
247 Base64URLEncodePaddingPolicy::Omit, encoded);
248 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 248); return rv; } } while (false)
;
249
250 nsAutoCString query;
251 rv = dnsURI->GetQuery(query);
252 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
253 return rv;
254 }
255
256 if (query.IsEmpty()) {
257 query.Assign("?dns="_ns);
258 } else {
259 query.Append("&dns="_ns);
260 }
261 query.Append(encoded);
262
263 rv = NS_MutateURI(dnsURI).SetQuery(query).Finalize(dnsURI);
Value stored to 'rv' is never read
264 LOG(("TRR::SendHTTPRequest GET dns=%s\n", body.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest GET dns=%s\n", body.get()); } } while
(0)
;
265 }
266
267 nsCOMPtr<nsIChannel> channel;
268 bool useOHTTP = StaticPrefs::network_trr_use_ohttp();
269 if (useOHTTP) {
270 nsCOMPtr<nsIObliviousHttpService> ohttpService(
271 do_GetService("@mozilla.org/network/oblivious-http-service;1"));
272 if (!ohttpService) {
273 return NS_ERROR_FAILURE;
274 }
275 nsCOMPtr<nsIURI> relayURI;
276 nsTArray<uint8_t> encodedConfig;
277 rv = ohttpService->GetTRRSettings(getter_AddRefs(relayURI), encodedConfig);
278 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
279 return rv;
280 }
281 if (!relayURI) {
282 return NS_ERROR_FAILURE;
283 }
284 rv = ohttpService->NewChannel(relayURI, dnsURI, encodedConfig,
285 getter_AddRefs(channel));
286 } else {
287 rv = DNSUtils::CreateChannelHelper(dnsURI, getter_AddRefs(channel));
288 }
289 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !channel) {
290 LOG(("TRR:SendHTTPRequest: NewChannel failed!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:SendHTTPRequest: NewChannel failed!\n"); } } while (0)
;
291 return rv;
292 }
293
294 auto loadFlags = nsIRequest::LOAD_ANONYMOUS | nsIRequest::INHIBIT_CACHING |
295 nsIRequest::LOAD_BYPASS_CACHE |
296 nsIChannel::LOAD_BYPASS_URL_CLASSIFIER;
297 if (mUseFreshConnection) {
298 // Causes TRRServiceChannel to tell the connection manager
299 // to clear out any connection with the current conn info.
300 loadFlags |= nsIRequest::LOAD_FRESH_CONNECTION;
301 }
302 channel->SetLoadFlags(loadFlags);
303 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 303); return rv; } } while (false)
;
304
305 rv = channel->SetNotificationCallbacks(this);
306 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 306); return rv; } } while (false)
;
307
308 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
309 if (!httpChannel) {
310 return NS_ERROR_UNEXPECTED;
311 }
312
313 // This connection should not use TRR
314 rv = httpChannel->SetTRRMode(nsIRequest::TRR_DISABLED_MODE);
315 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 315); return rv; } } while (false)
;
316
317 nsCString contentType(ContentType());
318 rv = httpChannel->SetRequestHeader("Accept"_ns, contentType, false);
319 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 319); return rv; } } while (false)
;
320
321 nsAutoCString cred;
322 if (UseDefaultServer()) {
323 TRRService::Get()->GetCredentials(cred);
324 }
325 if (!cred.IsEmpty()) {
326 rv = httpChannel->SetRequestHeader("Authorization"_ns, cred, false);
327 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 327); return rv; } } while (false)
;
328 }
329
330 nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(channel);
331 if (!internalChannel) {
332 return NS_ERROR_UNEXPECTED;
333 }
334
335 // setting a small stream window means the h2 stack won't pipeline a window
336 // update with each HEADERS or reply to a DATA with a WINDOW UPDATE
337 rv = internalChannel->SetInitialRwin(127 * 1024);
338 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 338); return rv; } } while (false)
;
339 rv = internalChannel->SetIsTRRServiceChannel(true);
340 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 340); return rv; } } while (false)
;
341
342 if (UseDefaultServer() && StaticPrefs::network_trr_async_connInfo()) {
343 RefPtr<nsHttpConnectionInfo> trrConnInfo =
344 TRRService::Get()->TRRConnectionInfo();
345 if (trrConnInfo) {
346 nsAutoCString host;
347 dnsURI->GetHost(host);
348 if (host.Equals(trrConnInfo->GetOrigin())) {
349 internalChannel->SetConnectionInfo(trrConnInfo);
350 LOG(("TRR::SendHTTPRequest use conn info:%s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest use conn info:%s\n", trrConnInfo->
HashKey().get()); } } while (0)
351 trrConnInfo->HashKey().get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SendHTTPRequest use conn info:%s\n", trrConnInfo->
HashKey().get()); } } while (0)
;
352 } else {
353 MOZ_DIAGNOSTIC_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 353); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
")"); do { *((volatile int*)__null) = 353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
354 }
355 } else {
356 TRRService::Get()->InitTRRConnectionInfo();
357 }
358 }
359
360 if (useGet) {
361 rv = httpChannel->SetRequestMethod("GET"_ns);
362 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 362); return rv; } } while (false)
;
363 } else {
364 nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(httpChannel);
365 if (!uploadChannel) {
366 return NS_ERROR_UNEXPECTED;
367 }
368 uint32_t streamLength = body.Length();
369 nsCOMPtr<nsIInputStream> uploadStream;
370 rv =
371 NS_NewCStringInputStream(getter_AddRefs(uploadStream), std::move(body));
372 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 372); return rv; } } while (false)
;
373
374 rv = uploadChannel->ExplicitSetUploadStream(uploadStream, contentType,
375 streamLength, "POST"_ns, false);
376 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 376); return rv; } } while (false)
;
377 }
378
379 rv = SetupTRRServiceChannelInternal(httpChannel, useGet, contentType);
380 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
381 return rv;
382 }
383
384 rv = httpChannel->AsyncOpen(this);
385 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
386 return rv;
387 }
388
389 // If the asyncOpen succeeded we can say that we actually attempted to
390 // use the TRR connection.
391 RefPtr<AddrHostRecord> addrRec = do_QueryObject(mRec);
392 if (addrRec) {
393 addrRec->mResolverType = ResolverType();
394 }
395
396 NS_NewTimerWithCallback(
397 getter_AddRefs(mTimeout), this,
398 mTimeoutMs ? mTimeoutMs : TRRService::Get()->GetRequestTimeout(),
399 nsITimer::TYPE_ONE_SHOT);
400
401 mChannel = channel;
402 return NS_OK;
403}
404
405// static
406nsresult TRR::SetupTRRServiceChannelInternal(nsIHttpChannel* aChannel,
407 bool aUseGet,
408 const nsACString& aContentType) {
409 nsCOMPtr<nsIHttpChannel> httpChannel = aChannel;
410 MOZ_ASSERT(httpChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(httpChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(httpChannel))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("httpChannel", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { *((volatile int*)__null) = 410; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
411
412 nsresult rv = NS_OK;
413 if (!aUseGet) {
414 rv =
415 httpChannel->SetRequestHeader("Cache-Control"_ns, "no-store"_ns, false);
416 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 416); return rv; } } while (false)
;
417 }
418
419 // Sanitize the request by removing the Accept-Language header so we minimize
420 // the amount of fingerprintable information we send to the server.
421 if (!StaticPrefs::network_trr_send_accept_language_headers()) {
422 rv = httpChannel->SetRequestHeader("Accept-Language"_ns, ""_ns, false);
423 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 423); return rv; } } while (false)
;
424 }
425
426 // Sanitize the request by removing the User-Agent
427 if (!StaticPrefs::network_trr_send_user_agent_headers()) {
428 rv = httpChannel->SetRequestHeader("User-Agent"_ns, ""_ns, false);
429 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 429); return rv; } } while (false)
;
430 }
431
432 if (StaticPrefs::network_trr_send_empty_accept_encoding_headers()) {
433 rv = httpChannel->SetEmptyRequestHeader("Accept-Encoding"_ns);
434 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 434); return rv; } } while (false)
;
435 }
436
437 // set the *default* response content type
438 if (NS_FAILED(httpChannel->SetContentType(aContentType))((bool)(__builtin_expect(!!(NS_FAILED_impl(httpChannel->SetContentType
(aContentType))), 0)))
) {
439 LOG(("TRR::SetupTRRServiceChannelInternal: couldn't set content-type!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::SetupTRRServiceChannelInternal: couldn't set content-type!\n"
); } } while (0)
;
440 }
441
442 nsCOMPtr<nsITimedChannel> timedChan(do_QueryInterface(httpChannel));
443 if (timedChan) {
444 timedChan->SetTimingEnabled(true);
445 }
446
447 return NS_OK;
448}
449
450NS_IMETHODIMPnsresult
451TRR::GetInterface(const nsIID& iid, void** result) {
452 if (!iid.Equals(NS_GET_IID(nsIHttpPushListener)(nsIHttpPushListener::COMTypeInfo<nsIHttpPushListener, void
>::kIID)
)) {
453 return NS_ERROR_NO_INTERFACE;
454 }
455
456 nsCOMPtr<nsIHttpPushListener> copy(this);
457 *result = copy.forget().take();
458 return NS_OK;
459}
460
461nsresult TRR::DohDecodeQuery(const nsCString& query, nsCString& host,
462 enum TrrType& type) {
463 FallibleTArray<uint8_t> binary;
464 bool found_dns = false;
465 LOG(("TRR::DohDecodeQuery %s!\n", query.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery %s!\n", query.get()); } } while (0)
;
466
467 // extract "dns=" from the query string
468 nsAutoCString data;
469 for (const nsACString& token :
470 nsCCharSeparatedTokenizer(query, '&').ToRange()) {
471 nsDependentCSubstring dns = Substring(token, 0, 4);
472 nsAutoCString check(dns);
473 if (check.Equals("dns=")) {
474 nsDependentCSubstring q = Substring(token, 4, -1);
475 data = q;
476 found_dns = true;
477 break;
478 }
479 }
480 if (!found_dns) {
481 LOG(("TRR::DohDecodeQuery no dns= in pushed URI query string\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery no dns= in pushed URI query string\n")
; } } while (0)
;
482 return NS_ERROR_ILLEGAL_VALUE;
483 }
484
485 nsresult rv =
486 Base64URLDecode(data, Base64URLDecodePaddingPolicy::Ignore, binary);
487 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 487); return rv; } } while (false)
;
488 uint32_t avail = binary.Length();
489 if (avail < 12) {
490 return NS_ERROR_FAILURE;
491 }
492 // check the query bit and the opcode
493 if ((binary[2] & 0xf8) != 0) {
494 return NS_ERROR_FAILURE;
495 }
496 uint32_t qdcount = (binary[4] << 8) + binary[5];
497 if (!qdcount) {
498 return NS_ERROR_FAILURE;
499 }
500
501 uint32_t index = 12;
502 uint32_t length = 0;
503 host.Truncate();
504 do {
505 if (avail < (index + 1)) {
506 return NS_ERROR_UNEXPECTED;
507 }
508
509 length = binary[index];
510 if (length) {
511 if (host.Length()) {
512 host.Append(".");
513 }
514 if (avail < (index + 1 + length)) {
515 return NS_ERROR_UNEXPECTED;
516 }
517 host.Append((const char*)(&binary[0]) + index + 1, length);
518 }
519 index += 1 + length; // skip length byte + label
520 } while (length);
521
522 LOG(("TRR::DohDecodeQuery host %s\n", host.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery host %s\n", host.get()); } } while (0)
;
523
524 if (avail < (index + 2)) {
525 return NS_ERROR_UNEXPECTED;
526 }
527 uint16_t i16 = 0;
528 i16 += binary[index] << 8;
529 i16 += binary[index + 1];
530 type = (enum TrrType)i16;
531
532 LOG(("TRR::DohDecodeQuery type %d\n", (int)type))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::DohDecodeQuery type %d\n", (int)type); } } while (0)
;
533
534 return NS_OK;
535}
536
537nsresult TRR::ReceivePush(nsIHttpChannel* pushed, nsHostRecord* pushedRec) {
538 if (!mHostResolver) {
539 return NS_ERROR_UNEXPECTED;
540 }
541
542 LOG(("TRR::ReceivePush: PUSH incoming!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush: PUSH incoming!\n"); } } while (0)
;
543
544 nsCOMPtr<nsIURI> uri;
545 pushed->GetURI(getter_AddRefs(uri));
546 nsAutoCString query;
547 if (uri) {
548 uri->GetQuery(query);
549 }
550
551 if (NS_FAILED(DohDecodeQuery(query, mHost, mType))((bool)(__builtin_expect(!!(NS_FAILED_impl(DohDecodeQuery(query
, mHost, mType))), 0)))
||
552 HostIsIPLiteral(mHost)) { // literal
553 LOG(("TRR::ReceivePush failed to decode %s\n", mHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush failed to decode %s\n", mHost.get()); } }
while (0)
;
554 return NS_ERROR_UNEXPECTED;
555 }
556
557 if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
558 (mType != TRRTYPE_TXT) && (mType != TRRTYPE_HTTPSSVC)) {
559 LOG(("TRR::ReceivePush unknown type %d\n", mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::ReceivePush unknown type %d\n", mType); } } while (0)
;
560 return NS_ERROR_UNEXPECTED;
561 }
562
563 if (TRRService::Get()->IsExcludedFromTRR(mHost)) {
564 return NS_ERROR_FAILURE;
565 }
566
567 uint32_t type = nsIDNSService::RESOLVE_TYPE_DEFAULT;
568 if (mType == TRRTYPE_TXT) {
569 type = nsIDNSService::RESOLVE_TYPE_TXT;
570 } else if (mType == TRRTYPE_HTTPSSVC) {
571 type = nsIDNSService::RESOLVE_TYPE_HTTPSSVC;
572 }
573
574 RefPtr<nsHostRecord> hostRecord;
575 nsresult rv;
576 rv = mHostResolver->GetHostRecord(
577 mHost, ""_ns, type, pushedRec->flags, pushedRec->af, pushedRec->pb,
578 pushedRec->originSuffix, getter_AddRefs(hostRecord));
579 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
580 return rv;
581 }
582
583 // Since we don't ever call nsHostResolver::NameLookup for this record,
584 // we need to copy the trr mode from the previous record
585 if (hostRecord->mEffectiveTRRMode == nsIRequest::TRR_DEFAULT_MODE) {
586 hostRecord->mEffectiveTRRMode =
587 static_cast<nsIRequest::TRRMode>(pushedRec->mEffectiveTRRMode);
588 }
589
590 rv = mHostResolver->TrrLookup_unlocked(hostRecord, this);
591 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
592 return rv;
593 }
594
595 rv = pushed->AsyncOpen(this);
596 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
597 return rv;
598 }
599
600 // OK!
601 mChannel = pushed;
602 mRec.swap(hostRecord);
603
604 return NS_OK;
605}
606
607NS_IMETHODIMPnsresult
608TRR::OnPush(nsIHttpChannel* associated, nsIHttpChannel* pushed) {
609 LOG(("TRR::OnPush entry\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnPush entry\n"); } } while (0)
;
610 MOZ_ASSERT(associated == mChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(associated == mChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(associated == mChannel))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("associated == mChannel"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns/TRR.cpp"
, 610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "associated == mChannel"
")"); do { *((volatile int*)__null) = 610; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
611 if (!mRec) {
612 return NS_ERROR_FAILURE;
613 }
614 if (!UseDefaultServer()) {
615 return NS_ERROR_FAILURE;
616 }
617
618 RefPtr<TRR> trr = new TRR(mHostResolver, mPB);
619 trr->SetPurpose(mPurpose);
620 return trr->ReceivePush(pushed, mRec);
621}
622
623NS_IMETHODIMPnsresult
624TRR::OnStartRequest(nsIRequest* aRequest) {
625 LOG(("TRR::OnStartRequest %p %s %d\n", this, mHost.get(), mType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnStartRequest %p %s %d\n", this, mHost.get(), mType)
; } } while (0)
;
626
627 nsresult status = NS_OK;
628 aRequest->GetStatus(&status);
629
630 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
631 if (NS_IsOffline()) {
632 RecordReason(TRRSkippedReason::TRR_IS_OFFLINE);
633 }
634
635 switch (status) {
636 case NS_ERROR_UNKNOWN_HOST:
637 RecordReason(TRRSkippedReason::TRR_CHANNEL_DNS_FAIL);
638 break;
639 case NS_ERROR_OFFLINE:
640 RecordReason(TRRSkippedReason::TRR_IS_OFFLINE);
641 break;
642 case NS_ERROR_NET_RESET:
643 RecordReason(TRRSkippedReason::TRR_NET_RESET);
644 break;
645 case NS_ERROR_NET_TIMEOUT:
646 case NS_ERROR_NET_TIMEOUT_EXTERNAL:
647 RecordReason(TRRSkippedReason::TRR_NET_TIMEOUT);
648 break;
649 case NS_ERROR_PROXY_CONNECTION_REFUSED:
650 RecordReason(TRRSkippedReason::TRR_NET_REFUSED);
651 break;
652 case NS_ERROR_NET_INTERRUPT:
653 RecordReason(TRRSkippedReason::TRR_NET_INTERRUPT);
654 break;
655 case NS_ERROR_NET_INADEQUATE_SECURITY:
656 RecordReason(TRRSkippedReason::TRR_NET_INADEQ_SEQURITY);
657 break;
658 default:
659 RecordReason(TRRSkippedReason::TRR_UNKNOWN_CHANNEL_FAILURE);
660 }
661 }
662
663 return NS_OK;
664}
665
666void TRR::SaveAdditionalRecords(
667 const nsClassHashtable<nsCStringHashKey, DOHresp>& aRecords) {
668 if (!mRec) {
669 return;
670 }
671 nsresult rv;
672 for (const auto& recordEntry : aRecords) {
673 if (!recordEntry.GetData() || recordEntry.GetData()->mAddresses.IsEmpty()) {
674 // no point in adding empty records.
675 continue;
676 }
677 // If IPv6 is disabled don't add anything else than IPv4.
678 if (StaticPrefs::network_dns_disableIPv6() &&
679 std::find_if(recordEntry.GetData()->mAddresses.begin(),
680 recordEntry.GetData()->mAddresses.end(),
681 [](const NetAddr& addr) { return !addr.IsIPAddrV4(); }) !=
682 recordEntry.GetData()->mAddresses.end()) {
683 continue;
684 }
685 RefPtr<nsHostRecord> hostRecord;
686 rv = mHostResolver->GetHostRecord(
687 recordEntry.GetKey(), EmptyCString(),
688 nsIDNSService::RESOLVE_TYPE_DEFAULT, mRec->flags, AF_UNSPEC0, mRec->pb,
689 mRec->originSuffix, getter_AddRefs(hostRecord));
690 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
691 LOG(("Failed to get host record for additional record %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record for additional record %s", nsCString
(recordEntry.GetKey()).get()); } } while (0)
692 nsCString(recordEntry.GetKey()).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record for additional record %s", nsCString
(recordEntry.GetKey()).get()); } } while (0)
;
693 continue;
694 }
695 RefPtr<AddrInfo> ai(
696 new AddrInfo(recordEntry.GetKey(), ResolverType(), TRRTYPE_A,
697 std::move(recordEntry.GetData()->mAddresses),
698 recordEntry.GetData()->mTtl));
699 mHostResolver->MaybeRenewHostRecord(hostRecord);
700
701 // Since we're not actually calling NameLookup for this record, we need
702 // to set these fields to avoid assertions in CompleteLookup.
703 // This is quite hacky, and should be fixed.
704 hostRecord->Reset();
705 hostRecord->mResolving++;
706 hostRecord->mEffectiveTRRMode =
707 static_cast<nsIRequest::TRRMode>(mRec->mEffectiveTRRMode);
708 LOG(("Completing lookup for additional: %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Completing lookup for additional: %s", nsCString(recordEntry
.GetKey()).get()); } } while (0)
709 nsCString(recordEntry.GetKey()).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Completing lookup for additional: %s", nsCString(recordEntry
.GetKey()).get()); } } while (0)
;
710 (void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB,
711 mOriginSuffix, TRRSkippedReason::TRR_OK,
712 this);
713 }
714}
715
716void TRR::StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord) {
717 LOG(("TRR::StoreIPHintAsDNSRecord [%p] [%s]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::StoreIPHintAsDNSRecord [%p] [%s]", this, aSVCBRecord.
mSvcDomainName.get()); } } while (0)
718 aSVCBRecord.mSvcDomainName.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::StoreIPHintAsDNSRecord [%p] [%s]", this, aSVCBRecord.
mSvcDomainName.get()); } } while (0)
;
719 CopyableTArray<NetAddr> addresses;
720 aSVCBRecord.GetIPHints(addresses);
721
722 if (StaticPrefs::network_dns_disableIPv6()) {
723 addresses.RemoveElementsBy(
724 [](const NetAddr& addr) { return !addr.IsIPAddrV4(); });
725 }
726
727 if (addresses.IsEmpty()) {
728 return;
729 }
730
731 RefPtr<nsHostRecord> hostRecord;
732 nsresult rv = mHostResolver->GetHostRecord(
733 aSVCBRecord.mSvcDomainName, EmptyCString(),
734 nsIDNSService::RESOLVE_TYPE_DEFAULT,
735 mRec->flags | nsIDNSService::RESOLVE_IP_HINT, AF_UNSPEC0, mRec->pb,
736 mRec->originSuffix, getter_AddRefs(hostRecord));
737 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
738 LOG(("Failed to get host record"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Failed to get host record"); } } while (0)
;
739 return;
740 }
741
742 mHostResolver->MaybeRenewHostRecord(hostRecord);
743
744 RefPtr<AddrInfo> ai(new AddrInfo(aSVCBRecord.mSvcDomainName, ResolverType(),
745 TRRTYPE_A, std::move(addresses), mTTL));
746
747 // Since we're not actually calling NameLookup for this record, we need
748 // to set these fields to avoid assertions in CompleteLookup.
749 // This is quite hacky, and should be fixed.
750 hostRecord->mResolving++;
751 hostRecord->mEffectiveTRRMode =
752 static_cast<nsIRequest::TRRMode>(mRec->mEffectiveTRRMode);
753 (void)mHostResolver->CompleteLookup(hostRecord, NS_OK, ai, mPB, mOriginSuffix,
754 TRRSkippedReason::TRR_OK, this);
755}
756
757nsresult TRR::ReturnData(nsIChannel* aChannel) {
758 if (mType != TRRTYPE_TXT && mType != TRRTYPE_HTTPSSVC) {
759 // create and populate an AddrInfo instance to pass on
760 RefPtr<AddrInfo> ai(new AddrInfo(mHost, ResolverType(), mType,
761 nsTArray<NetAddr>(), mDNS.mTtl));
762 auto builder = ai->Build();
763 builder.SetAddresses(std::move(mDNS.mAddresses));
764 builder.SetCanonicalHostname(mCname);
765
766 // Set timings.
767 nsCOMPtr<nsITimedChannel> timedChan = do_QueryInterface(aChannel);
768 if (timedChan) {
769 TimeStamp asyncOpen, start, end;
770 if (NS_SUCCEEDED(timedChan->GetAsyncOpen(&asyncOpen))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetAsyncOpen
(&asyncOpen))), 1)))
&&
771 !asyncOpen.IsNull()) {
772 builder.SetTrrFetchDuration(
773 (TimeStamp::Now() - asyncOpen).ToMilliseconds());
774 }
775 if (NS_SUCCEEDED(timedChan->GetRequestStart(&start))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetRequestStart
(&start))), 1)))
&&
776 NS_SUCCEEDED(timedChan->GetResponseEnd(&end))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChan->GetResponseEnd
(&end))), 1)))
&& !start.IsNull() &&
777 !end.IsNull()) {
778 builder.SetTrrFetchDurationNetworkOnly((end - start).ToMilliseconds());
779 }
780 }
781 ai = builder.Finish();
782
783 if (!mHostResolver) {
784 return NS_ERROR_FAILURE;
785 }
786 RecordReason(TRRSkippedReason::TRR_OK);
787 (void)mHostResolver->CompleteLookup(mRec, NS_OK, ai, mPB, mOriginSuffix,
788 mTRRSkippedReason, this);
789 mHostResolver = nullptr;
790 mRec = nullptr;
791 } else {
792 RecordReason(TRRSkippedReason::TRR_OK);
793 (void)mHostResolver->CompleteLookupByType(mRec, NS_OK, mResult,
794 mTRRSkippedReason, mTTL, mPB);
795 }
796 return NS_OK;
797}
798
799nsresult TRR::FailData(nsresult error) {
800 if (!mHostResolver) {
801 return NS_ERROR_FAILURE;
802 }
803
804 // If we didn't record a reason until now, record a default one.
805 RecordReason(TRRSkippedReason::TRR_FAILED);
806
807 if (mType == TRRTYPE_TXT || mType == TRRTYPE_HTTPSSVC) {
808 TypeRecordResultType empty(Nothing{});
809 (void)mHostResolver->CompleteLookupByType(mRec, error, empty,
810 mTRRSkippedReason, 0, mPB);
811 } else {
812 // create and populate an TRR AddrInfo instance to pass on to signal that
813 // this comes from TRR
814 nsTArray<NetAddr> noAddresses;
815 RefPtr<AddrInfo> ai =
816 new AddrInfo(mHost, ResolverType(), mType, std::move(noAddresses));
817
818 (void)mHostResolver->CompleteLookup(mRec, error, ai, mPB, mOriginSuffix,
819 mTRRSkippedReason, this);
820 }
821
822 mHostResolver = nullptr;
823 mRec = nullptr;
824 return NS_OK;
825}
826
827void TRR::HandleDecodeError(nsresult aStatusCode) {
828 auto rcode = mPacket->GetRCode();
829 if (rcode.isOk() && rcode.unwrap() != 0) {
830 if (rcode.unwrap() == 0x03) {
831 RecordReason(TRRSkippedReason::TRR_NXDOMAIN);
832 } else {
833 RecordReason(TRRSkippedReason::TRR_RCODE_FAIL);
834 }
835 } else if (aStatusCode == NS_ERROR_UNKNOWN_HOST ||
836 aStatusCode == NS_ERROR_DEFINITIVE_UNKNOWN_HOST) {
837 RecordReason(TRRSkippedReason::TRR_NO_ANSWERS);
838 } else {
839 RecordReason(TRRSkippedReason::TRR_DECODE_FAILED);
840 }
841}
842
843bool TRR::HasUsableResponse() {
844 if (mType == TRRTYPE_A || mType == TRRTYPE_AAAA) {
845 return !mDNS.mAddresses.IsEmpty();
846 }
847 if (mType == TRRTYPE_TXT) {
848 return mResult.is<TypeRecordTxt>();
849 }
850 if (mType == TRRTYPE_HTTPSSVC) {
851 return mResult.is<TypeRecordHTTPSSVC>();
852 }
853 return false;
854}
855
856nsresult TRR::FollowCname(nsIChannel* aChannel) {
857 nsresult rv = NS_OK;
858 nsAutoCString cname;
859 while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mDNS.mAddresses.IsEmpty() && !mCname.IsEmpty() &&
860 mCnameLoop > 0) {
861 mCnameLoop--;
862 LOG(("TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(), mCname.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
863 mCnameLoop))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
;
864 cname = mCname;
865 mCname.Truncate();
866
867 LOG(("TRR: check for CNAME record for %s within previous response\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: check for CNAME record for %s within previous response\n"
, cname.get()); } } while (0)
868 cname.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: check for CNAME record for %s within previous response\n"
, cname.get()); } } while (0)
;
869 nsClassHashtable<nsCStringHashKey, DOHresp> additionalRecords;
870 rv = GetOrCreateDNSPacket()->Decode(
871 cname, mType, mCname, StaticPrefs::network_trr_allow_rfc1918(), mDNS,
872 mResult, additionalRecords, mTTL);
873 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
874 LOG(("TRR::FollowCname DohDecode %x\n", (int)rv))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::FollowCname DohDecode %x\n", (int)rv); } } while (0)
;
875 HandleDecodeError(rv);
876 }
877 }
878
879 // restore mCname as DohDecode() change it
880 mCname = cname;
881 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HasUsableResponse()) {
882 ReturnData(aChannel);
883 return NS_OK;
884 }
885
886 bool ra = mPacket && mPacket->RecursionAvailable().unwrapOr(false);
887 LOG(("ra = %d", ra))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "ra = %d", ra); } } while (0)
;
888 if (rv == NS_ERROR_UNKNOWN_HOST && ra) {
889 // If recursion is available, but no addresses have been returned,
890 // we can just return a failure here.
891 LOG(("TRR::FollowCname not sending another request as RA flag is set."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::FollowCname not sending another request as RA flag is set."
); } } while (0)
;
892 FailData(NS_ERROR_UNKNOWN_HOST);
893 return NS_OK;
894 }
895
896 if (!mCnameLoop) {
897 LOG(("TRR::On200Response CNAME loop, eject!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME loop, eject!\n"); } } while (0)
;
898 return NS_ERROR_REDIRECT_LOOP;
899 }
900
901 LOG(("TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(), mCname.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
902 mCnameLoop))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response CNAME %s => %s (%u)\n", mHost.get(),
mCname.get(), mCnameLoop); } } while (0)
;
903 RefPtr<TRR> trr =
904 new TRR(mHostResolver, mRec, mCname, mType, mCnameLoop, mPB);
905 trr->SetPurpose(mPurpose);
906 if (!TRRService::Get()) {
907 return NS_ERROR_FAILURE;
908 }
909 return TRRService::Get()->DispatchTRRRequest(trr);
910}
911
912nsresult TRR::On200Response(nsIChannel* aChannel) {
913 // decode body and create an AddrInfo struct for the response
914 nsClassHashtable<nsCStringHashKey, DOHresp> additionalRecords;
915 RefPtr<TypeHostRecord> typeRec = do_QueryObject(mRec);
916 if (typeRec && typeRec->mOriginHost) {
917 GetOrCreateDNSPacket()->SetOriginHost(typeRec->mOriginHost);
918 }
919 nsresult rv = GetOrCreateDNSPacket()->Decode(
920 mHost, mType, mCname, StaticPrefs::network_trr_allow_rfc1918(), mDNS,
921 mResult, additionalRecords, mTTL);
922 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
923 LOG(("TRR::On200Response DohDecode %x\n", (int)rv))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response DohDecode %x\n", (int)rv); } } while (0
)
;
924 HandleDecodeError(rv);
925 return rv;
926 }
927 if (StaticPrefs::network_trr_add_additional_records()) {
928 SaveAdditionalRecords(additionalRecords);
929 }
930
931 if (mResult.is<TypeRecordHTTPSSVC>()) {
932 auto& results = mResult.as<TypeRecordHTTPSSVC>();
933 for (const auto& rec : results) {
934 StoreIPHintAsDNSRecord(rec);
935 }
936 }
937
938 if (!mDNS.mAddresses.IsEmpty() || mType == TRRTYPE_TXT || mCname.IsEmpty()) {
939 // pass back the response data
940 ReturnData(aChannel);
941 return NS_OK;
942 }
943
944 LOG(("TRR::On200Response trying CNAME %s", mCname.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::On200Response trying CNAME %s", mCname.get()); } } while
(0)
;
945 return FollowCname(aChannel);
946}
947
948void TRR::RecordProcessingTime(nsIChannel* aChannel) {
949 // This method records the time it took from the last received byte of the
950 // DoH response until we've notified the consumer with a host record.
951 nsCOMPtr<nsITimedChannel> timedChan = do_QueryInterface(aChannel);
952 if (!timedChan) {
953 return;
954 }
955 TimeStamp end;
956 if (NS_FAILED(timedChan->GetResponseEnd(&end))((bool)(__builtin_expect(!!(NS_FAILED_impl(timedChan->GetResponseEnd
(&end))), 0)))
) {
957 return;
958 }
959
960 if (end.IsNull()) {
961 return;
962 }
963
964 Telemetry::AccumulateTimeDelta(Telemetry::DNS_TRR_PROCESSING_TIME, end);
965
966 LOG(("Processing DoH response took %f ms",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Processing DoH response took %f ms", (TimeStamp::Now() - end
).ToMilliseconds()); } } while (0)
967 (TimeStamp::Now() - end).ToMilliseconds()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "Processing DoH response took %f ms", (TimeStamp::Now() - end
).ToMilliseconds()); } } while (0)
;
968}
969
970void TRR::ReportStatus(nsresult aStatusCode) {
971 // If the TRR was cancelled by nsHostResolver, then we don't need to report
972 // it as failed; otherwise it can cause the confirmation to fail.
973 if (UseDefaultServer() && aStatusCode != NS_ERROR_ABORT) {
974 // Bad content is still considered "okay" if the HTTP response is okay
975 TRRService::Get()->RecordTRRStatus(this);
976 }
977}
978
979static void RecordHttpVersion(nsIHttpChannel* aHttpChannel) {
980 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
981 do_QueryInterface(aHttpChannel);
982 if (!internalChannel) {
983 LOG(("RecordHttpVersion: Failed to QI nsIHttpChannelInternal"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Failed to QI nsIHttpChannelInternal"); }
} while (0)
;
984 return;
985 }
986
987 uint32_t major, minor;
988 if (NS_FAILED(internalChannel->GetResponseVersion(&major, &minor))((bool)(__builtin_expect(!!(NS_FAILED_impl(internalChannel->
GetResponseVersion(&major, &minor))), 0)))
) {
989 LOG(("RecordHttpVersion: Failed to get protocol version"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Failed to get protocol version"); } } while
(0)
;
990 return;
991 }
992
993 auto label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_1;
994 if (major == 2) {
995 label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_2;
996 } else if (major == 3) {
997 label = Telemetry::LABELS_DNS_TRR_HTTP_VERSION2::h_3;
998 }
999
1000 Telemetry::AccumulateCategoricalKeyed(TRRService::ProviderKey(), label);
1001
1002 LOG(("RecordHttpVersion: Provider responded using HTTP version: %d", major))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "RecordHttpVersion: Provider responded using HTTP version: %d"
, major); } } while (0)
;
1003}
1004
1005NS_IMETHODIMPnsresult
1006TRR::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
1007 // The dtor will be run after the function returns
1008 LOG(("TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost
.get(), mType, mFailed, (unsigned int)aStatusCode); } } while
(0)
1009 mType, mFailed, (unsigned int)aStatusCode))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d failed=%d code=%X\n", this, mHost
.get(), mType, mFailed, (unsigned int)aStatusCode); } } while
(0)
;
1010 nsCOMPtr<nsIChannel> channel;
1011 channel.swap(mChannel);
1012
1013 mChannelStatus = aStatusCode;
1014 if (NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) {
1015 nsCString label = "regular"_ns;
1016 if (mPB) {
1017 label = "private"_ns;
1018 }
1019 mozilla::glean::networking::trr_request_count.Get(label).Add(1);
1020 }
1021
1022 {
1023 // Cancel the timer since we don't need it anymore.
1024 nsCOMPtr<nsITimer> timer;
1025 mTimeout.swap(timer);
1026 if (timer) {
1027 timer->Cancel();
1028 }
1029 }
1030
1031 auto scopeExit = MakeScopeExit([&] { ReportStatus(aStatusCode); });
1032
1033 nsresult rv = NS_OK;
1034 // if status was "fine", parse the response and pass on the answer
1035 if (!mFailed && NS_SUCCEEDED(aStatusCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatusCode)), 1)
))
) {
1036 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
1037 if (!httpChannel) {
1038 return NS_ERROR_UNEXPECTED;
1039 }
1040 nsAutoCString contentType;
1041 httpChannel->GetContentType(contentType);
1042 if (contentType.Length() &&
1043 !contentType.LowerCaseEqualsASCII(ContentType())) {
1044 LOG(("TRR:OnStopRequest %p %s %d wrong content type %s\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d wrong content type %s\n", this,
mHost.get(), mType, contentType.get()); } } while (0)
1045 mHost.get(), mType, contentType.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p %s %d wrong content type %s\n", this,
mHost.get(), mType, contentType.get()); } } while (0)
;
1046 FailData(NS_ERROR_UNEXPECTED);
1047 return NS_OK;
1048 }
1049
1050 uint32_t httpStatus;
1051 rv = httpChannel->GetResponseStatus(&httpStatus);
1052 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && httpStatus == 200) {
1053 rv = On200Response(channel);
1054 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && UseDefaultServer()) {
1055 RecordReason(TRRSkippedReason::TRR_OK);
1056 RecordProcessingTime(channel);
1057 RecordHttpVersion(httpChannel);
1058 return rv;
1059 }
1060 } else {
1061 RecordReason(TRRSkippedReason::TRR_SERVER_RESPONSE_ERR);
1062 LOG(("TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", __LINE__, this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", 1062, this
, (int)rv, httpStatus); } } while (0)
1063 (int)rv, httpStatus))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest:%d %p rv %x httpStatus %d\n", 1062, this
, (int)rv, httpStatus); } } while (0)
;
1064 }
1065 }
1066
1067 LOG(("TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode
, mFailed); } } while (0)
1068 mFailed))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnStopRequest %p status %x mFailed %d\n", this, (int)aStatusCode
, mFailed); } } while (0)
;
1069 FailData(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? NS_ERROR_UNKNOWN_HOST : rv);
1070 return NS_OK;
1071}
1072
1073NS_IMETHODIMPnsresult
1074TRR::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
1075 uint64_t aOffset, const uint32_t aCount) {
1076 LOG(("TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this, mHost.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this,
mHost.get(), mType, mFailed, (unsigned int)aCount); } } while
(0)
1077 mType, mFailed, (unsigned int)aCount))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR:OnDataAvailable %p %s %d failed=%d aCount=%u\n", this,
mHost.get(), mType, mFailed, (unsigned int)aCount); } } while
(0)
;
1078 // receive DNS response into the local buffer
1079 if (mFailed) {
1080 return NS_ERROR_FAILURE;
1081 }
1082
1083 nsresult rv = GetOrCreateDNSPacket()->OnDataAvailable(aRequest, aInputStream,
1084 aOffset, aCount);
1085 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1086 LOG(("TRR::OnDataAvailable:%d fail\n", __LINE__))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR::OnDataAvailable:%d fail\n", 1086); } } while (0)
;
1087 mFailed = true;
1088 return rv;
1089 }
1090 return NS_OK;
1091}
1092
1093void TRR::Cancel(nsresult aStatus) {
1094 bool isTRRServiceChannel = false;
1095 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
1096 do_QueryInterface(mChannel));
1097 if (httpChannelInternal) {
1098 nsresult rv =
1099 httpChannelInternal->GetIsTRRServiceChannel(&isTRRServiceChannel);
1100 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1101 isTRRServiceChannel = false;
1102 }
1103 }
1104 // nsHttpChannel can be only canceled on the main thread.
1105 RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel);
1106 if (isTRRServiceChannel && !XRE_IsSocketProcess() && !httpChannel) {
1107 if (TRRService::Get()) {
1108 nsCOMPtr<nsIThread> thread = TRRService::Get()->TRRThread();
1109 if (thread && !thread->IsOnCurrentThread()) {
1110 thread->Dispatch(NS_NewRunnableFunction(
1111 "TRR::Cancel",
1112 [self = RefPtr(this), aStatus]() { self->Cancel(aStatus); }));
1113 return;
1114 }
1115 }
1116 } else {
1117 if (!NS_IsMainThread()) {
1118 NS_DispatchToMainThread(NS_NewRunnableFunction(
1119 "TRR::Cancel",
1120 [self = RefPtr(this), aStatus]() { self->Cancel(aStatus); }));
1121 return;
1122 }
1123 }
1124
1125 if (mCancelled) {
1126 return;
1127 }
1128 mCancelled = true;
1129
1130 if (mChannel) {
1131 RecordReason(TRRSkippedReason::TRR_REQ_CANCELLED);
1132 LOG(("TRR: %p canceling Channel %p %s %d status=%" PRIx32 "\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: %p canceling Channel %p %s %d status=%" "x" "\n", this
, mChannel.get(), mHost.get(), mType, static_cast<uint32_t
>(aStatus)); } } while (0)
1133 mChannel.get(), mHost.get(), mType, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHostResolverLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, "TRR: %p canceling Channel %p %s %d status=%" "x" "\n", this
, mChannel.get(), mHost.get(), mType, static_cast<uint32_t
>(aStatus)); } } while (0)
;
1134 mChannel->Cancel(aStatus);
1135 }
1136}
1137
1138bool TRR::UseDefaultServer() { return !mRec || mRec->mTrrServer.IsEmpty(); }
1139
1140} // namespace net
1141} // namespace mozilla