[dns] add Name::ComapreMultipleLabels() and update Matches() (#9744)

This commit introduces a new method, `Name::CompareMultipleLabels()`,
to efficiently parse and compare multiple DNS name labels directly
from a message. This is then used to optimize `Name::Matches()`
eliminating the need to read the entire name into a separate buffer.

This commit also updates `Name::Matches()` method to treat the
first label as a single label allowing it to include dot character
(which is useful for service instance label).

Additionally, `test_dns` unit test is updated to validate the
functionality of the new methods.
This commit is contained in:
Abtin Keshavarzian
2023-12-28 18:26:35 -08:00
committed by GitHub
parent 3f99b118d4
commit 666a9bd076
3 changed files with 204 additions and 48 deletions
+124 -20
View File
@@ -59,8 +59,8 @@ void TestDnsName(void)
struct TestMatches
{
const char *mFullName;
const char *mFirstLabels;
const char *mSecondLabels;
const char *mFirstLabel;
const char *mLabels;
const char *mDomain;
bool mShouldMatch;
};
@@ -79,6 +79,7 @@ void TestDnsName(void)
const char *domain2;
const char *fullName;
const char *suffixName;
Dns::Name dnsName;
static const uint8_t kEncodedName1[] = {7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0};
static const uint8_t kEncodedName2[] = {3, 'f', 'o', 'o', 1, 'a', 2, 'b', 'b', 3, 'e', 'd', 'u', 0};
@@ -150,9 +151,7 @@ void TestDnsName(void)
static const TestMatches kTestMatches[] = {
{"foo.bar.local.", "foo", "bar", "local.", true},
{"foo.bar.local.", "foo.bar", nullptr, "local.", true},
{"foo.bar.local.", nullptr, "foo.bar", "local.", true},
{"foo.bar.local.", nullptr, nullptr, "foo.bar.local.", true},
{"foo.bar.local.", "foo", "ba", "local.", false},
{"foo.bar.local.", "fooooo", "bar", "local.", false},
{"foo.bar.local.", "foo", "bar", "locall.", false},
@@ -160,11 +159,8 @@ void TestDnsName(void)
{"foo.bar.local.", "foo", "barr", "local.", false},
{"foo.bar.local.", "foo", "bar", ".local.", false},
{"My Lovely Instance._mt._udp.local.", "mY lovely instancE", "_mt._udp", "local.", true},
{"My Lovely Instance._mt._udp.local.", "mY lovely instancE._mt", "_udp", "local.", true},
{"_s1._sub._srv._udp.default.service.arpa.", "_s1._sub", "_srv._udp", "default.service.arpa.", true},
{"_s1._sub._srv._udp.default.service.arpa.", "_s1._sub", "_srv._udp", "default.service.arpa", false},
{"_s1._sub._srv._udp.default.service.arpa.", "_s1._sub", "_srv._udp.", "default.service.arpa.", false},
{"_s1._sub._srv._udp.default.service.arpa.", "_s1._sub.", "_srv._udp", "default.service.arpa.", false},
{"My Lovely Instance._mt._udp.local.", nullptr, "mY lovely instancE._mt._udp", "local.", true},
{"_s1._sub._srv._udp.default.service.arpa.", "_s1", "_sub._srv._udp", "default.service.arpa.", true},
};
printf("================================================================\n");
@@ -555,20 +551,48 @@ void TestDnsName(void)
for (const TestMatches &test : kTestMatches)
{
Dns::Name name;
printf(" \"%s\"\n", test.mFullName);
name.Set(test.mFullName);
VerifyOrQuit(name.Matches(test.mFirstLabels, test.mSecondLabels, test.mDomain) == test.mShouldMatch);
dnsName.Set(test.mFullName);
VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
IgnoreError(message->SetLength(0));
SuccessOrQuit(name.AppendTo(*message));
SuccessOrQuit(dnsName.AppendTo(*message));
name.SetFromMessage(*message, 0);
VerifyOrQuit(name.Matches(test.mFirstLabels, test.mSecondLabels, test.mDomain) == test.mShouldMatch);
dnsName.SetFromMessage(*message, 0);
VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
}
IgnoreError(message->SetLength(0));
dnsName.SetFromMessage(*message, 0);
SuccessOrQuit(Dns::Name::AppendLabel("Name.With.Dot", *message));
SuccessOrQuit(Dns::Name::AppendName("_srv._udp.local.", *message));
VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
VerifyOrQuit(!dnsName.Matches("Name", "With.Dot._srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.", "With.Dot._srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With", "Dot._srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
offset = 0;
SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
dnsName.Set(name);
VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
message->Free();
testFreeInstance(instance);
}
@@ -601,6 +625,13 @@ void TestDnsCompressedName(void)
static const char *kName3Labels[] = {"ISI", "ARPA"};
static const char *kName4Labels[] = {"Human.Readable", "F", "ISI", "ARPA"};
static const char *kName1MultiLabels[] = {"F.ISI", "ARPA"};
static const char *kName2MultiLabels1[] = {"FOO", "F.ISI.ARPA."};
static const char *kName2MultiLabels2[] = {"FOO.F.", "ISI.ARPA."};
static const char kName1BadMultiLabels[] = "F.ISI.ARPA.MORE";
static const char kName2BadMultiLabels[] = "FOO.F.IS";
static const char kExpectedReadName1[] = "F.ISI.ARPA.";
static const char kExpectedReadName2[] = "FOO.F.ISI.ARPA.";
static const char kExpectedReadName3[] = "ISI.ARPA.";
@@ -712,11 +743,35 @@ void TestDnsCompressedName(void)
VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::ReadName() returned incorrect offset");
offset = name1Offset;
for (const char *nameLabel : kName1Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name1Offset;
for (const char *nameLabel : kName1Labels)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name1Offset;
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName1));
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name1Offset;
VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
offset = name1Offset;
VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName1BadMultiLabels) == kErrorNotFound);
offset = name1Offset;
for (const char *nameLabels : kName1MultiLabels)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name1Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName1));
@@ -769,11 +824,42 @@ void TestDnsCompressedName(void)
VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::ReadName() returned incorrect offset");
offset = name2Offset;
for (const char *nameLabel : kName2Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
for (const char *nameLabel : kName2Labels)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName2));
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
offset = name2Offset;
VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName2BadMultiLabels) == kErrorNotFound);
offset = name2Offset;
for (const char *nameLabels : kName2MultiLabels1)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
for (const char *nameLabels : kName2MultiLabels2)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName2));
@@ -826,11 +912,22 @@ void TestDnsCompressedName(void)
VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::ReadName() returned incorrect offset");
offset = name3Offset;
for (const char *nameLabel : kName3Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name3Offset;
for (const char *nameLabel : kName3Labels)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name3Offset;
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName3));
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name3Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName3));
@@ -880,11 +977,18 @@ void TestDnsCompressedName(void)
VerifyOrQuit(offset == name4Offset + kName4EncodedSize, "Name::ParseName() returned incorrect offset");
offset = name4Offset;
for (const char *nameLabel : kName4Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name4Offset;
for (const char *nameLabel : kName4Labels)
{
SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
}
SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name4Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");