Skip to content

Commit

Permalink
[dns] support longer key length in otDnsTxtEntryIterator (openthrea…
Browse files Browse the repository at this point in the history
…d#9616)

This commit introduces `OT_DNS_TXT_KEY_ITER_MAX_LENGTH` with a value
of `64` to represent the maximum TXT data key length supported by
`otDnsTxtEntryIterator`. We intentionally set this value higher than
the recommended maximum key length of `9` (as specified in RFC 6763
section 6.4) to enable the parsing of TXT data when longer keys are
employed.
  • Loading branch information
abtink authored Nov 20, 2023
1 parent 23c0fc4 commit 657b973
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 13 deletions.
10 changes: 6 additions & 4 deletions include/openthread/dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ extern "C" {

#define OT_DNS_TXT_KEY_MAX_LENGTH 9 ///< Recommended maximum length of TXT record key string (RFC 6763 - section 6.4).

#define OT_DNS_TXT_KEY_ITER_MAX_LENGTH 64 ///< Maximum length of TXT key string supported by `otDnsTxtEntryIterator`.

/**
* Represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3).
*
Expand Down Expand Up @@ -104,7 +106,7 @@ typedef struct otDnsTxtEntryIterator
{
const void *mPtr;
uint16_t mData[2];
char mChar[OT_DNS_TXT_KEY_MAX_LENGTH + 1];
char mChar[OT_DNS_TXT_KEY_ITER_MAX_LENGTH + 1];
} otDnsTxtEntryIterator;

/**
Expand All @@ -127,9 +129,9 @@ void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t *
* data buffer used to initialize the iterator MUST persist and remain unchanged. Otherwise the behavior of this
* function is undefined.
*
* If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_MAX_LENGTH` (recommended max key length)
* the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and the
* entire encoded TXT entry string is returned in `mValue` and `mValueLength`.
* If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_ITER_MAX_LENGTH` the key string is
* returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and the entire encoded TXT
* entry string is returned in `mValue` and `mValueLength`.
*
* @param[in] aIterator A pointer to the iterator (MUST NOT be NULL).
* @param[out] aEntry A pointer to a `otDnsTxtEntry` structure to output the parsed/read entry (MUST NOT be NULL).
Expand Down
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (371)
#define OPENTHREAD_API_VERSION (373)

/**
* @addtogroup api-instance
Expand Down
6 changes: 3 additions & 3 deletions src/core/net/dns_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry)
const char *cur;
char *keyBuffer = GetKeyBuffer();

static_assert(sizeof(mChar) == TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length");
static_assert(sizeof(mChar) >= TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length");

VerifyOrExit(GetTxtData() != nullptr, error = kErrorParse);

Expand Down Expand Up @@ -985,9 +985,9 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry)
ExitNow();
}

if (index >= kMaxKeyLength)
if (index >= sizeof(mChar) - 1)
{
// The key is larger than recommended max key length.
// The key is larger than supported key string length.
// In this case, we return the full encoded string in
// `mValue` and `mValueLength` and set `mKey` to
// `nullptr`.
Expand Down
14 changes: 11 additions & 3 deletions src/core/net/dns_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,14 @@ class TxtEntry : public otDnsTxtEntry
*/
static constexpr uint8_t kMaxKeyLength = OT_DNS_TXT_KEY_MAX_LENGTH;

/**
* Maximum length of TXT key string supported by `Iterator`.
*
* This is selected to be longer than recommended `kMaxKeyLength` to handle cases where longer keys are used.
*
*/
static constexpr uint8_t kMaxIterKeyLength = OT_DNS_TXT_KEY_ITER_MAX_LENGTH;

/**
* Represents an iterator for TXT record entries (key/value pairs).
*
Expand Down Expand Up @@ -1083,9 +1091,9 @@ class TxtEntry : public otDnsTxtEntry
* The `Iterator` instance MUST be initialized using `Init()` before calling this method and the TXT data
* buffer used to initialize the iterator MUST persist and remain unchanged.
*
* If the parsed key string length is smaller than or equal to `kMaxKeyLength` (recommended max key length)
* the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and
* the entire encoded TXT entry is returned in `mValue` and `mValueLength`.
* If the parsed key string length is smaller than or equal to `kMaxIterKeyLength` the key string is returned
* in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to `nullptr` the entire encoded TXT
* entry is returned in `mValue` and `mValueLength`.
*
* @param[out] aEntry A reference to a `TxtEntry` to output the parsed/read entry.
*
Expand Down
2 changes: 1 addition & 1 deletion src/core/radio/trel_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ Error Interface::ParsePeerInfoTxtData(const Peer::Info &aInfo,
while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
{
// If the TXT data happens to have entries with key longer
// than `kMaxKeyLength`, `mKey` would be `nullptr` and full
// than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full
// entry would be placed in `mValue`. We skip over such
// entries.
if (entry.mKey == nullptr)
Expand Down
17 changes: 16 additions & 1 deletion tests/unit/test_dns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,9 @@ void TestDnsTxtEntry(void)
const char kKey6[] = "boolKey"; // Should be encoded as "boolKey" (without `=`).
const char kKey7[] = "emptyKey"; // Should be encoded as "emptyKey=".

const char kKey8[] = "1234567890123456789012345678901234567890123456789012345678901234567890";
const uint8_t kValue8[] = "abcd";

// Invalid key
const char kShortKey[] = "";

Expand All @@ -1312,6 +1315,17 @@ void TestDnsTxtEntry(void)
const uint8_t kEncodedTxt5[] = {12, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '=', 'a'};
const uint8_t kEncodedTxt6[] = {7, 'b', 'o', 'o', 'l', 'K', 'e', 'y'};
const uint8_t kEncodedTxt7[] = {9, 'e', 'm', 'p', 't', 'y', 'K', 'e', 'y', '='};
const uint8_t kEncodedTxt8[] = {
75, // length
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 10
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 20
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 40
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 50
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 60
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 70
'=', 'a', 'b', 'c', 'd',
};

const uint8_t kInvalidEncodedTxt1[] = {4, 'a', '=', 'b'}; // Incorrect length

Expand All @@ -1327,6 +1341,7 @@ void TestDnsTxtEntry(void)
Dns::TxtEntry(kKey5, kValue5, sizeof(kValue5)),
Dns::TxtEntry(kKey6, nullptr, 0),
Dns::TxtEntry(kKey7, kValue1, 0),
Dns::TxtEntry(kKey8, kValue8, sizeof(kValue8)),
};

const EncodedTxtData kEncodedTxtData[] = {
Expand Down Expand Up @@ -1381,7 +1396,7 @@ void TestDnsTxtEntry(void)
SuccessOrQuit(iterator.GetNextEntry(txtEntry), "TxtEntry::GetNextEntry() failed");
printf("key:\"%s\" valueLen:%d\n", txtEntry.mKey != nullptr ? txtEntry.mKey : "(null)", txtEntry.mValueLength);

if (expectedKeyLength > Dns::TxtEntry::kMaxKeyLength)
if (expectedKeyLength > Dns::TxtEntry::kMaxIterKeyLength)
{
// When the key is longer than recommended max key length,
// the full encoded string is returned in `mValue` and
Expand Down

0 comments on commit 657b973

Please sign in to comment.