diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp index 2dd9531de..ef3fb3da2 100644 --- a/src/core/net/dns_client.cpp +++ b/src/core/net/dns_client.cpp @@ -168,7 +168,10 @@ Error Client::Response::CheckForHostNameAlias(Section aSection, Name &aHostName) { // If the response includes a CNAME record mapping the query host // name to a canonical name, we update `aHostName` to the new alias - // name. Otherwise `aHostName` remains as before. + // name. Otherwise `aHostName` remains as before. This method handles + // when there are multiple CNAME records mapping the host name multiple + // times. We limit number of changes to `kMaxCnameAliasNameChanges` + // to detect and handle if the response contains CNAME record loops. Error error; uint16_t offset; @@ -177,27 +180,32 @@ Error Client::Response::CheckForHostNameAlias(Section aSection, Name &aHostName) VerifyOrExit(mMessage != nullptr, error = kErrorNotFound); - SelectSection(aSection, offset, numRecords); - error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aHostName, cnameRecord); - - switch (error) + for (uint16_t counter = 0; counter < kMaxCnameAliasNameChanges; counter++) { - case kErrorNone: + SelectSection(aSection, offset, numRecords); + error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aHostName, cnameRecord); + + if (error == kErrorNotFound) + { + error = kErrorNone; + ExitNow(); + } + + SuccessOrExit(error); + // A CNAME record was found. `offset` now points to after the // last read byte within the `mMessage` into the `cnameRecord` // (which is the start of the new canonical name). + aHostName.SetFromMessage(*mMessage, offset); - error = Name::ParseName(*mMessage, offset); - break; + SuccessOrExit(error = Name::ParseName(*mMessage, offset)); - case kErrorNotFound: - error = kErrorNone; - break; - - default: - break; + // Loop back to check if there may be a CNAME record for the + // new `aHostName`. } + error = kErrorParse; + exit: return error; } diff --git a/src/core/net/dns_client.hpp b/src/core/net/dns_client.hpp index d663c91f8..e086f746b 100644 --- a/src/core/net/dns_client.hpp +++ b/src/core/net/dns_client.hpp @@ -770,6 +770,8 @@ public: #endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE private: + static constexpr uint16_t kMaxCnameAliasNameChanges = 40; + enum QueryType : uint8_t { kIp6AddressQuery, // IPv6 Address resolution.