diff --git a/include/openthread/dns.h b/include/openthread/dns.h index f34322b75..2a5dd1373 100644 --- a/include/openthread/dns.h +++ b/include/openthread/dns.h @@ -38,6 +38,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -140,6 +141,32 @@ void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t * */ otError otDnsGetNextTxtEntry(otDnsTxtEntryIterator *aIterator, otDnsTxtEntry *aEntry); +/** + * This function enables/disables the "DNS name compression" mode. + * + * By default DNS name compression is enabled. When disabled, DNS names are appended as full and never compressed. This + * is applicable to OpenThread's DNS and SRP client/server modules. + * + * This is intended for testing only and available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` config is enabled. + * + * Note that in the case `OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE` is used, this mode applies to all OpenThread + * instances (i.e., calling this function enables/disables the compression mode on all OpenThread instances). + * + * @param[in] aEnabled TRUE to enable the "DNS name compression" mode, FALSE to disable. + * + */ +void otDnsSetNameCompressionEnabled(bool aEnabled); + +/** + * This function indicates whether the "DNS name compression" mode is enabled or not. + * + * This is intended for testing only and available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` config is enabled. + * + * @returns TRUE if the "DNS name compression" mode is enabled, FALSE otherwise. + * + */ +bool otDnsIsNameCompressionEnabled(void); + /** * @} * diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 00f5e317f..29919e319 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (92) +#define OPENTHREAD_API_VERSION (93) /** * @addtogroup api-instance diff --git a/src/cli/README.md b/src/cli/README.md index 7641d8090..1c0b4e706 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -991,6 +991,33 @@ Send a service instance resolution DNS query for a given service instance. Servi The parameters after `service-name` are optional. Any unspecified (or zero) value for these optional parameters is replaced by the value from the current default config (`dns config`). +### dns compression \[enable|disable\] + +Enable/Disable the "DNS name compression" mode. + +By default DNS name compression is enabled. When disabled, DNS names are appended as full and never compressed. This is applicable to OpenThread's DNS and SRP client/server modules. + +This is intended for testing only and available under `REFERENCE_DEVICE` config. + +Get the current "DNS name compression" mode. + +``` +> dns compression +Enabled +``` + +Set the "DNS name compression" mode. + +``` +> dns compression disable +Done +> +> +> dns compression +Disabled +Done +``` + ### domainname Get the Thread Domain Name for Thread 1.2 device. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 8ad91a50a..d17b32650 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1369,52 +1369,52 @@ void Interpreter::OutputDnsTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLen OutputFormat("]"); } -#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE - -otError Interpreter::GetDnsConfig(uint8_t aArgsLength, - char * aArgs[], - otDnsQueryConfig *&aConfig, - uint8_t aStartArgsIndex) -{ - // This method gets the optional config from given `aArgs` after the - // `aStartArgsIndex`. The format: `[server IPv6 address] [server - // port] [timeout] [max tx attempt] [recursion desired]`. - - otError error = OT_ERROR_NONE; - bool recursionDesired; - - memset(aConfig, 0, sizeof(otDnsQueryConfig)); - - VerifyOrExit(aArgsLength > aStartArgsIndex, aConfig = nullptr); - - SuccessOrExit(error = ParseAsIp6Address(aArgs[aStartArgsIndex], aConfig->mServerSockAddr.mAddress)); - - VerifyOrExit(aArgsLength > aStartArgsIndex + 1); - SuccessOrExit(error = ParseAsUint16(aArgs[aStartArgsIndex + 1], aConfig->mServerSockAddr.mPort)); - - VerifyOrExit(aArgsLength > aStartArgsIndex + 2); - SuccessOrExit(error = ParseAsUint32(aArgs[aStartArgsIndex + 2], aConfig->mResponseTimeout)); - - VerifyOrExit(aArgsLength > aStartArgsIndex + 3); - SuccessOrExit(error = ParseAsUint8(aArgs[aStartArgsIndex + 3], aConfig->mMaxTxAttempts)); - - VerifyOrExit(aArgsLength > aStartArgsIndex + 4); - SuccessOrExit(error = ParseAsBool(aArgs[aStartArgsIndex + 4], recursionDesired)); - aConfig->mRecursionFlag = recursionDesired ? OT_DNS_FLAG_RECURSION_DESIRED : OT_DNS_FLAG_NO_RECURSION; - -exit: - return error; -} - otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[]) { - otError error = OT_ERROR_NONE; + OT_UNUSED_VARIABLE(aArgs); + + otError error = OT_ERROR_NONE; +#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE otDnsQueryConfig queryConfig; otDnsQueryConfig *config = &queryConfig; +#endif - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); + if (aArgsLength == 0) + { + error = OT_ERROR_INVALID_ARGS; + } +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + else if (strcmp(aArgs[0], "compression") == 0) + { + if (aArgsLength == 1) + { + OutputEnabledDisabledStatus(otDnsIsNameCompressionEnabled()); + } + else + { + bool enable; - if (strcmp(aArgs[0], "config") == 0) + VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); + + if (strcmp(aArgs[1], "enable") == 0) + { + enable = true; + } + else if (strcmp(aArgs[1], "disable") == 0) + { + enable = false; + } + else + { + ExitNow(error = OT_ERROR_INVALID_COMMAND); + } + + otDnsSetNameCompressionEnabled(enable); + } + } +#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE + else if (strcmp(aArgs[0], "config") == 0) { if (aArgsLength == 1) { @@ -1457,6 +1457,7 @@ otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[]) error = OT_ERROR_PENDING; } #endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE +#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE else { ExitNow(error = OT_ERROR_INVALID_COMMAND); @@ -1466,6 +1467,43 @@ exit: return error; } +#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE + +otError Interpreter::GetDnsConfig(uint8_t aArgsLength, + char * aArgs[], + otDnsQueryConfig *&aConfig, + uint8_t aStartArgsIndex) +{ + // This method gets the optional config from given `aArgs` after the + // `aStartArgsIndex`. The format: `[server IPv6 address] [server + // port] [timeout] [max tx attempt] [recursion desired]`. + + otError error = OT_ERROR_NONE; + bool recursionDesired; + + memset(aConfig, 0, sizeof(otDnsQueryConfig)); + + VerifyOrExit(aArgsLength > aStartArgsIndex, aConfig = nullptr); + + SuccessOrExit(error = ParseAsIp6Address(aArgs[aStartArgsIndex], aConfig->mServerSockAddr.mAddress)); + + VerifyOrExit(aArgsLength > aStartArgsIndex + 1); + SuccessOrExit(error = ParseAsUint16(aArgs[aStartArgsIndex + 1], aConfig->mServerSockAddr.mPort)); + + VerifyOrExit(aArgsLength > aStartArgsIndex + 2); + SuccessOrExit(error = ParseAsUint32(aArgs[aStartArgsIndex + 2], aConfig->mResponseTimeout)); + + VerifyOrExit(aArgsLength > aStartArgsIndex + 3); + SuccessOrExit(error = ParseAsUint8(aArgs[aStartArgsIndex + 3], aConfig->mMaxTxAttempts)); + + VerifyOrExit(aArgsLength > aStartArgsIndex + 4); + SuccessOrExit(error = ParseAsBool(aArgs[aStartArgsIndex + 4], recursionDesired)); + aConfig->mRecursionFlag = recursionDesired ? OT_DNS_FLAG_RECURSION_DESIRED : OT_DNS_FLAG_NO_RECURSION; + +exit: + return error; +} + void Interpreter::HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse, void *aContext) { static_cast(aContext)->HandleDnsAddressResponse(aError, aResponse); diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 8f54fd294..3091d846c 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -374,9 +374,7 @@ private: otError ProcessDiag(uint8_t aArgsLength, char *aArgs[]); #endif otError ProcessDiscover(uint8_t aArgsLength, char *aArgs[]); -#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE otError ProcessDns(uint8_t aArgsLength, char *aArgs[]); -#endif #if OPENTHREAD_FTD otError ProcessEidCache(uint8_t aArgsLength, char *aArgs[]); #endif @@ -671,9 +669,7 @@ private: {"diag", &Interpreter::ProcessDiag}, #endif {"discover", &Interpreter::ProcessDiscover}, -#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE {"dns", &Interpreter::ProcessDns}, -#endif #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) {"domainname", &Interpreter::ProcessDomainName}, #endif diff --git a/src/core/api/dns_api.cpp b/src/core/api/dns_api.cpp index 5038a4763..d92c68234 100644 --- a/src/core/api/dns_api.cpp +++ b/src/core/api/dns_api.cpp @@ -52,6 +52,18 @@ otError otDnsGetNextTxtEntry(otDnsTxtEntryIterator *aIterator, otDnsTxtEntry *aE return static_cast(aIterator)->GetNextEntry(*static_cast(aEntry)); } +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +void otDnsSetNameCompressionEnabled(bool aEnabled) +{ + Instance::SetDnsNameCompressionEnabled(aEnabled); +} + +bool otDnsIsNameCompressionEnabled(void) +{ + return Instance::IsDnsNameCompressionEnabled(); +} +#endif + #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE const otDnsQueryConfig *otDnsClientGetDefaultConfig(otInstance *aInstance) diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index 1e37ef876..2d5e62bc7 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -52,6 +52,9 @@ OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t); #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE Utils::Heap Instance::sHeap; #endif +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +bool Instance::sDnsNameCompressionEnabled = true; +#endif #endif Instance::Instance(void) diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index a4ad5be90..d87f68b16 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -283,6 +283,29 @@ public: Coap::CoapSecure &GetApplicationCoapSecure(void) { return mApplicationCoapSecure; } #endif +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + /** + * This method enables/disables the "DNS name compressions" mode. + * + * By default DNS name compression is enabled. When disabled, DNS names are appended as full and never compressed. + * This is applicable to OpenThread's DNS and SRP client/server modules. + * + * This is intended for testing only and available under a `REFERENCE_DEVICE` config. + * + * @param[in] aEnabled TRUE to enable the "DNS name compression" mode, FALSE to disable. + * + */ + static void SetDnsNameCompressionEnabled(bool aEnabled) { sDnsNameCompressionEnabled = aEnabled; } + + /** + * This method indicates whether the "DNS name compression" mode is enabled or not. + * + * @returns TRUE if the "DNS name compressions" mode is enabled, FALSE otherwise. + * + */ + static bool IsDnsNameCompressionEnabled(void) { return sDnsNameCompressionEnabled; } +#endif + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD /** @@ -396,6 +419,10 @@ private: FactoryDiags::Diags mDiags; #endif bool mIsInitialized; + +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD) + static bool sDnsNameCompressionEnabled; +#endif }; // Specializations of the `Get()` method. diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp index ebb0524bf..7f2c4fc4d 100644 --- a/src/core/net/dns_types.cpp +++ b/src/core/net/dns_types.cpp @@ -35,6 +35,7 @@ #include "common/code_utils.hpp" #include "common/debug.hpp" +#include "common/instance.hpp" #include "common/logging.hpp" #include "common/random.hpp" #include "common/string.hpp" @@ -221,6 +222,23 @@ Error Name::AppendTerminator(Message &aMessage) Error Name::AppendPointerLabel(uint16_t aOffset, Message &aMessage) { + Error error; + uint16_t value; + +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + if (!Instance::IsDnsNameCompressionEnabled()) + { + // If "DNS name compression" mode is disabled, instead of + // appending the pointer label, read the name from the message + // and append it uncompressed. Note that the `aOffset` parameter + // in this method is given relative to the start of DNS header + // in `aMessage` (which `aMessage.GetOffset()` specifies). + + error = Name(aMessage, aOffset + aMessage.GetOffset()).AppendTo(aMessage); + ExitNow(); + } +#endif + // A pointer label takes the form of a two byte sequence as a // `uint16_t` value. The first two bits are ones. This allows a // pointer to be distinguished from a text label, since the text @@ -228,13 +246,14 @@ Error Name::AppendPointerLabel(uint16_t aOffset, Message &aMessage) // restricted to 63 octets or less). The next 14-bits specify // an offset value relative to start of DNS header. - uint16_t value; - OT_ASSERT(aOffset < kPointerLabelTypeUint16); value = HostSwap16(aOffset | kPointerLabelTypeUint16); - return aMessage.Append(value); + ExitNow(error = aMessage.Append(value)); + +exit: + return error; } Error Name::AppendName(const char *aName, Message &aMessage)