Bug 1844673 [wpt PR 41130] - Update wpt metadata, a=testonly
[gecko.git] / netwerk / dns / PlatformDNSWin.cpp
blob42f1483ec3274503ab89938880f02756a4fc12c1
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/net/DNSPacket.h"
9 #include "nsIDNSService.h"
10 #include "mozilla/Maybe.h"
11 #include "mozilla/ScopeExit.h"
12 #include "mozilla/StaticPrefs_network.h"
14 #ifdef DNSQUERY_AVAILABLE
15 // There is a bug in windns.h where the type of parameter ppQueryResultsSet for
16 // DnsQuery_A is dependent on UNICODE being set. It should *always* be
17 // PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this
18 // we make sure that UNICODE is unset.
19 # undef UNICODE
20 # include <ws2tcpip.h>
21 # undef GetAddrInfo
22 # include <windns.h>
23 #endif // DNSQUERY_AVAILABLE
25 namespace mozilla::net {
27 #define LOG(msg, ...) \
28 MOZ_LOG(gGetAddrInfoLog, LogLevel::Debug, ("[DNS]: " msg, ##__VA_ARGS__))
30 nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
31 TypeRecordResultType& aResult, uint32_t& aTTL) {
32 nsAutoCString host(aHost);
33 PDNS_RECORD result = nullptr;
34 nsAutoCString cname;
35 aTTL = UINT32_MAX;
37 if (xpc::IsInAutomation() &&
38 !StaticPrefs::network_dns_native_https_query_in_automation()) {
39 return NS_ERROR_UNKNOWN_HOST;
42 DNS_STATUS status =
43 DnsQuery_A(host.get(), nsIDNSService::RESOLVE_TYPE_HTTPSSVC,
44 DNS_QUERY_STANDARD, nullptr, &result, nullptr);
45 if (status != ERROR_SUCCESS) {
46 LOG("DnsQuery_A failed with error: %ld\n", status);
47 return NS_ERROR_UNKNOWN_HOST;
50 // This will free the record if we exit early from this function.
51 auto freeDnsRecord =
52 MakeScopeExit([&]() { DnsRecordListFree(result, DnsFreeRecordList); });
54 auto CheckRecords = [&aResult, &cname, &aTTL](
55 PDNS_RECORD result,
56 const nsCString& aHost) -> nsresult {
57 PDNS_RECORD current = result;
59 for (current = result; current; current = current->pNext) {
60 if (strcmp(current->pName, aHost.get()) != 0) {
61 continue;
63 if (current->wType == nsIDNSService::RESOLVE_TYPE_HTTPSSVC) {
64 const unsigned char* ptr = (const unsigned char*)&(current->Data);
65 struct SVCB parsed;
66 nsresult rv = DNSPacket::ParseHTTPS(current->wDataLength, parsed, 0,
67 ptr, current->wDataLength, aHost);
68 if (NS_FAILED(rv)) {
69 return rv;
72 if (parsed.mSvcDomainName.IsEmpty() && parsed.mSvcFieldPriority == 0) {
73 // For AliasMode SVCB RRs, a TargetName of "." indicates that the
74 // service is not available or does not exist.
75 continue;
78 if (parsed.mSvcFieldPriority == 0) {
79 // Alias form SvcDomainName must not have the "." value (empty)
80 if (parsed.mSvcDomainName.IsEmpty()) {
81 return NS_ERROR_UNEXPECTED;
83 cname = parsed.mSvcDomainName;
84 ToLowerCase(cname);
85 break;
88 if (!aResult.is<TypeRecordHTTPSSVC>()) {
89 aResult = mozilla::AsVariant(CopyableTArray<SVCB>());
91 auto& results = aResult.as<TypeRecordHTTPSSVC>();
92 results.AppendElement(parsed);
93 aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
94 } else if (current->wType == DNS_TYPE_CNAME) {
95 cname = current->Data.Cname.pNameHost;
96 ToLowerCase(cname);
97 aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
98 break;
101 return NS_OK;
104 int32_t loopCount = 64;
105 while (loopCount > 0 && aResult.is<Nothing>()) {
106 loopCount--;
108 nsresult rv = CheckRecords(result, host);
109 if (NS_FAILED(rv)) {
110 return rv;
113 if (aResult.is<Nothing>() && !cname.IsEmpty()) {
114 host = cname;
115 cname.Truncate();
116 continue;
119 if (aResult.is<Nothing>()) {
120 return NS_ERROR_UNKNOWN_HOST;
124 // CNAME loop
125 if (loopCount == 0) {
126 return NS_ERROR_UNKNOWN_HOST;
129 if (aResult.is<Nothing>()) {
130 // The call succeeded, but no HTTPS records were found.
131 return NS_ERROR_UNKNOWN_HOST;
134 if (aTTL == UINT32_MAX) {
135 aTTL = 60; // Defaults to 60 seconds
137 return NS_OK;
140 void DNSThreadShutdown() {}
142 } // namespace mozilla::net