Files
sousa-gecko/netwerk/dns/PlatformDNSWin.cpp
T
Emilio Cobos Álvarez abbeff4fd9 Bug 2054311 - Sort headers in netwerk/. r=webrtc-reviewers,cookie-reviewers,mjf,timhuang
Autogenerated with:

    cp dom/.clang-format netwerk/ && mach format netwerk/**.{cpp,h,mm}

Manual fixes:

 * mozurl/cbindgen.toml (including headers earlier)
 * NetlinkService.h (forward-declaring a necessary struct)
 * nsIWebSocketChannel.idl (forward-declaring OriginAttributes).
 * nsAsyncRedirectVerifyHelper.h (forward-declaring nsIEventTarget)
 * CapsuleEncoder.h gets a missing Capsule forward-decl.
 * WebSocketConnectionBase.h gets some missing includes.
 * HappyEyeballsConnectionAttempt gets some missing includes.
 * nsUDPSocket missed nsSocketTransportService2.h for OnSocketThread().
 * HttpInfo missed a forward declaration.
 * MockHttpAuth missed an nsCOMPtr include.
 * nsHttpAuthManager missed a forward declaration for nsIHttpAuthCache.
 * WebTransportSessionProxy was using mozilla::Mutex in a member without
   including it.
 * win32 fixes to keep include order because windows headers suck.
 * nsInputStreamPump needs an Atomics.h include.

Differential Revision: https://phabricator.services.mozilla.com/D311696
2026-07-13 09:55:57 +00:00

149 lines
4.5 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GetAddrInfo.h"
#include "mozilla/Maybe.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/glean/NetwerkMetrics.h"
#include "mozilla/net/DNSPacket.h"
#include "nsIDNSService.h"
#ifdef DNSQUERY_AVAILABLE
// There is a bug in windns.h where the type of parameter ppQueryResultsSet for
// DnsQuery_A is dependent on UNICODE being set. It should *always* be
// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this
// we make sure that UNICODE is unset.
# undef UNICODE
# include <ws2tcpip.h>
# undef GetAddrInfo
# include <windns.h>
#endif // DNSQUERY_AVAILABLE
namespace mozilla::net {
#define LOG(msg, ...) \
MOZ_LOG(gGetAddrInfoLog, LogLevel::Debug, ("[DNS]: " msg, ##__VA_ARGS__))
nsresult ResolveHTTPSRecordImpl(const nsACString& aHost,
nsIDNSService::DNSFlags aFlags,
TypeRecordResultType& aResult, uint32_t& aTTL) {
nsAutoCString host(aHost);
PDNS_RECORD result = nullptr;
nsAutoCString cname;
aTTL = UINT32_MAX;
if (xpc::IsInAutomation() &&
!StaticPrefs::network_dns_native_https_query_in_automation()) {
return NS_ERROR_UNKNOWN_HOST;
}
TimeStamp startTime = TimeStamp::Now();
DNS_STATUS status =
DnsQuery_A(host.get(), nsIDNSService::RESOLVE_TYPE_HTTPSSVC,
DNS_QUERY_STANDARD, nullptr, &result, nullptr);
mozilla::glean::networking::dns_native_https_call_time.AccumulateRawDuration(
TimeStamp::Now() - startTime);
if (status != ERROR_SUCCESS) {
LOG("DnsQuery_A failed with error: %ld\n", status);
return NS_ERROR_UNKNOWN_HOST;
}
// This will free the record if we exit early from this function.
auto freeDnsRecord =
MakeScopeExit([&]() { DnsRecordListFree(result, DnsFreeRecordList); });
auto CheckRecords = [&aResult, &cname, &aTTL](
PDNS_RECORD result,
const nsCString& aHost) -> nsresult {
PDNS_RECORD current = result;
for (current = result; current; current = current->pNext) {
if (strcmp(current->pName, aHost.get()) != 0) {
continue;
}
if (current->wType == nsIDNSService::RESOLVE_TYPE_HTTPSSVC) {
const unsigned char* ptr = (const unsigned char*)&(current->Data);
struct SVCB parsed;
nsresult rv = DNSPacket::ParseHTTPS(current->wDataLength, parsed, 0,
ptr, current->wDataLength, aHost);
if (NS_FAILED(rv)) {
return rv;
}
if (parsed.mSvcDomainName.IsEmpty() && parsed.mSvcFieldPriority == 0) {
// For AliasMode SVCB RRs, a TargetName of "." indicates that the
// service is not available or does not exist.
continue;
}
if (parsed.mSvcFieldPriority == 0) {
// Alias form SvcDomainName must not have the "." value (empty)
if (parsed.mSvcDomainName.IsEmpty()) {
return NS_ERROR_UNEXPECTED;
}
cname = parsed.mSvcDomainName;
ToLowerCase(cname);
break;
}
if (!aResult.is<TypeRecordHTTPSSVC>()) {
aResult = mozilla::AsVariant(CopyableTArray<SVCB>());
}
auto& results = aResult.as<TypeRecordHTTPSSVC>();
results.AppendElement(parsed);
aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
} else if (current->wType == DNS_TYPE_CNAME) {
cname = current->Data.Cname.pNameHost;
ToLowerCase(cname);
aTTL = std::min<uint32_t>(aTTL, current->dwTtl);
break;
}
}
return NS_OK;
};
int32_t loopCount = 64;
while (loopCount > 0 && aResult.is<Nothing>()) {
loopCount--;
nsresult rv = CheckRecords(result, host);
if (NS_FAILED(rv)) {
return rv;
}
if (aResult.is<Nothing>() && !cname.IsEmpty()) {
host = cname;
cname.Truncate();
continue;
}
if (aResult.is<Nothing>()) {
return NS_ERROR_UNKNOWN_HOST;
}
}
// CNAME loop
if (loopCount == 0) {
return NS_ERROR_UNKNOWN_HOST;
}
if (aResult.is<Nothing>()) {
// The call succeeded, but no HTTPS records were found.
return NS_ERROR_UNKNOWN_HOST;
}
if (aTTL == UINT32_MAX) {
aTTL = 60; // Defaults to 60 seconds
}
return NS_OK;
}
void DNSThreadShutdown() {}
} // namespace mozilla::net