[dns] add Name::StripName() and support in-place ExtractLabels() (#10037)

- Updates `Dns::Name::ExtractLabels()` for in-place label extraction,
  optimizing string operations.
- Introduces `Name::StripName()` to efficiently remove a suffix name
  from a DNS name in place.
- Updates and simplifies unit tests `test_dns` to validate new
  functionality.
This commit is contained in:
Abtin Keshavarzian
2024-04-17 15:21:16 -07:00
committed by GitHub
parent b6a1dc8fe8
commit be7d36e4ff
3 changed files with 94 additions and 64 deletions
+5 -1
View File
@@ -732,7 +732,11 @@ Error Name::ExtractLabels(const char *aName, const char *aSuffixName, char *aLab
nameLength -= (suffixLength + 1);
VerifyOrExit(nameLength < aLabelsSize, error = kErrorNoBufs);
memcpy(aLabels, aName, nameLength);
if (aLabels != aName)
{
memmove(aLabels, aName, nameLength);
}
aLabels[nameLength] = kNullChar;
error = kErrorNone;
+28
View File
@@ -1028,6 +1028,9 @@ public:
* Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise
* `kErrorParse` is returned.
*
* The @p aLabels buffer may be the same as @p aName for in-place label extraction. In this case, the
* implementation avoids unnecessary character copies.
*
* @param[in] aName The name to extract labels from.
* @param[in] aSuffixName The suffix name (e.g., can be domain name).
* @param[out] aLabels Pointer to buffer to copy the extracted labels.
@@ -1047,6 +1050,9 @@ public:
* Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise
* `kErrorParse` is returned.
*
* The @p aLabels buffer may be the same as @p aName for in-place label extraction. In this case, the
* implementation avoids unnecessary character copies.
*
* @tparam kLabelsBufferSize Size of the buffer string.
*
* @param[in] aName The name to extract labels from.
@@ -1064,6 +1070,28 @@ public:
return ExtractLabels(aName, aSuffixName, aLabels, kLabelsBufferSize);
}
/**
* Strips a given suffix name (e.g., a domain name) from a given DNS name string, updating it in place.
*
* First checks that @p Name ends with the given @p aSuffixName, otherwise `kErrorParse` is returned.
*
* Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise
* `kErrorParse` is returned.
*
* @tparam kNameBufferSize The size of name buffer.
*
* @param[in] aName The name buffer to strip the @p aSuffixName from.
* @param[in] aSuffixName The suffix name (e.g., can be domain name).
*
* @retval kErrorNone Successfully stripped the suffix name from @p aName.
* @retval kErrorParse @p aName does not contain @p aSuffixName.
*
*/
template <uint16_t kNameBufferSize> static Error StripName(char (&aName)[kNameBufferSize], const char *aSuffixName)
{
return ExtractLabels(aName, aSuffixName, aName, kNameBufferSize);
}
/**
* Tests if a DNS name is a sub-domain of a given domain.
*
+61 -63
View File
@@ -276,79 +276,77 @@ void TestDnsName(void)
printf("----------------------------------------------------------------\n");
printf("Extracting label(s) and removing domains:\n");
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
{
struct TestCase
{
const char *mFullName;
const char *mSuffixName;
const char *mLabels;
};
fullName = "my-service._ipps._tcp.default.service.arpa";
suffixName = "default.service.arpa";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
static const TestCase kTestCases[] = {
{"my-service._ipps._tcp.default.service.arpa.", "default.service.arpa.", "my-service._ipps._tcp"},
{"my-service._ipps._tcp.default.service.arpa", "default.service.arpa", "my-service._ipps._tcp"},
{"my.service._ipps._tcp.default.service.arpa.", "_ipps._tcp.default.service.arpa.", "my.service"},
{"my-service._ipps._tcp.default.service.arpa.", "DeFault.SerVice.ARPA.", "my-service._ipps._tcp"},
{"my-service._ipps._tcp.default.service.arpa", "DeFault.SerVice.ARPA", "my-service._ipps._tcp"},
fullName = "my-service._ipps._tcp.default.service.arpa";
suffixName = "default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
{"my-service._ipps._tcp.default.service.arpa", "default.service.arpa.", nullptr},
{"my-service._ipps._tcp.default.service.arpa.", "default.service.arpa", nullptr},
{"my-service._ipps._tcp.default.service.arpa.", "efault.service.arpa.", nullptr},
{"my-service._ipps._tcp.default.service.arpa", "efault.service.arpa", nullptr},
{"my-service._ipps._tcp.default.service.arpa.", "xdefault.service.arpa.", nullptr},
{"my-service._ipps._tcp.default.service.arpa.", ".default.service.arpa.", nullptr},
{"my-service._ipps._tcp.default.service.arpa.", "default.service.arp.", nullptr},
{"default.service.arpa.", "default.service.arpa.", nullptr},
{"default.service.arpa", "default.service.arpa", nullptr},
{"efault.service.arpa.", "default.service.arpa.", nullptr},
};
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
for (const TestCase &testCase : kTestCases)
{
Error error;
fullName = "my.service._ipps._tcp.default.service.arpa.";
suffixName = "_ipps._tcp.default.service.arpa.";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my.service") == 0);
printf("\n");
printf(" FullName : %s\n", testCase.mFullName);
printf(" SuffixName : %s\n", testCase.mSuffixName);
printf(" Extracted labels: %s\n", (testCase.mLabels != nullptr) ? testCase.mLabels : "(parse)");
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "DeFault.SerVice.ARPA.";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
error = Dns::Name::ExtractLabels(testCase.mFullName, testCase.mSuffixName, name);
fullName = "my-service._ipps._tcp.default.service.arpa";
suffixName = "DeFault.SerVice.ARPA";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
if (testCase.mLabels != nullptr)
{
SuccessOrQuit(error);
VerifyOrQuit(strcmp(name, testCase.mLabels) == 0);
}
else
{
VerifyOrQuit(error == kErrorParse);
}
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "efault.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
strcpy(name, testCase.mFullName);
error = Dns::Name::StripName(name, testCase.mSuffixName);
fullName = "my-service._ipps._tcp.default.service.arpa";
suffixName = "efault.service.arpa";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
if (testCase.mLabels != nullptr)
{
SuccessOrQuit(error);
VerifyOrQuit(strcmp(name, testCase.mLabels) == 0);
}
else
{
VerifyOrQuit(error == kErrorParse);
}
}
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "xdefault.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 22));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = ".default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arp.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "default.service.arpa.";
suffixName = "default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "default.service.arpa";
suffixName = "default.service.arpa";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "efault.service.arpa.";
suffixName = "default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 22));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 21) == kErrorNoBufs);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 21) == kErrorNoBufs);
}
printf("----------------------------------------------------------------\n");
printf("Append names, check encoded bytes, parse name and read labels:\n");