Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / dns / PlatformDNSWin.cpp
blob4b91ad407516a25086445e72da62dac5e5909b79
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/. */
7 #include "GetAddrInfo.h"
8 #include "mozilla/glean/NetwerkMetrics.h"
9 #include "mozilla/net/DNSPacket.h"
10 #include "nsIDNSService.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/ScopeExit.h"
13 #include "mozilla/StaticPrefs_network.h"
15 #ifdef DNSQUERY_AVAILABLE
16 // There is a bug in windns.h where the type of parameter ppQueryResultsSet for
17 // DnsQuery_A is dependent on UNICODE being set. It should *always* be
18 // PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this
19 // we make sure that UNICODE is unset.
20 # undef UNICODE
21 # include <ws2tcpip.h>
22 # undef GetAddrInfo
23 # include <windns.h>
24 #endif // DNSQUERY_AVAILABLE
26 namespace mozilla::net {
28 #define LOG(msg, ...) \
29 MOZ_LOG(gGetAddrInfoLog, LogLevel::Debug, ("[DNS]: " msg, ##__VA_ARGS__))
31 nsresult ResolveHTTPSRecordImpl(const nsACString& aHost,
32 nsIDNSService::DNSFlags aFlags,
33 TypeRecordResultType& aResult, uint32_t& aTTL) {
34 nsAutoCString host(aHost);
35 PDNS_RECORD result = nullptr;
36 nsAutoCString cname;
37 aTTL = UINT32_MAX;
39 if (xpc::IsInAutomation() &&
40 !StaticPrefs::network_dns_native_https_query_in_automation()) {
41 return NS_ERROR_UNKNOWN_HOST;
44 TimeStamp startTime = TimeStamp::Now();
46 DNS_STATUS status =
47 DnsQuery_A(host.get(), nsIDNSService::RESOLVE_TYPE_HTTPSSVC,
48 DNS_QUERY_STANDARD, nullptr, &result, nullptr);
50 mozilla::glean::networking::dns_native_https_call_time.AccumulateRawDuration(
51 TimeStamp::Now() - startTime);
53 if (status != ERROR_SUCCESS) {
54 LOG("DnsQuery_A failed with error: %ld\n", status);
55 return NS_ERROR_UNKNOWN_HOST;
58 // This will free the record if we exit early from this function.
59 auto freeDnsRecord =
60 MakeScopeExit([&]() { DnsRecordListFree(result, DnsFreeRecordList); });
62 auto CheckRecords = [&aResult, &cname, &aTTL](
63 PDNS_RECORD result,
64 const nsCString& aHost) -> nsresult {
65 PDNS_RECORD current = result;
67 for (current = result; current; current = current->pNext) {
68 if (strcmp(current->pName, aHost.get()) != 0) {
69 continue;
71 if (current->wType == nsIDNSService::RESOLVE_TYPE_HTTPSSVC) {
72 const unsigned char* ptr = (const unsigned char*)&(current->Data);
73 struct SVCB parsed;
74 nsresult rv = DNSPacket::ParseHTTPS(current->wDataLength, parsed, 0,
75 ptr, current->wDataLength, aHost);
76 if (NS_FAILED(rv)) {
77 return rv;
80 if (parsed.mSvcDomainName.IsEmpty() && parsed.mSvcFieldPriority == 0) {
81 // For AliasMode SVCB RRs, a TargetName of "." indicates that the
82 // service is not available or does not exist.
83 continue;
86 if (parsed.mSvcFieldPriority == 0) {
87 // Alias form SvcDomainName must not have the "." value (empty)
88 if (parsed.mSvcDomainName.IsEmpty()) {
89 return NS_ERROR_UNEXPECTED;
91 cname = parsed.mSvcDomainName;
92 ToLowerCase(cname);
93 break;
96 if (!aResult.is<TypeRecordHTTPSSVC>()) {
97 aResult = mozilla::AsVariant(CopyableTArray<SVCB>());
99 auto& results = aResult.as<TypeRecordHTTPSSVC>();
100 results.AppendElement(parsed);
101 aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
102 } else if (current->wType == DNS_TYPE_CNAME) {
103 cname = current->Data.Cname.pNameHost;
104 ToLowerCase(cname);
105 aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
106 break;
109 return NS_OK;
112 int32_t loopCount = 64;
113 while (loopCount > 0 && aResult.is<Nothing>()) {
114 loopCount--;
116 nsresult rv = CheckRecords(result, host);
117 if (NS_FAILED(rv)) {
118 return rv;
121 if (aResult.is<Nothing>() && !cname.IsEmpty()) {
122 host = cname;
123 cname.Truncate();
124 continue;
127 if (aResult.is<Nothing>()) {
128 return NS_ERROR_UNKNOWN_HOST;
132 // CNAME loop
133 if (loopCount == 0) {
134 return NS_ERROR_UNKNOWN_HOST;
137 if (aResult.is<Nothing>()) {
138 // The call succeeded, but no HTTPS records were found.
139 return NS_ERROR_UNKNOWN_HOST;
142 if (aTTL == UINT32_MAX) {
143 aTTL = 60; // Defaults to 60 seconds
145 return NS_OK;
148 void DNSThreadShutdown() {}
150 } // namespace mozilla::net