From d163dee2af0ff3114f6dfb554a4dea9f62d6cbb8 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 11 Oct 2024 10:32:53 -0700 Subject: [PATCH] [dns-client] enhance logic for following up with IPv4 address query (#10781) This commit updates the `ReplaceWithIp4Query()` method, which determines whether an unsuccessful IPv6 address query should be followed up with an IPv4 query. The logic is changed as follows: - If the response code to the IPv6 query indicates success but the answer section is empty (meaning the name exists but has no IPv6 address), or the response code indicates an error other than `NameError`, the query is replaced with an IPv4 address resolution query for the same name. - If the server responds with `NameError` (RCode=3), indicating that the name doesn't exist, an IPv4 query is not attempted. This replaces the previous behavior where a follow-up query was attempted for any error response code. --- src/core/net/dns_client.cpp | 40 +++++++++++++++++++---- src/core/net/dns_client.hpp | 2 +- tests/unit/test_dnssd_discovery_proxy.cpp | 1 + 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp index bdf730296..61695dc4e 100644 --- a/src/core/net/dns_client.cpp +++ b/src/core/net/dns_client.cpp @@ -1309,17 +1309,18 @@ void Client::ProcessResponse(const Message &aResponseMessage) SuccessOrExit(ParseResponse(aResponseMessage, query, responseError)); +#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE + if (ReplaceWithIp4Query(*query, aResponseMessage) == kErrorNone) + { + ExitNow(); + } +#endif + if (responseError != kErrorNone) { // Received an error from server, check if we can replace // the query. -#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE - if (ReplaceWithIp4Query(*query) == kErrorNone) - { - ExitNow(); - } -#endif #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE if (ReplaceWithSeparateSrvTxtQueries(*query) == kErrorNone) { @@ -1556,16 +1557,41 @@ void Client::HandleTimer(void) #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE -Error Client::ReplaceWithIp4Query(Query &aQuery) +Error Client::ReplaceWithIp4Query(Query &aQuery, const Message &aResponseMessage) { Error error = kErrorFailed; QueryInfo info; + Header header; info.ReadFrom(aQuery); VerifyOrExit(info.mQueryType == kIp6AddressQuery); VerifyOrExit(info.mConfig.GetNat64Mode() == QueryConfig::kNat64Allow); + // Check the response to the IPv6 query from the server. If the + // response code is success but the answer section is empty + // (indicating the name exists but has no IPv6 address), or the + // response code indicates an error other than `NameError`, we + // replace the query with an IPv4 address resolution query for + // the same name. If the server responded with `NameError` + // (RCode=3), it indicates that the name doesn't exist, so there + // is no need to try an IPv4 query. + + SuccessOrExit(aResponseMessage.Read(aResponseMessage.GetOffset(), header)); + + switch (header.GetResponseCode()) + { + case Header::kResponseSuccess: + VerifyOrExit(header.GetAnswerCount() == 0); + OT_FALL_THROUGH; + + default: + break; + + case Header::kResponseNameError: + ExitNow(); + } + // We send a new query for IPv4 address resolution // for the same host name. We reuse the existing `aQuery` // instance and keep all the info but clear `mTransmissionCount` diff --git a/src/core/net/dns_client.hpp b/src/core/net/dns_client.hpp index 4ae017dd6..4591e5db3 100644 --- a/src/core/net/dns_client.hpp +++ b/src/core/net/dns_client.hpp @@ -805,7 +805,7 @@ private: void HandleTimer(void); #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE - Error ReplaceWithIp4Query(Query &aQuery); + Error ReplaceWithIp4Query(Query &aQuery, const Message &aResponseMessage); #endif #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE Error Resolve(const char *aInstanceLabel, diff --git a/tests/unit/test_dnssd_discovery_proxy.cpp b/tests/unit/test_dnssd_discovery_proxy.cpp index 09536821a..1c6db5f1b 100644 --- a/tests/unit/test_dnssd_discovery_proxy.cpp +++ b/tests/unit/test_dnssd_discovery_proxy.cpp @@ -1696,6 +1696,7 @@ void TestProxyTimeout(void) config.Clear(); config.mResponseTimeout = 120 * 1000; // 2 minutes (in msec) + config.mNat64Mode = OT_DNS_NAT64_DISALLOW; dnsClient->SetDefaultConfig(config); Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");