xref: /aosp_15_r20/external/openthread/tests/unit/test_dns.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2020, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker #include <string.h>
30*cfb92d14SAndroid Build Coastguard Worker 
31*cfb92d14SAndroid Build Coastguard Worker #include <openthread/config.h>
32*cfb92d14SAndroid Build Coastguard Worker 
33*cfb92d14SAndroid Build Coastguard Worker #include "test_platform.h"
34*cfb92d14SAndroid Build Coastguard Worker #include "test_util.hpp"
35*cfb92d14SAndroid Build Coastguard Worker 
36*cfb92d14SAndroid Build Coastguard Worker #include "common/array.hpp"
37*cfb92d14SAndroid Build Coastguard Worker #include "instance/instance.hpp"
38*cfb92d14SAndroid Build Coastguard Worker #include "net/dns_types.hpp"
39*cfb92d14SAndroid Build Coastguard Worker 
40*cfb92d14SAndroid Build Coastguard Worker namespace ot {
41*cfb92d14SAndroid Build Coastguard Worker 
TestDnsName(void)42*cfb92d14SAndroid Build Coastguard Worker void TestDnsName(void)
43*cfb92d14SAndroid Build Coastguard Worker {
44*cfb92d14SAndroid Build Coastguard Worker     enum
45*cfb92d14SAndroid Build Coastguard Worker     {
46*cfb92d14SAndroid Build Coastguard Worker         kMaxSize       = 300,
47*cfb92d14SAndroid Build Coastguard Worker         kMaxNameLength = Dns::Name::kMaxNameSize - 1,
48*cfb92d14SAndroid Build Coastguard Worker     };
49*cfb92d14SAndroid Build Coastguard Worker 
50*cfb92d14SAndroid Build Coastguard Worker     struct TestName
51*cfb92d14SAndroid Build Coastguard Worker     {
52*cfb92d14SAndroid Build Coastguard Worker         const char    *mName;
53*cfb92d14SAndroid Build Coastguard Worker         uint16_t       mEncodedLength;
54*cfb92d14SAndroid Build Coastguard Worker         const uint8_t *mEncodedData;
55*cfb92d14SAndroid Build Coastguard Worker         const char   **mLabels;
56*cfb92d14SAndroid Build Coastguard Worker         const char    *mExpectedReadName;
57*cfb92d14SAndroid Build Coastguard Worker     };
58*cfb92d14SAndroid Build Coastguard Worker 
59*cfb92d14SAndroid Build Coastguard Worker     struct TestMatches
60*cfb92d14SAndroid Build Coastguard Worker     {
61*cfb92d14SAndroid Build Coastguard Worker         const char *mFullName;
62*cfb92d14SAndroid Build Coastguard Worker         const char *mFirstLabel;
63*cfb92d14SAndroid Build Coastguard Worker         const char *mLabels;
64*cfb92d14SAndroid Build Coastguard Worker         const char *mDomain;
65*cfb92d14SAndroid Build Coastguard Worker         bool        mShouldMatch;
66*cfb92d14SAndroid Build Coastguard Worker     };
67*cfb92d14SAndroid Build Coastguard Worker 
68*cfb92d14SAndroid Build Coastguard Worker     Instance              *instance;
69*cfb92d14SAndroid Build Coastguard Worker     MessagePool           *messagePool;
70*cfb92d14SAndroid Build Coastguard Worker     Message               *message;
71*cfb92d14SAndroid Build Coastguard Worker     uint8_t                buffer[kMaxSize];
72*cfb92d14SAndroid Build Coastguard Worker     uint16_t               len;
73*cfb92d14SAndroid Build Coastguard Worker     uint16_t               offset;
74*cfb92d14SAndroid Build Coastguard Worker     Dns::Name::LabelBuffer label;
75*cfb92d14SAndroid Build Coastguard Worker     uint8_t                labelLength;
76*cfb92d14SAndroid Build Coastguard Worker     Dns::Name::Buffer      name;
77*cfb92d14SAndroid Build Coastguard Worker     const char            *subDomain;
78*cfb92d14SAndroid Build Coastguard Worker     const char            *domain;
79*cfb92d14SAndroid Build Coastguard Worker     const char            *domain2;
80*cfb92d14SAndroid Build Coastguard Worker     const char            *fullName;
81*cfb92d14SAndroid Build Coastguard Worker     const char            *suffixName;
82*cfb92d14SAndroid Build Coastguard Worker     Dns::Name              dnsName;
83*cfb92d14SAndroid Build Coastguard Worker 
84*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kEncodedName1[] = {7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0};
85*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kEncodedName2[] = {3, 'f', 'o', 'o', 1, 'a', 2, 'b', 'b', 3, 'e', 'd', 'u', 0};
86*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kEncodedName3[] = {10, 'f', 'o', 'u', 'n', 'd', 'a', 't', 'i', 'o', 'n', 0};
87*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kEncodedName4[] = {0};
88*cfb92d14SAndroid Build Coastguard Worker 
89*cfb92d14SAndroid Build Coastguard Worker     static const char *kLabels1[] = {"example", "com", nullptr};
90*cfb92d14SAndroid Build Coastguard Worker     static const char *kLabels2[] = {"foo", "a", "bb", "edu", nullptr};
91*cfb92d14SAndroid Build Coastguard Worker     static const char *kLabels3[] = {"foundation", nullptr};
92*cfb92d14SAndroid Build Coastguard Worker     static const char *kLabels4[] = {nullptr};
93*cfb92d14SAndroid Build Coastguard Worker 
94*cfb92d14SAndroid Build Coastguard Worker     static const TestName kTestNames[] = {
95*cfb92d14SAndroid Build Coastguard Worker         {"example.com", sizeof(kEncodedName1), kEncodedName1, kLabels1, "example.com."},
96*cfb92d14SAndroid Build Coastguard Worker         {"example.com.", sizeof(kEncodedName1), kEncodedName1, kLabels1, "example.com."},
97*cfb92d14SAndroid Build Coastguard Worker         {"foo.a.bb.edu", sizeof(kEncodedName2), kEncodedName2, kLabels2, "foo.a.bb.edu."},
98*cfb92d14SAndroid Build Coastguard Worker         {"foo.a.bb.edu.", sizeof(kEncodedName2), kEncodedName2, kLabels2, "foo.a.bb.edu."},
99*cfb92d14SAndroid Build Coastguard Worker         {"foundation", sizeof(kEncodedName3), kEncodedName3, kLabels3, "foundation."},
100*cfb92d14SAndroid Build Coastguard Worker         {"foundation.", sizeof(kEncodedName3), kEncodedName3, kLabels3, "foundation."},
101*cfb92d14SAndroid Build Coastguard Worker         {"", sizeof(kEncodedName4), kEncodedName4, kLabels4, "."},
102*cfb92d14SAndroid Build Coastguard Worker         {".", sizeof(kEncodedName4), kEncodedName4, kLabels4, "."},
103*cfb92d14SAndroid Build Coastguard Worker         {nullptr, sizeof(kEncodedName4), kEncodedName4, kLabels4, "."},
104*cfb92d14SAndroid Build Coastguard Worker     };
105*cfb92d14SAndroid Build Coastguard Worker 
106*cfb92d14SAndroid Build Coastguard Worker     static const char *kMaxLengthNames[] = {
107*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
108*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
109*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
110*cfb92d14SAndroid Build Coastguard Worker         "SorcererAndMagicia.",
111*cfb92d14SAndroid Build Coastguard Worker 
112*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
113*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
114*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
115*cfb92d14SAndroid Build Coastguard Worker         "SorcererAndMagicia",
116*cfb92d14SAndroid Build Coastguard Worker     };
117*cfb92d14SAndroid Build Coastguard Worker 
118*cfb92d14SAndroid Build Coastguard Worker     static const char *kInvalidNames[] = {
119*cfb92d14SAndroid Build Coastguard Worker         "foo..bar",
120*cfb92d14SAndroid Build Coastguard Worker         "..",
121*cfb92d14SAndroid Build Coastguard Worker         "a..",
122*cfb92d14SAndroid Build Coastguard Worker         "..b",
123*cfb92d14SAndroid Build Coastguard Worker 
124*cfb92d14SAndroid Build Coastguard Worker         // Long label
125*cfb92d14SAndroid Build Coastguard Worker         "a.an-invalid-very-long-label-string-with-more-than-sixty-four-characters.com",
126*cfb92d14SAndroid Build Coastguard Worker 
127*cfb92d14SAndroid Build Coastguard Worker         // Long name (more than 255 characters)
128*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
129*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
130*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
131*cfb92d14SAndroid Build Coastguard Worker         "SorcererAndMagician.NoEyesCanEverSee.AnArtfulConjurer.MySenseFromMeTaken."
132*cfb92d14SAndroid Build Coastguard Worker         "MyEyesWillNeverSee.BeautiesOfTheWholeWorld.BeholdWhoseVisionFine.MySightFromMeTaken"
133*cfb92d14SAndroid Build Coastguard Worker         "PoemByRumiMolana",
134*cfb92d14SAndroid Build Coastguard Worker 
135*cfb92d14SAndroid Build Coastguard Worker         // Long name of 255 characters which ends with a dot
136*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
137*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
138*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
139*cfb92d14SAndroid Build Coastguard Worker         "SorcererAndMagician.",
140*cfb92d14SAndroid Build Coastguard Worker 
141*cfb92d14SAndroid Build Coastguard Worker         // Long name of 254 characters which does not end with a dot
142*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
143*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
144*cfb92d14SAndroid Build Coastguard Worker         "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
145*cfb92d14SAndroid Build Coastguard Worker         "SorcererAndMagician",
146*cfb92d14SAndroid Build Coastguard Worker 
147*cfb92d14SAndroid Build Coastguard Worker     };
148*cfb92d14SAndroid Build Coastguard Worker 
149*cfb92d14SAndroid Build Coastguard Worker     static const char kBadLabel[] = "badlabel";
150*cfb92d14SAndroid Build Coastguard Worker     static const char kBadName[]  = "bad.name";
151*cfb92d14SAndroid Build Coastguard Worker 
152*cfb92d14SAndroid Build Coastguard Worker     static const TestMatches kTestMatches[] = {
153*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "foo", "bar", "local.", true},
154*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", nullptr, "foo.bar", "local.", true},
155*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "foo", "ba", "local.", false},
156*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "fooooo", "bar", "local.", false},
157*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "foo", "bar", "locall.", false},
158*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "f", "bar", "local.", false},
159*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "foo", "barr", "local.", false},
160*cfb92d14SAndroid Build Coastguard Worker         {"foo.bar.local.", "foo", "bar", ".local.", false},
161*cfb92d14SAndroid Build Coastguard Worker         {"My Lovely Instance._mt._udp.local.", "mY lovely instancE", "_mt._udp", "local.", true},
162*cfb92d14SAndroid Build Coastguard Worker         {"My Lovely Instance._mt._udp.local.", nullptr, "mY lovely instancE._mt._udp", "local.", true},
163*cfb92d14SAndroid Build Coastguard Worker         {"_s1._sub._srv._udp.default.service.arpa.", "_s1", "_sub._srv._udp", "default.service.arpa.", true},
164*cfb92d14SAndroid Build Coastguard Worker     };
165*cfb92d14SAndroid Build Coastguard Worker 
166*cfb92d14SAndroid Build Coastguard Worker     printf("================================================================\n");
167*cfb92d14SAndroid Build Coastguard Worker     printf("TestDnsName()\n");
168*cfb92d14SAndroid Build Coastguard Worker 
169*cfb92d14SAndroid Build Coastguard Worker     instance = static_cast<Instance *>(testInitInstance());
170*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
171*cfb92d14SAndroid Build Coastguard Worker 
172*cfb92d14SAndroid Build Coastguard Worker     messagePool = &instance->Get<MessagePool>();
173*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
174*cfb92d14SAndroid Build Coastguard Worker 
175*cfb92d14SAndroid Build Coastguard Worker     message->SetOffset(0);
176*cfb92d14SAndroid Build Coastguard Worker 
177*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
178*cfb92d14SAndroid Build Coastguard Worker     printf("Verify domain name match:\n");
179*cfb92d14SAndroid Build Coastguard Worker 
180*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local.";
181*cfb92d14SAndroid Build Coastguard Worker     domain    = "local.";
182*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
183*cfb92d14SAndroid Build Coastguard Worker 
184*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local";
185*cfb92d14SAndroid Build Coastguard Worker     domain    = "local.";
186*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
187*cfb92d14SAndroid Build Coastguard Worker 
188*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local.";
189*cfb92d14SAndroid Build Coastguard Worker     domain    = "local";
190*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
191*cfb92d14SAndroid Build Coastguard Worker 
192*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local";
193*cfb92d14SAndroid Build Coastguard Worker     domain    = "local";
194*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
195*cfb92d14SAndroid Build Coastguard Worker 
196*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.default.service.arpa.";
197*cfb92d14SAndroid Build Coastguard Worker     domain    = "default.service.arpa.";
198*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
199*cfb92d14SAndroid Build Coastguard Worker 
200*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.default.service.arpa.";
201*cfb92d14SAndroid Build Coastguard Worker     domain    = "service.arpa.";
202*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
203*cfb92d14SAndroid Build Coastguard Worker 
204*cfb92d14SAndroid Build Coastguard Worker     // Verify it doesn't match a portion of a label.
205*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.default.service.arpa.";
206*cfb92d14SAndroid Build Coastguard Worker     domain    = "vice.arpa.";
207*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
208*cfb92d14SAndroid Build Coastguard Worker 
209*cfb92d14SAndroid Build Coastguard Worker     // Validate case does not matter
210*cfb92d14SAndroid Build Coastguard Worker 
211*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local.";
212*cfb92d14SAndroid Build Coastguard Worker     domain    = "LOCAL.";
213*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
214*cfb92d14SAndroid Build Coastguard Worker 
215*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local";
216*cfb92d14SAndroid Build Coastguard Worker     domain    = "LOCAL.";
217*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
218*cfb92d14SAndroid Build Coastguard Worker 
219*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local.";
220*cfb92d14SAndroid Build Coastguard Worker     domain    = "LOCAL";
221*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
222*cfb92d14SAndroid Build Coastguard Worker 
223*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.local";
224*cfb92d14SAndroid Build Coastguard Worker     domain    = "LOCAL";
225*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
226*cfb92d14SAndroid Build Coastguard Worker 
227*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.Default.Service.ARPA.";
228*cfb92d14SAndroid Build Coastguard Worker     domain    = "dEFAULT.Service.arpa.";
229*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
230*cfb92d14SAndroid Build Coastguard Worker 
231*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.default.service.ARpa.";
232*cfb92d14SAndroid Build Coastguard Worker     domain    = "SeRvIcE.arPA.";
233*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
234*cfb92d14SAndroid Build Coastguard Worker 
235*cfb92d14SAndroid Build Coastguard Worker     // Verify it doesn't match a portion of a label.
236*cfb92d14SAndroid Build Coastguard Worker     subDomain = "my-service._ipps._tcp.default.service.arpa.";
237*cfb92d14SAndroid Build Coastguard Worker     domain    = "Vice.arpa.";
238*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
239*cfb92d14SAndroid Build Coastguard Worker 
240*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
241*cfb92d14SAndroid Build Coastguard Worker     domain2 = "example.com.";
242*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
243*cfb92d14SAndroid Build Coastguard Worker 
244*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
245*cfb92d14SAndroid Build Coastguard Worker     domain2 = "example.com";
246*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
247*cfb92d14SAndroid Build Coastguard Worker 
248*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
249*cfb92d14SAndroid Build Coastguard Worker     domain2 = "ExAmPlE.cOm";
250*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
251*cfb92d14SAndroid Build Coastguard Worker 
252*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com";
253*cfb92d14SAndroid Build Coastguard Worker     domain2 = "ExAmPlE.cOm";
254*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
255*cfb92d14SAndroid Build Coastguard Worker 
256*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
257*cfb92d14SAndroid Build Coastguard Worker     domain2 = "ExAmPlE.cOm.";
258*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
259*cfb92d14SAndroid Build Coastguard Worker 
260*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
261*cfb92d14SAndroid Build Coastguard Worker     domain2 = "aExAmPlE.cOm.";
262*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
263*cfb92d14SAndroid Build Coastguard Worker 
264*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
265*cfb92d14SAndroid Build Coastguard Worker     domain2 = "cOm.";
266*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
267*cfb92d14SAndroid Build Coastguard Worker 
268*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.";
269*cfb92d14SAndroid Build Coastguard Worker     domain2 = "example.com.";
270*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
271*cfb92d14SAndroid Build Coastguard Worker 
272*cfb92d14SAndroid Build Coastguard Worker     domain  = "example.com.";
273*cfb92d14SAndroid Build Coastguard Worker     domain2 = ".example.com.";
274*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
275*cfb92d14SAndroid Build Coastguard Worker 
276*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
277*cfb92d14SAndroid Build Coastguard Worker     printf("Extracting label(s) and removing domains:\n");
278*cfb92d14SAndroid Build Coastguard Worker 
279*cfb92d14SAndroid Build Coastguard Worker     {
280*cfb92d14SAndroid Build Coastguard Worker         struct TestCase
281*cfb92d14SAndroid Build Coastguard Worker         {
282*cfb92d14SAndroid Build Coastguard Worker             const char *mFullName;
283*cfb92d14SAndroid Build Coastguard Worker             const char *mSuffixName;
284*cfb92d14SAndroid Build Coastguard Worker             const char *mLabels;
285*cfb92d14SAndroid Build Coastguard Worker         };
286*cfb92d14SAndroid Build Coastguard Worker 
287*cfb92d14SAndroid Build Coastguard Worker         static const TestCase kTestCases[] = {
288*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "default.service.arpa.", "my-service._ipps._tcp"},
289*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa", "default.service.arpa", "my-service._ipps._tcp"},
290*cfb92d14SAndroid Build Coastguard Worker             {"my.service._ipps._tcp.default.service.arpa.", "_ipps._tcp.default.service.arpa.", "my.service"},
291*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "DeFault.SerVice.ARPA.", "my-service._ipps._tcp"},
292*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa", "DeFault.SerVice.ARPA", "my-service._ipps._tcp"},
293*cfb92d14SAndroid Build Coastguard Worker 
294*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa", "default.service.arpa.", nullptr},
295*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "default.service.arpa", nullptr},
296*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "efault.service.arpa.", nullptr},
297*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa", "efault.service.arpa", nullptr},
298*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "xdefault.service.arpa.", nullptr},
299*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", ".default.service.arpa.", nullptr},
300*cfb92d14SAndroid Build Coastguard Worker             {"my-service._ipps._tcp.default.service.arpa.", "default.service.arp.", nullptr},
301*cfb92d14SAndroid Build Coastguard Worker             {"default.service.arpa.", "default.service.arpa.", nullptr},
302*cfb92d14SAndroid Build Coastguard Worker             {"default.service.arpa", "default.service.arpa", nullptr},
303*cfb92d14SAndroid Build Coastguard Worker             {"efault.service.arpa.", "default.service.arpa.", nullptr},
304*cfb92d14SAndroid Build Coastguard Worker         };
305*cfb92d14SAndroid Build Coastguard Worker 
306*cfb92d14SAndroid Build Coastguard Worker         for (const TestCase &testCase : kTestCases)
307*cfb92d14SAndroid Build Coastguard Worker         {
308*cfb92d14SAndroid Build Coastguard Worker             Error error;
309*cfb92d14SAndroid Build Coastguard Worker 
310*cfb92d14SAndroid Build Coastguard Worker             printf("\n");
311*cfb92d14SAndroid Build Coastguard Worker             printf("  FullName        : %s\n", testCase.mFullName);
312*cfb92d14SAndroid Build Coastguard Worker             printf("  SuffixName      : %s\n", testCase.mSuffixName);
313*cfb92d14SAndroid Build Coastguard Worker             printf("  Extracted labels: %s\n", (testCase.mLabels != nullptr) ? testCase.mLabels : "(parse)");
314*cfb92d14SAndroid Build Coastguard Worker 
315*cfb92d14SAndroid Build Coastguard Worker             error = Dns::Name::ExtractLabels(testCase.mFullName, testCase.mSuffixName, name);
316*cfb92d14SAndroid Build Coastguard Worker 
317*cfb92d14SAndroid Build Coastguard Worker             if (testCase.mLabels != nullptr)
318*cfb92d14SAndroid Build Coastguard Worker             {
319*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrQuit(error);
320*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(strcmp(name, testCase.mLabels) == 0);
321*cfb92d14SAndroid Build Coastguard Worker             }
322*cfb92d14SAndroid Build Coastguard Worker             else
323*cfb92d14SAndroid Build Coastguard Worker             {
324*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(error == kErrorParse);
325*cfb92d14SAndroid Build Coastguard Worker             }
326*cfb92d14SAndroid Build Coastguard Worker 
327*cfb92d14SAndroid Build Coastguard Worker             strcpy(name, testCase.mFullName);
328*cfb92d14SAndroid Build Coastguard Worker             error = Dns::Name::StripName(name, testCase.mSuffixName);
329*cfb92d14SAndroid Build Coastguard Worker 
330*cfb92d14SAndroid Build Coastguard Worker             if (testCase.mLabels != nullptr)
331*cfb92d14SAndroid Build Coastguard Worker             {
332*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrQuit(error);
333*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(strcmp(name, testCase.mLabels) == 0);
334*cfb92d14SAndroid Build Coastguard Worker             }
335*cfb92d14SAndroid Build Coastguard Worker             else
336*cfb92d14SAndroid Build Coastguard Worker             {
337*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(error == kErrorParse);
338*cfb92d14SAndroid Build Coastguard Worker             }
339*cfb92d14SAndroid Build Coastguard Worker         }
340*cfb92d14SAndroid Build Coastguard Worker 
341*cfb92d14SAndroid Build Coastguard Worker         fullName   = "my-service._ipps._tcp.default.service.arpa.";
342*cfb92d14SAndroid Build Coastguard Worker         suffixName = "default.service.arpa.";
343*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 22));
344*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
345*cfb92d14SAndroid Build Coastguard Worker 
346*cfb92d14SAndroid Build Coastguard Worker         fullName   = "my-service._ipps._tcp.default.service.arpa.";
347*cfb92d14SAndroid Build Coastguard Worker         suffixName = "default.service.arpa.";
348*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, 21) == kErrorNoBufs);
349*cfb92d14SAndroid Build Coastguard Worker     }
350*cfb92d14SAndroid Build Coastguard Worker 
351*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
352*cfb92d14SAndroid Build Coastguard Worker     printf("Append names, check encoded bytes, parse name and read labels:\n");
353*cfb92d14SAndroid Build Coastguard Worker 
354*cfb92d14SAndroid Build Coastguard Worker     for (const TestName &test : kTestNames)
355*cfb92d14SAndroid Build Coastguard Worker     {
356*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
357*cfb92d14SAndroid Build Coastguard Worker 
358*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendName(test.mName, *message));
359*cfb92d14SAndroid Build Coastguard Worker 
360*cfb92d14SAndroid Build Coastguard Worker         len = message->GetLength();
361*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Read(0, buffer, len));
362*cfb92d14SAndroid Build Coastguard Worker 
363*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer(test.mName, buffer, len);
364*cfb92d14SAndroid Build Coastguard Worker 
365*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(len == test.mEncodedLength, "Encoded length does not match expected value");
366*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(buffer, test.mEncodedData, len) == 0, "Encoded name data does not match expected data");
367*cfb92d14SAndroid Build Coastguard Worker 
368*cfb92d14SAndroid Build Coastguard Worker         // Parse and skip over the name
369*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
370*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ParseName(*message, offset));
371*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::ParseName() returned incorrect offset");
372*cfb92d14SAndroid Build Coastguard Worker 
373*cfb92d14SAndroid Build Coastguard Worker         // Read labels one by one.
374*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
375*cfb92d14SAndroid Build Coastguard Worker 
376*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t index = 0; test.mLabels[index] != nullptr; index++)
377*cfb92d14SAndroid Build Coastguard Worker         {
378*cfb92d14SAndroid Build Coastguard Worker             labelLength = sizeof(label);
379*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength));
380*cfb92d14SAndroid Build Coastguard Worker 
381*cfb92d14SAndroid Build Coastguard Worker             printf("Label[%d] = \"%s\"\n", index, label);
382*cfb92d14SAndroid Build Coastguard Worker 
383*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(strcmp(label, test.mLabels[index]) == 0, "Name::ReadLabel() did not get expected label");
384*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(labelLength == strlen(label), "Name::ReadLabel() returned incorrect label length");
385*cfb92d14SAndroid Build Coastguard Worker         }
386*cfb92d14SAndroid Build Coastguard Worker 
387*cfb92d14SAndroid Build Coastguard Worker         labelLength = sizeof(label);
388*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
389*cfb92d14SAndroid Build Coastguard Worker                      "Name::ReadLabel() failed at end of the name");
390*cfb92d14SAndroid Build Coastguard Worker 
391*cfb92d14SAndroid Build Coastguard Worker         // Read entire name
392*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
393*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
394*cfb92d14SAndroid Build Coastguard Worker 
395*cfb92d14SAndroid Build Coastguard Worker         printf("Read name =\"%s\"\n", name);
396*cfb92d14SAndroid Build Coastguard Worker 
397*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(name, test.mExpectedReadName) == 0, "Name::ReadName() did not get expected name");
398*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::ReadName() returned incorrect offset");
399*cfb92d14SAndroid Build Coastguard Worker 
400*cfb92d14SAndroid Build Coastguard Worker         // Read entire name with different name buffer sizes (just right and one byte off the expected size)
401*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
402*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(
403*cfb92d14SAndroid Build Coastguard Worker             Dns::Name::ReadName(*message, offset, name, static_cast<uint16_t>(strlen(test.mExpectedReadName) + 1)),
404*cfb92d14SAndroid Build Coastguard Worker             "Name::ReadName() failed with exact name buffer size");
405*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
406*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadName(*message, offset, name,
407*cfb92d14SAndroid Build Coastguard Worker                                          static_cast<uint16_t>(strlen(test.mExpectedReadName))) == kErrorNoBufs,
408*cfb92d14SAndroid Build Coastguard Worker                      "Name::ReadName() did not fail with too small name buffer size");
409*cfb92d14SAndroid Build Coastguard Worker 
410*cfb92d14SAndroid Build Coastguard Worker         // Compare labels one by one.
411*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
412*cfb92d14SAndroid Build Coastguard Worker 
413*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t index = 0; test.mLabels[index] != nullptr; index++)
414*cfb92d14SAndroid Build Coastguard Worker         {
415*cfb92d14SAndroid Build Coastguard Worker             uint16_t startOffset = offset;
416*cfb92d14SAndroid Build Coastguard Worker 
417*cfb92d14SAndroid Build Coastguard Worker             strcpy(label, test.mLabels[index]);
418*cfb92d14SAndroid Build Coastguard Worker 
419*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, label));
420*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(offset != startOffset, "Name::CompareLabel() did not change offset");
421*cfb92d14SAndroid Build Coastguard Worker 
422*cfb92d14SAndroid Build Coastguard Worker             offset = startOffset;
423*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(Dns::Name::CompareLabel(*message, offset, kBadLabel) == kErrorNotFound,
424*cfb92d14SAndroid Build Coastguard Worker                          "Name::CompareLabel() did not fail with incorrect label");
425*cfb92d14SAndroid Build Coastguard Worker 
426*cfb92d14SAndroid Build Coastguard Worker             StringConvertToUppercase(label);
427*cfb92d14SAndroid Build Coastguard Worker 
428*cfb92d14SAndroid Build Coastguard Worker             offset = startOffset;
429*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, label));
430*cfb92d14SAndroid Build Coastguard Worker         }
431*cfb92d14SAndroid Build Coastguard Worker 
432*cfb92d14SAndroid Build Coastguard Worker         // Compare the whole name.
433*cfb92d14SAndroid Build Coastguard Worker         strcpy(name, test.mExpectedReadName);
434*cfb92d14SAndroid Build Coastguard Worker 
435*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
436*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, name));
437*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
438*cfb92d14SAndroid Build Coastguard Worker 
439*cfb92d14SAndroid Build Coastguard Worker         StringConvertToUppercase(name);
440*cfb92d14SAndroid Build Coastguard Worker 
441*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
442*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, name));
443*cfb92d14SAndroid Build Coastguard Worker 
444*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
445*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
446*cfb92d14SAndroid Build Coastguard Worker                      "Name::CompareName() did not fail with incorrect name");
447*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
448*cfb92d14SAndroid Build Coastguard Worker 
449*cfb92d14SAndroid Build Coastguard Worker         // Remove the terminating '.' in expected name and verify
450*cfb92d14SAndroid Build Coastguard Worker         // that it can still be used by `CompareName()`.
451*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
452*cfb92d14SAndroid Build Coastguard Worker         strcpy(name, test.mExpectedReadName);
453*cfb92d14SAndroid Build Coastguard Worker         name[strlen(name) - 1] = '\0';
454*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, name));
455*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
456*cfb92d14SAndroid Build Coastguard Worker 
457*cfb92d14SAndroid Build Coastguard Worker         if (strlen(name) >= 1)
458*cfb92d14SAndroid Build Coastguard Worker         {
459*cfb92d14SAndroid Build Coastguard Worker             name[strlen(name) - 1] = '\0';
460*cfb92d14SAndroid Build Coastguard Worker             offset                 = 0;
461*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(Dns::Name::CompareName(*message, offset, name) == kErrorNotFound,
462*cfb92d14SAndroid Build Coastguard Worker                          "Name::CompareName() did not fail with invalid name");
463*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
464*cfb92d14SAndroid Build Coastguard Worker         }
465*cfb92d14SAndroid Build Coastguard Worker 
466*cfb92d14SAndroid Build Coastguard Worker         // Compare the name with itself read from message.
467*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
468*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset));
469*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
470*cfb92d14SAndroid Build Coastguard Worker     }
471*cfb92d14SAndroid Build Coastguard Worker 
472*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
473*cfb92d14SAndroid Build Coastguard Worker     printf("Max length names:\n");
474*cfb92d14SAndroid Build Coastguard Worker 
475*cfb92d14SAndroid Build Coastguard Worker     for (const char *&maxLengthName : kMaxLengthNames)
476*cfb92d14SAndroid Build Coastguard Worker     {
477*cfb92d14SAndroid Build Coastguard Worker         if (maxLengthName[strlen(maxLengthName) - 1] == '.')
478*cfb92d14SAndroid Build Coastguard Worker         {
479*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(strlen(maxLengthName) == kMaxNameLength);
480*cfb92d14SAndroid Build Coastguard Worker         }
481*cfb92d14SAndroid Build Coastguard Worker         else
482*cfb92d14SAndroid Build Coastguard Worker         {
483*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(strlen(maxLengthName) == kMaxNameLength - 1);
484*cfb92d14SAndroid Build Coastguard Worker         }
485*cfb92d14SAndroid Build Coastguard Worker 
486*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
487*cfb92d14SAndroid Build Coastguard Worker 
488*cfb92d14SAndroid Build Coastguard Worker         printf("\"%s\"\n", maxLengthName);
489*cfb92d14SAndroid Build Coastguard Worker 
490*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendName(maxLengthName, *message));
491*cfb92d14SAndroid Build Coastguard Worker     }
492*cfb92d14SAndroid Build Coastguard Worker 
493*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
494*cfb92d14SAndroid Build Coastguard Worker     printf("Invalid names:\n");
495*cfb92d14SAndroid Build Coastguard Worker 
496*cfb92d14SAndroid Build Coastguard Worker     for (const char *&invalidName : kInvalidNames)
497*cfb92d14SAndroid Build Coastguard Worker     {
498*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
499*cfb92d14SAndroid Build Coastguard Worker 
500*cfb92d14SAndroid Build Coastguard Worker         printf("\"%s\"\n", invalidName);
501*cfb92d14SAndroid Build Coastguard Worker 
502*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::AppendName(invalidName, *message) == kErrorInvalidArgs);
503*cfb92d14SAndroid Build Coastguard Worker     }
504*cfb92d14SAndroid Build Coastguard Worker 
505*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
506*cfb92d14SAndroid Build Coastguard Worker     printf("Append as multiple labels and terminator instead of full name:\n");
507*cfb92d14SAndroid Build Coastguard Worker 
508*cfb92d14SAndroid Build Coastguard Worker     for (const TestName &test : kTestNames)
509*cfb92d14SAndroid Build Coastguard Worker     {
510*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
511*cfb92d14SAndroid Build Coastguard Worker 
512*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendMultipleLabels(test.mName, *message));
513*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendTerminator(*message));
514*cfb92d14SAndroid Build Coastguard Worker 
515*cfb92d14SAndroid Build Coastguard Worker         len = message->GetLength();
516*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Read(0, buffer, len));
517*cfb92d14SAndroid Build Coastguard Worker 
518*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer(test.mName, buffer, len);
519*cfb92d14SAndroid Build Coastguard Worker 
520*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(len == test.mEncodedLength, "Encoded length does not match expected value");
521*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(buffer, test.mEncodedData, len) == 0, "Encoded name data does not match expected data");
522*cfb92d14SAndroid Build Coastguard Worker     }
523*cfb92d14SAndroid Build Coastguard Worker 
524*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
525*cfb92d14SAndroid Build Coastguard Worker     printf("Append labels one by one:\n");
526*cfb92d14SAndroid Build Coastguard Worker 
527*cfb92d14SAndroid Build Coastguard Worker     for (const TestName &test : kTestNames)
528*cfb92d14SAndroid Build Coastguard Worker     {
529*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
530*cfb92d14SAndroid Build Coastguard Worker 
531*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t index = 0; test.mLabels[index] != nullptr; index++)
532*cfb92d14SAndroid Build Coastguard Worker         {
533*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(Dns::Name::AppendLabel(test.mLabels[index], *message));
534*cfb92d14SAndroid Build Coastguard Worker         }
535*cfb92d14SAndroid Build Coastguard Worker 
536*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendTerminator(*message));
537*cfb92d14SAndroid Build Coastguard Worker 
538*cfb92d14SAndroid Build Coastguard Worker         len = message->GetLength();
539*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Read(0, buffer, len));
540*cfb92d14SAndroid Build Coastguard Worker 
541*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer(test.mName, buffer, len);
542*cfb92d14SAndroid Build Coastguard Worker 
543*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(len == test.mEncodedLength, "Encoded length does not match expected value");
544*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(buffer, test.mEncodedData, len) == 0, "Encoded name data does not match expected data");
545*cfb92d14SAndroid Build Coastguard Worker     }
546*cfb92d14SAndroid Build Coastguard Worker 
547*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
548*cfb92d14SAndroid Build Coastguard Worker     printf("Name::Matches() variations\n");
549*cfb92d14SAndroid Build Coastguard Worker 
550*cfb92d14SAndroid Build Coastguard Worker     for (const TestMatches &test : kTestMatches)
551*cfb92d14SAndroid Build Coastguard Worker     {
552*cfb92d14SAndroid Build Coastguard Worker         printf(" \"%s\"\n", test.mFullName);
553*cfb92d14SAndroid Build Coastguard Worker 
554*cfb92d14SAndroid Build Coastguard Worker         dnsName.Set(test.mFullName);
555*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
556*cfb92d14SAndroid Build Coastguard Worker 
557*cfb92d14SAndroid Build Coastguard Worker         IgnoreError(message->SetLength(0));
558*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(dnsName.AppendTo(*message));
559*cfb92d14SAndroid Build Coastguard Worker 
560*cfb92d14SAndroid Build Coastguard Worker         dnsName.SetFromMessage(*message, 0);
561*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
562*cfb92d14SAndroid Build Coastguard Worker     }
563*cfb92d14SAndroid Build Coastguard Worker 
564*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(message->SetLength(0));
565*cfb92d14SAndroid Build Coastguard Worker     dnsName.SetFromMessage(*message, 0);
566*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendLabel("Name.With.Dot", *message));
567*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendName("_srv._udp.local.", *message));
568*cfb92d14SAndroid Build Coastguard Worker 
569*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
570*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
571*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
572*cfb92d14SAndroid Build Coastguard Worker 
573*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name", "With.Dot._srv._udp", "local."));
574*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.", "With.Dot._srv._udp", "local."));
575*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With", "Dot._srv._udp", "local."));
576*cfb92d14SAndroid Build Coastguard Worker 
577*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
578*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
579*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
580*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
581*cfb92d14SAndroid Build Coastguard Worker 
582*cfb92d14SAndroid Build Coastguard Worker     offset = 0;
583*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
584*cfb92d14SAndroid Build Coastguard Worker     dnsName.Set(name);
585*cfb92d14SAndroid Build Coastguard Worker 
586*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
587*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
588*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
589*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
590*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
591*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
592*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
593*cfb92d14SAndroid Build Coastguard Worker 
594*cfb92d14SAndroid Build Coastguard Worker     message->Free();
595*cfb92d14SAndroid Build Coastguard Worker     testFreeInstance(instance);
596*cfb92d14SAndroid Build Coastguard Worker }
597*cfb92d14SAndroid Build Coastguard Worker 
TestDnsCompressedName(void)598*cfb92d14SAndroid Build Coastguard Worker void TestDnsCompressedName(void)
599*cfb92d14SAndroid Build Coastguard Worker {
600*cfb92d14SAndroid Build Coastguard Worker     enum
601*cfb92d14SAndroid Build Coastguard Worker     {
602*cfb92d14SAndroid Build Coastguard Worker         kHeaderOffset   = 10,
603*cfb92d14SAndroid Build Coastguard Worker         kGuardBlockSize = 20,
604*cfb92d14SAndroid Build Coastguard Worker         kMaxBufferSize  = 100,
605*cfb92d14SAndroid Build Coastguard Worker         kLabelSize      = 64,
606*cfb92d14SAndroid Build Coastguard Worker         kNameSize       = 256,
607*cfb92d14SAndroid Build Coastguard Worker 
608*cfb92d14SAndroid Build Coastguard Worker         kName2EncodedSize = 4 + 2,  // encoded "FOO" + pointer label (2 bytes)
609*cfb92d14SAndroid Build Coastguard Worker         kName3EncodedSize = 2,      // pointer label (2 bytes)
610*cfb92d14SAndroid Build Coastguard Worker         kName4EncodedSize = 15 + 2, // encoded "Human.Readable" + pointer label (2 bytes).
611*cfb92d14SAndroid Build Coastguard Worker 
612*cfb92d14SAndroid Build Coastguard Worker     };
613*cfb92d14SAndroid Build Coastguard Worker 
614*cfb92d14SAndroid Build Coastguard Worker     const char kName[]          = "F.ISI.ARPA";
615*cfb92d14SAndroid Build Coastguard Worker     const char kLabel1[]        = "FOO";
616*cfb92d14SAndroid Build Coastguard Worker     const char kInstanceLabel[] = "Human.Readable";
617*cfb92d14SAndroid Build Coastguard Worker 
618*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kEncodedName[]    = {1, 'F', 3, 'I', 'S', 'I', 4, 'A', 'R', 'P', 'A', 0};
619*cfb92d14SAndroid Build Coastguard Worker     static const uint8_t kIsiRelativeIndex = 2; // Index in kEncodedName to the start of "ISI.ARPA" portion.
620*cfb92d14SAndroid Build Coastguard Worker 
621*cfb92d14SAndroid Build Coastguard Worker     static const char *kName1Labels[] = {"F", "ISI", "ARPA"};
622*cfb92d14SAndroid Build Coastguard Worker     static const char *kName2Labels[] = {"FOO", "F", "ISI", "ARPA"};
623*cfb92d14SAndroid Build Coastguard Worker     static const char *kName3Labels[] = {"ISI", "ARPA"};
624*cfb92d14SAndroid Build Coastguard Worker     static const char *kName4Labels[] = {"Human.Readable", "F", "ISI", "ARPA"};
625*cfb92d14SAndroid Build Coastguard Worker 
626*cfb92d14SAndroid Build Coastguard Worker     static const char *kName1MultiLabels[]  = {"F.ISI", "ARPA"};
627*cfb92d14SAndroid Build Coastguard Worker     static const char *kName2MultiLabels1[] = {"FOO", "F.ISI.ARPA."};
628*cfb92d14SAndroid Build Coastguard Worker     static const char *kName2MultiLabels2[] = {"FOO.F.", "ISI.ARPA."};
629*cfb92d14SAndroid Build Coastguard Worker 
630*cfb92d14SAndroid Build Coastguard Worker     static const char kName1BadMultiLabels[] = "F.ISI.ARPA.MORE";
631*cfb92d14SAndroid Build Coastguard Worker     static const char kName2BadMultiLabels[] = "FOO.F.IS";
632*cfb92d14SAndroid Build Coastguard Worker 
633*cfb92d14SAndroid Build Coastguard Worker     static const char kExpectedReadName1[] = "F.ISI.ARPA.";
634*cfb92d14SAndroid Build Coastguard Worker     static const char kExpectedReadName2[] = "FOO.F.ISI.ARPA.";
635*cfb92d14SAndroid Build Coastguard Worker     static const char kExpectedReadName3[] = "ISI.ARPA.";
636*cfb92d14SAndroid Build Coastguard Worker     static const char kExpectedReadName4[] = "Human.Readable.F.ISI.ARPA.";
637*cfb92d14SAndroid Build Coastguard Worker 
638*cfb92d14SAndroid Build Coastguard Worker     static const char kBadName[] = "bad.name";
639*cfb92d14SAndroid Build Coastguard Worker 
640*cfb92d14SAndroid Build Coastguard Worker     Instance    *instance;
641*cfb92d14SAndroid Build Coastguard Worker     MessagePool *messagePool;
642*cfb92d14SAndroid Build Coastguard Worker     Message     *message;
643*cfb92d14SAndroid Build Coastguard Worker     Message     *message2;
644*cfb92d14SAndroid Build Coastguard Worker     uint16_t     offset;
645*cfb92d14SAndroid Build Coastguard Worker     uint16_t     name1Offset;
646*cfb92d14SAndroid Build Coastguard Worker     uint16_t     name2Offset;
647*cfb92d14SAndroid Build Coastguard Worker     uint16_t     name3Offset;
648*cfb92d14SAndroid Build Coastguard Worker     uint16_t     name4Offset;
649*cfb92d14SAndroid Build Coastguard Worker     uint8_t      buffer[kMaxBufferSize];
650*cfb92d14SAndroid Build Coastguard Worker     char         label[kLabelSize];
651*cfb92d14SAndroid Build Coastguard Worker     uint8_t      labelLength;
652*cfb92d14SAndroid Build Coastguard Worker     char         name[kNameSize];
653*cfb92d14SAndroid Build Coastguard Worker     Dns::Name    dnsName1;
654*cfb92d14SAndroid Build Coastguard Worker     Dns::Name    dnsName2;
655*cfb92d14SAndroid Build Coastguard Worker     Dns::Name    dnsName3;
656*cfb92d14SAndroid Build Coastguard Worker     Dns::Name    dnsName4;
657*cfb92d14SAndroid Build Coastguard Worker 
658*cfb92d14SAndroid Build Coastguard Worker     printf("================================================================\n");
659*cfb92d14SAndroid Build Coastguard Worker     printf("TestDnsCompressedName()\n");
660*cfb92d14SAndroid Build Coastguard Worker 
661*cfb92d14SAndroid Build Coastguard Worker     instance = static_cast<Instance *>(testInitInstance());
662*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
663*cfb92d14SAndroid Build Coastguard Worker 
664*cfb92d14SAndroid Build Coastguard Worker     messagePool = &instance->Get<MessagePool>();
665*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
666*cfb92d14SAndroid Build Coastguard Worker 
667*cfb92d14SAndroid Build Coastguard Worker     // Append name1 "F.ISI.ARPA"
668*cfb92d14SAndroid Build Coastguard Worker 
669*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < kHeaderOffset + kGuardBlockSize; index++)
670*cfb92d14SAndroid Build Coastguard Worker     {
671*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(index));
672*cfb92d14SAndroid Build Coastguard Worker     }
673*cfb92d14SAndroid Build Coastguard Worker 
674*cfb92d14SAndroid Build Coastguard Worker     message->SetOffset(kHeaderOffset);
675*cfb92d14SAndroid Build Coastguard Worker 
676*cfb92d14SAndroid Build Coastguard Worker     name1Offset = message->GetLength();
677*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendName(kName, *message));
678*cfb92d14SAndroid Build Coastguard Worker 
679*cfb92d14SAndroid Build Coastguard Worker     // Append name2 "FOO.F.ISI.ARPA" as a compressed name after some guard/extra bytes
680*cfb92d14SAndroid Build Coastguard Worker 
681*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < kGuardBlockSize; index++)
682*cfb92d14SAndroid Build Coastguard Worker     {
683*cfb92d14SAndroid Build Coastguard Worker         uint8_t value = 0xff;
684*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(value));
685*cfb92d14SAndroid Build Coastguard Worker     }
686*cfb92d14SAndroid Build Coastguard Worker 
687*cfb92d14SAndroid Build Coastguard Worker     name2Offset = message->GetLength();
688*cfb92d14SAndroid Build Coastguard Worker 
689*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendLabel(kLabel1, *message));
690*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendPointerLabel(name1Offset - kHeaderOffset, *message));
691*cfb92d14SAndroid Build Coastguard Worker 
692*cfb92d14SAndroid Build Coastguard Worker     // Append name3 "ISI.ARPA" as a compressed name after some guard/extra bytes
693*cfb92d14SAndroid Build Coastguard Worker 
694*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t index = 0; index < kGuardBlockSize; index++)
695*cfb92d14SAndroid Build Coastguard Worker     {
696*cfb92d14SAndroid Build Coastguard Worker         uint8_t value = 0xaa;
697*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(value));
698*cfb92d14SAndroid Build Coastguard Worker     }
699*cfb92d14SAndroid Build Coastguard Worker 
700*cfb92d14SAndroid Build Coastguard Worker     name3Offset = message->GetLength();
701*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendPointerLabel(name1Offset + kIsiRelativeIndex - kHeaderOffset, *message));
702*cfb92d14SAndroid Build Coastguard Worker 
703*cfb92d14SAndroid Build Coastguard Worker     name4Offset = message->GetLength();
704*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendLabel(kInstanceLabel, *message));
705*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendPointerLabel(name1Offset - kHeaderOffset, *message));
706*cfb92d14SAndroid Build Coastguard Worker 
707*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
708*cfb92d14SAndroid Build Coastguard Worker     printf("Read and parse the uncompressed name-1 \"F.ISI.ARPA\"\n");
709*cfb92d14SAndroid Build Coastguard Worker 
710*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(name1Offset, buffer, sizeof(kEncodedName)));
711*cfb92d14SAndroid Build Coastguard Worker 
712*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer(kName, buffer, sizeof(kEncodedName));
713*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(buffer, kEncodedName, sizeof(kEncodedName)) == 0,
714*cfb92d14SAndroid Build Coastguard Worker                  "Encoded name data does not match expected data");
715*cfb92d14SAndroid Build Coastguard Worker 
716*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
717*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ParseName(*message, offset));
718*cfb92d14SAndroid Build Coastguard Worker 
719*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::ParseName() returned incorrect offset");
720*cfb92d14SAndroid Build Coastguard Worker 
721*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
722*cfb92d14SAndroid Build Coastguard Worker 
723*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName1Labels)
724*cfb92d14SAndroid Build Coastguard Worker     {
725*cfb92d14SAndroid Build Coastguard Worker         labelLength = sizeof(label);
726*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength));
727*cfb92d14SAndroid Build Coastguard Worker 
728*cfb92d14SAndroid Build Coastguard Worker         printf("label: \"%s\"\n", label);
729*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
730*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(labelLength == strlen(label), "Name::ReadLabel() returned incorrect label length");
731*cfb92d14SAndroid Build Coastguard Worker     }
732*cfb92d14SAndroid Build Coastguard Worker 
733*cfb92d14SAndroid Build Coastguard Worker     labelLength = sizeof(label);
734*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
735*cfb92d14SAndroid Build Coastguard Worker                  "Name::ReadLabel() failed at end of the name");
736*cfb92d14SAndroid Build Coastguard Worker 
737*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
738*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
739*cfb92d14SAndroid Build Coastguard Worker     printf("Read name =\"%s\"\n", name);
740*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(strcmp(name, kExpectedReadName1) == 0, "Name::ReadName() did not return expected name");
741*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::ReadName() returned incorrect offset");
742*cfb92d14SAndroid Build Coastguard Worker 
743*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
744*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName1Labels)
745*cfb92d14SAndroid Build Coastguard Worker     {
746*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
747*cfb92d14SAndroid Build Coastguard Worker     }
748*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
749*cfb92d14SAndroid Build Coastguard Worker 
750*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
751*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName1Labels)
752*cfb92d14SAndroid Build Coastguard Worker     {
753*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
754*cfb92d14SAndroid Build Coastguard Worker     }
755*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
756*cfb92d14SAndroid Build Coastguard Worker 
757*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
758*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName1));
759*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
760*cfb92d14SAndroid Build Coastguard Worker 
761*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
762*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
763*cfb92d14SAndroid Build Coastguard Worker 
764*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
765*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName1BadMultiLabels) == kErrorNotFound);
766*cfb92d14SAndroid Build Coastguard Worker 
767*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
768*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabels : kName1MultiLabels)
769*cfb92d14SAndroid Build Coastguard Worker     {
770*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
771*cfb92d14SAndroid Build Coastguard Worker     }
772*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
773*cfb92d14SAndroid Build Coastguard Worker 
774*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
775*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName1));
776*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
777*cfb92d14SAndroid Build Coastguard Worker 
778*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
779*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
780*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with incorrect name");
781*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
782*cfb92d14SAndroid Build Coastguard Worker 
783*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
784*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset));
785*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
786*cfb92d14SAndroid Build Coastguard Worker 
787*cfb92d14SAndroid Build Coastguard Worker     offset = name1Offset;
788*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name2Offset) == kErrorNotFound,
789*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with mismatching name");
790*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
791*cfb92d14SAndroid Build Coastguard Worker 
792*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
793*cfb92d14SAndroid Build Coastguard Worker     printf("Read and parse compressed name-2 \"FOO.F.ISI.ARPA\"\n");
794*cfb92d14SAndroid Build Coastguard Worker 
795*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(name2Offset, buffer, kName2EncodedSize));
796*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("name2(compressed)", buffer, kName2EncodedSize);
797*cfb92d14SAndroid Build Coastguard Worker 
798*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
799*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ParseName(*message, offset));
800*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::ParseName() returned incorrect offset");
801*cfb92d14SAndroid Build Coastguard Worker 
802*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
803*cfb92d14SAndroid Build Coastguard Worker 
804*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName2Labels)
805*cfb92d14SAndroid Build Coastguard Worker     {
806*cfb92d14SAndroid Build Coastguard Worker         labelLength = sizeof(label);
807*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength));
808*cfb92d14SAndroid Build Coastguard Worker 
809*cfb92d14SAndroid Build Coastguard Worker         printf("label: \"%s\"\n", label);
810*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
811*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(labelLength == strlen(label), "Name::ReadLabel() returned incorrect label length");
812*cfb92d14SAndroid Build Coastguard Worker     }
813*cfb92d14SAndroid Build Coastguard Worker 
814*cfb92d14SAndroid Build Coastguard Worker     labelLength = sizeof(label);
815*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
816*cfb92d14SAndroid Build Coastguard Worker                  "Name::ReadLabel() failed at end of the name");
817*cfb92d14SAndroid Build Coastguard Worker 
818*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
819*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
820*cfb92d14SAndroid Build Coastguard Worker     printf("Read name =\"%s\"\n", name);
821*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(strcmp(name, kExpectedReadName2) == 0, "Name::ReadName() did not return expected name");
822*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::ReadName() returned incorrect offset");
823*cfb92d14SAndroid Build Coastguard Worker 
824*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
825*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName2Labels)
826*cfb92d14SAndroid Build Coastguard Worker     {
827*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
828*cfb92d14SAndroid Build Coastguard Worker     }
829*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
830*cfb92d14SAndroid Build Coastguard Worker 
831*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
832*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName2Labels)
833*cfb92d14SAndroid Build Coastguard Worker     {
834*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
835*cfb92d14SAndroid Build Coastguard Worker     }
836*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
837*cfb92d14SAndroid Build Coastguard Worker 
838*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
839*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName2));
840*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
841*cfb92d14SAndroid Build Coastguard Worker 
842*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
843*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
844*cfb92d14SAndroid Build Coastguard Worker 
845*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
846*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName2BadMultiLabels) == kErrorNotFound);
847*cfb92d14SAndroid Build Coastguard Worker 
848*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
849*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabels : kName2MultiLabels1)
850*cfb92d14SAndroid Build Coastguard Worker     {
851*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
852*cfb92d14SAndroid Build Coastguard Worker     }
853*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
854*cfb92d14SAndroid Build Coastguard Worker 
855*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
856*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabels : kName2MultiLabels2)
857*cfb92d14SAndroid Build Coastguard Worker     {
858*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
859*cfb92d14SAndroid Build Coastguard Worker     }
860*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
861*cfb92d14SAndroid Build Coastguard Worker 
862*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
863*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName2));
864*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
865*cfb92d14SAndroid Build Coastguard Worker 
866*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
867*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
868*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with incorrect name");
869*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
870*cfb92d14SAndroid Build Coastguard Worker 
871*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
872*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
873*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
874*cfb92d14SAndroid Build Coastguard Worker 
875*cfb92d14SAndroid Build Coastguard Worker     offset = name2Offset;
876*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name3Offset) == kErrorNotFound,
877*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with mismatching name");
878*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
879*cfb92d14SAndroid Build Coastguard Worker 
880*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
881*cfb92d14SAndroid Build Coastguard Worker     printf("Read and parse compressed name-3 \"ISI.ARPA\"\n");
882*cfb92d14SAndroid Build Coastguard Worker 
883*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(name3Offset, buffer, kName3EncodedSize));
884*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("name2(compressed)", buffer, kName3EncodedSize);
885*cfb92d14SAndroid Build Coastguard Worker 
886*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
887*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ParseName(*message, offset));
888*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::ParseName() returned incorrect offset");
889*cfb92d14SAndroid Build Coastguard Worker 
890*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
891*cfb92d14SAndroid Build Coastguard Worker 
892*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName3Labels)
893*cfb92d14SAndroid Build Coastguard Worker     {
894*cfb92d14SAndroid Build Coastguard Worker         labelLength = sizeof(label);
895*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength));
896*cfb92d14SAndroid Build Coastguard Worker 
897*cfb92d14SAndroid Build Coastguard Worker         printf("label: \"%s\"\n", label);
898*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
899*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(labelLength == strlen(label), "Name::ReadLabel() returned incorrect label length");
900*cfb92d14SAndroid Build Coastguard Worker     }
901*cfb92d14SAndroid Build Coastguard Worker 
902*cfb92d14SAndroid Build Coastguard Worker     labelLength = sizeof(label);
903*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
904*cfb92d14SAndroid Build Coastguard Worker                  "Name::ReadLabel() failed at end of the name");
905*cfb92d14SAndroid Build Coastguard Worker 
906*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
907*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
908*cfb92d14SAndroid Build Coastguard Worker     printf("Read name =\"%s\"\n", name);
909*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(strcmp(name, kExpectedReadName3) == 0, "Name::ReadName() did not return expected name");
910*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::ReadName() returned incorrect offset");
911*cfb92d14SAndroid Build Coastguard Worker 
912*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
913*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName3Labels)
914*cfb92d14SAndroid Build Coastguard Worker     {
915*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
916*cfb92d14SAndroid Build Coastguard Worker     }
917*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
918*cfb92d14SAndroid Build Coastguard Worker 
919*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
920*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName3Labels)
921*cfb92d14SAndroid Build Coastguard Worker     {
922*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
923*cfb92d14SAndroid Build Coastguard Worker     }
924*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
925*cfb92d14SAndroid Build Coastguard Worker 
926*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
927*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName3));
928*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
929*cfb92d14SAndroid Build Coastguard Worker 
930*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
931*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName3));
932*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
933*cfb92d14SAndroid Build Coastguard Worker 
934*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
935*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
936*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with incorrect name");
937*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
938*cfb92d14SAndroid Build Coastguard Worker 
939*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
940*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
941*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
942*cfb92d14SAndroid Build Coastguard Worker 
943*cfb92d14SAndroid Build Coastguard Worker     offset = name3Offset;
944*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name4Offset) == kErrorNotFound,
945*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with mismatching name");
946*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
947*cfb92d14SAndroid Build Coastguard Worker 
948*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
949*cfb92d14SAndroid Build Coastguard Worker     printf("Read and parse the uncompressed name-4 \"Human\\.Readable.F.ISI.ARPA\"\n");
950*cfb92d14SAndroid Build Coastguard Worker 
951*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(name4Offset, buffer, kName4EncodedSize));
952*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("name4(compressed)", buffer, kName4EncodedSize);
953*cfb92d14SAndroid Build Coastguard Worker 
954*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
955*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ParseName(*message, offset));
956*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name4Offset + kName4EncodedSize, "Name::ParseName() returned incorrect offset");
957*cfb92d14SAndroid Build Coastguard Worker 
958*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
959*cfb92d14SAndroid Build Coastguard Worker 
960*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName4Labels)
961*cfb92d14SAndroid Build Coastguard Worker     {
962*cfb92d14SAndroid Build Coastguard Worker         labelLength = sizeof(label);
963*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength));
964*cfb92d14SAndroid Build Coastguard Worker 
965*cfb92d14SAndroid Build Coastguard Worker         printf("label: \"%s\"\n", label);
966*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
967*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(labelLength == strlen(label), "Name::ReadLabel() returned incorrect label length");
968*cfb92d14SAndroid Build Coastguard Worker     }
969*cfb92d14SAndroid Build Coastguard Worker 
970*cfb92d14SAndroid Build Coastguard Worker     // `ReadName()` for name-4 should still succeed since only the first label contains dot char
971*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
972*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
973*cfb92d14SAndroid Build Coastguard Worker     printf("Read name =\"%s\"\n", name);
974*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(strcmp(name, kExpectedReadName4) == 0, "Name::ReadName() did not return expected name");
975*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == name4Offset + kName4EncodedSize, "Name::ParseName() returned incorrect offset");
976*cfb92d14SAndroid Build Coastguard Worker 
977*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
978*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName4Labels)
979*cfb92d14SAndroid Build Coastguard Worker     {
980*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
981*cfb92d14SAndroid Build Coastguard Worker     }
982*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
983*cfb92d14SAndroid Build Coastguard Worker 
984*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
985*cfb92d14SAndroid Build Coastguard Worker     for (const char *nameLabel : kName4Labels)
986*cfb92d14SAndroid Build Coastguard Worker     {
987*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
988*cfb92d14SAndroid Build Coastguard Worker     }
989*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
990*cfb92d14SAndroid Build Coastguard Worker 
991*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
992*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
993*cfb92d14SAndroid Build Coastguard Worker 
994*cfb92d14SAndroid Build Coastguard Worker     offset = name4Offset;
995*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name1Offset) == kErrorNotFound,
996*cfb92d14SAndroid Build Coastguard Worker                  "Name::CompareName() did not fail with mismatching name");
997*cfb92d14SAndroid Build Coastguard Worker 
998*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
999*cfb92d14SAndroid Build Coastguard Worker     printf("Append names from one message to another\n");
1000*cfb92d14SAndroid Build Coastguard Worker 
1001*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((message2 = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
1002*cfb92d14SAndroid Build Coastguard Worker 
1003*cfb92d14SAndroid Build Coastguard Worker     dnsName1.SetFromMessage(*message, name1Offset);
1004*cfb92d14SAndroid Build Coastguard Worker     dnsName2.SetFromMessage(*message, name2Offset);
1005*cfb92d14SAndroid Build Coastguard Worker     dnsName3.SetFromMessage(*message, name3Offset);
1006*cfb92d14SAndroid Build Coastguard Worker     dnsName4.SetFromMessage(*message, name4Offset);
1007*cfb92d14SAndroid Build Coastguard Worker 
1008*cfb92d14SAndroid Build Coastguard Worker     offset = 0;
1009*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(dnsName1.AppendTo(*message2));
1010*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(dnsName2.AppendTo(*message2));
1011*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(dnsName3.AppendTo(*message2));
1012*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(dnsName4.AppendTo(*message2));
1013*cfb92d14SAndroid Build Coastguard Worker 
1014*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message2->Read(0, buffer, message2->GetLength()));
1015*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("message2", buffer, message2->GetLength());
1016*cfb92d14SAndroid Build Coastguard Worker 
1017*cfb92d14SAndroid Build Coastguard Worker     // Now compare the names one by one in `message2`. Note that
1018*cfb92d14SAndroid Build Coastguard Worker     // `CompareName()` will update `offset` on success.
1019*cfb92d14SAndroid Build Coastguard Worker 
1020*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message2, offset, dnsName1));
1021*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message2, offset, dnsName2));
1022*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message2, offset, dnsName3));
1023*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message2, offset, dnsName4));
1024*cfb92d14SAndroid Build Coastguard Worker 
1025*cfb92d14SAndroid Build Coastguard Worker     offset = 0;
1026*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
1027*cfb92d14SAndroid Build Coastguard Worker     printf("- Name1 after `AppendTo()`: \"%s\"\n", name);
1028*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
1029*cfb92d14SAndroid Build Coastguard Worker     printf("- Name2 after `AppendTo()`: \"%s\"\n", name);
1030*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
1031*cfb92d14SAndroid Build Coastguard Worker     printf("- Name3 after `AppendTo()`: \"%s\"\n", name);
1032*cfb92d14SAndroid Build Coastguard Worker     // `ReadName()` for name-4 will fail due to first label containing dot char.
1033*cfb92d14SAndroid Build Coastguard Worker 
1034*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
1035*cfb92d14SAndroid Build Coastguard Worker     printf("Improperly formatted names (looped)\n");
1036*cfb92d14SAndroid Build Coastguard Worker 
1037*cfb92d14SAndroid Build Coastguard Worker     {
1038*cfb92d14SAndroid Build Coastguard Worker         // Pointer label jumps forward to offset 6.
1039*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kEncodedName[] = {3, 'F', 'O', 'O', 0xc0, 6, 2, 'A', 'B', 0};
1040*cfb92d14SAndroid Build Coastguard Worker 
1041*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->SetLength(0));
1042*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kEncodedName));
1043*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer("pointer-moving-forward", kEncodedName, sizeof(kEncodedName));
1044*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
1045*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ParseName(*message, offset) == kErrorParse);
1046*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadName(*message, offset, name) == kErrorParse);
1047*cfb92d14SAndroid Build Coastguard Worker     }
1048*cfb92d14SAndroid Build Coastguard Worker 
1049*cfb92d14SAndroid Build Coastguard Worker     {
1050*cfb92d14SAndroid Build Coastguard Worker         // Pointer label jumps back to offset 0 creating a loop.
1051*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kEncodedName[] = {0xc0, 0};
1052*cfb92d14SAndroid Build Coastguard Worker 
1053*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->SetLength(0));
1054*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kEncodedName));
1055*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer("looped-name", kEncodedName, sizeof(kEncodedName));
1056*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
1057*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ParseName(*message, offset) == kErrorParse);
1058*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadName(*message, offset, name) == kErrorParse);
1059*cfb92d14SAndroid Build Coastguard Worker     }
1060*cfb92d14SAndroid Build Coastguard Worker 
1061*cfb92d14SAndroid Build Coastguard Worker     {
1062*cfb92d14SAndroid Build Coastguard Worker         // After first label, we have a pointer label jumping back to
1063*cfb92d14SAndroid Build Coastguard Worker         // offset 0, creating a loop.
1064*cfb92d14SAndroid Build Coastguard Worker 
1065*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kEncodedName[] = {3, 'F', 'O', 'O', 0xc0, 0};
1066*cfb92d14SAndroid Build Coastguard Worker 
1067*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->SetLength(0));
1068*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kEncodedName));
1069*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer("looped-one-label", kEncodedName, sizeof(kEncodedName));
1070*cfb92d14SAndroid Build Coastguard Worker         offset = 0;
1071*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ParseName(*message, offset) == kErrorParse);
1072*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadName(*message, offset, name) == kErrorParse);
1073*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::CompareName(*message, offset, "FOO.") == kErrorParse);
1074*cfb92d14SAndroid Build Coastguard Worker     }
1075*cfb92d14SAndroid Build Coastguard Worker 
1076*cfb92d14SAndroid Build Coastguard Worker     {
1077*cfb92d14SAndroid Build Coastguard Worker         // After two labels we have a pointer label jumping back to
1078*cfb92d14SAndroid Build Coastguard Worker         // start of the first label. Name itself starts at offset 3
1079*cfb92d14SAndroid Build Coastguard Worker         // (first 3 bytes are unused).
1080*cfb92d14SAndroid Build Coastguard Worker 
1081*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kEncodedName[] = {0, 0, 0, 3, 'F', 'O', 'O', 2, 'B', 'A', 0xc0, 3};
1082*cfb92d14SAndroid Build Coastguard Worker 
1083*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->SetLength(0));
1084*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kEncodedName));
1085*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer("looped-two-labels", kEncodedName, sizeof(kEncodedName));
1086*cfb92d14SAndroid Build Coastguard Worker         offset = 3;
1087*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ParseName(*message, offset) == kErrorParse);
1088*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::ReadName(*message, offset, name) == kErrorParse);
1089*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::Name::CompareName(*message, offset, "FOO.BA.") == kErrorParse);
1090*cfb92d14SAndroid Build Coastguard Worker     }
1091*cfb92d14SAndroid Build Coastguard Worker 
1092*cfb92d14SAndroid Build Coastguard Worker     {
1093*cfb92d14SAndroid Build Coastguard Worker         // Same as last case, but pointer label now points to
1094*cfb92d14SAndroid Build Coastguard Worker         // immediately before the first label (at offset 2). The name
1095*cfb92d14SAndroid Build Coastguard Worker         // is now valid.
1096*cfb92d14SAndroid Build Coastguard Worker 
1097*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kEncodedName[] = {0, 0, 0, 3, 'F', 'O', 'O', 2, 'B', 'A', 0xc0, 2};
1098*cfb92d14SAndroid Build Coastguard Worker 
1099*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->SetLength(0));
1100*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kEncodedName));
1101*cfb92d14SAndroid Build Coastguard Worker         DumpBuffer("valid-name", kEncodedName, sizeof(kEncodedName));
1102*cfb92d14SAndroid Build Coastguard Worker         offset = 3;
1103*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ParseName(*message, offset));
1104*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == sizeof(kEncodedName));
1105*cfb92d14SAndroid Build Coastguard Worker 
1106*cfb92d14SAndroid Build Coastguard Worker         offset = 3;
1107*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
1108*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == sizeof(kEncodedName));
1109*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(name, "FOO.BA.") == 0);
1110*cfb92d14SAndroid Build Coastguard Worker         printf("Read name =\"%s\"\n", name);
1111*cfb92d14SAndroid Build Coastguard Worker     }
1112*cfb92d14SAndroid Build Coastguard Worker 
1113*cfb92d14SAndroid Build Coastguard Worker     message->Free();
1114*cfb92d14SAndroid Build Coastguard Worker     message2->Free();
1115*cfb92d14SAndroid Build Coastguard Worker     testFreeInstance(instance);
1116*cfb92d14SAndroid Build Coastguard Worker }
1117*cfb92d14SAndroid Build Coastguard Worker 
TestHeaderAndResourceRecords(void)1118*cfb92d14SAndroid Build Coastguard Worker void TestHeaderAndResourceRecords(void)
1119*cfb92d14SAndroid Build Coastguard Worker {
1120*cfb92d14SAndroid Build Coastguard Worker     enum
1121*cfb92d14SAndroid Build Coastguard Worker     {
1122*cfb92d14SAndroid Build Coastguard Worker         kHeaderOffset    = 0,
1123*cfb92d14SAndroid Build Coastguard Worker         kQuestionCount   = 1,
1124*cfb92d14SAndroid Build Coastguard Worker         kAnswerCount     = 2,
1125*cfb92d14SAndroid Build Coastguard Worker         kAdditionalCount = 5,
1126*cfb92d14SAndroid Build Coastguard Worker         kTtl             = 7200,
1127*cfb92d14SAndroid Build Coastguard Worker         kTxtTtl          = 7300,
1128*cfb92d14SAndroid Build Coastguard Worker         kSrvPort         = 1234,
1129*cfb92d14SAndroid Build Coastguard Worker         kSrvPriority     = 1,
1130*cfb92d14SAndroid Build Coastguard Worker         kSrvWeight       = 2,
1131*cfb92d14SAndroid Build Coastguard Worker         kMaxSize         = 600,
1132*cfb92d14SAndroid Build Coastguard Worker     };
1133*cfb92d14SAndroid Build Coastguard Worker 
1134*cfb92d14SAndroid Build Coastguard Worker     const char    kMessageString[]  = "DnsMessage";
1135*cfb92d14SAndroid Build Coastguard Worker     const char    kDomainName[]     = "example.com.";
1136*cfb92d14SAndroid Build Coastguard Worker     const char    kServiceLabels[]  = "_service._udp";
1137*cfb92d14SAndroid Build Coastguard Worker     const char    kServiceName[]    = "_service._udp.example.com.";
1138*cfb92d14SAndroid Build Coastguard Worker     const char    kInstance1Label[] = "inst1";
1139*cfb92d14SAndroid Build Coastguard Worker     const char    kInstance2Label[] = "instance.2"; // Instance label includes dot '.' character.
1140*cfb92d14SAndroid Build Coastguard Worker     const char    kInstance1Name[]  = "inst1._service._udp.example.com.";
1141*cfb92d14SAndroid Build Coastguard Worker     const char    kInstance2Name[]  = "instance.2._service._udp.example.com.";
1142*cfb92d14SAndroid Build Coastguard Worker     const char    kHostName[]       = "host.example.com.";
1143*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kTxtData[]        = {9, 'k', 'e', 'y', '=', 'v', 'a', 'l', 'u', 'e', 0};
1144*cfb92d14SAndroid Build Coastguard Worker     const char    kHostAddress[]    = "fd00::abcd:";
1145*cfb92d14SAndroid Build Coastguard Worker 
1146*cfb92d14SAndroid Build Coastguard Worker     const char *kInstanceLabels[] = {kInstance1Label, kInstance2Label};
1147*cfb92d14SAndroid Build Coastguard Worker     const char *kInstanceNames[]  = {kInstance1Name, kInstance2Name};
1148*cfb92d14SAndroid Build Coastguard Worker 
1149*cfb92d14SAndroid Build Coastguard Worker     Instance           *instance;
1150*cfb92d14SAndroid Build Coastguard Worker     MessagePool        *messagePool;
1151*cfb92d14SAndroid Build Coastguard Worker     Message            *message;
1152*cfb92d14SAndroid Build Coastguard Worker     Dns::Header         header;
1153*cfb92d14SAndroid Build Coastguard Worker     uint16_t            messageId;
1154*cfb92d14SAndroid Build Coastguard Worker     uint16_t            headerOffset;
1155*cfb92d14SAndroid Build Coastguard Worker     uint16_t            offset;
1156*cfb92d14SAndroid Build Coastguard Worker     uint16_t            numRecords;
1157*cfb92d14SAndroid Build Coastguard Worker     uint16_t            len;
1158*cfb92d14SAndroid Build Coastguard Worker     uint16_t            serviceNameOffset;
1159*cfb92d14SAndroid Build Coastguard Worker     uint16_t            hostNameOffset;
1160*cfb92d14SAndroid Build Coastguard Worker     uint16_t            answerSectionOffset;
1161*cfb92d14SAndroid Build Coastguard Worker     uint16_t            additionalSectionOffset;
1162*cfb92d14SAndroid Build Coastguard Worker     uint16_t            index;
1163*cfb92d14SAndroid Build Coastguard Worker     Dns::PtrRecord      ptrRecord;
1164*cfb92d14SAndroid Build Coastguard Worker     Dns::SrvRecord      srvRecord;
1165*cfb92d14SAndroid Build Coastguard Worker     Dns::TxtRecord      txtRecord;
1166*cfb92d14SAndroid Build Coastguard Worker     Dns::AaaaRecord     aaaaRecord;
1167*cfb92d14SAndroid Build Coastguard Worker     Dns::ResourceRecord record;
1168*cfb92d14SAndroid Build Coastguard Worker     Ip6::Address        hostAddress;
1169*cfb92d14SAndroid Build Coastguard Worker 
1170*cfb92d14SAndroid Build Coastguard Worker     Dns::Name::LabelBuffer label;
1171*cfb92d14SAndroid Build Coastguard Worker     Dns::Name::Buffer      name;
1172*cfb92d14SAndroid Build Coastguard Worker     uint8_t                buffer[kMaxSize];
1173*cfb92d14SAndroid Build Coastguard Worker 
1174*cfb92d14SAndroid Build Coastguard Worker     printf("================================================================\n");
1175*cfb92d14SAndroid Build Coastguard Worker     printf("TestHeaderAndResourceRecords()\n");
1176*cfb92d14SAndroid Build Coastguard Worker 
1177*cfb92d14SAndroid Build Coastguard Worker     instance = static_cast<Instance *>(testInitInstance());
1178*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
1179*cfb92d14SAndroid Build Coastguard Worker 
1180*cfb92d14SAndroid Build Coastguard Worker     messagePool = &instance->Get<MessagePool>();
1181*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
1182*cfb92d14SAndroid Build Coastguard Worker 
1183*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
1184*cfb92d14SAndroid Build Coastguard Worker     printf("Preparing the message\n");
1185*cfb92d14SAndroid Build Coastguard Worker 
1186*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Append(kMessageString));
1187*cfb92d14SAndroid Build Coastguard Worker 
1188*cfb92d14SAndroid Build Coastguard Worker     // Header
1189*cfb92d14SAndroid Build Coastguard Worker 
1190*cfb92d14SAndroid Build Coastguard Worker     headerOffset = message->GetLength();
1191*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(header.SetRandomMessageId());
1192*cfb92d14SAndroid Build Coastguard Worker     messageId = header.GetMessageId();
1193*cfb92d14SAndroid Build Coastguard Worker     header.SetType(Dns::Header::kTypeResponse);
1194*cfb92d14SAndroid Build Coastguard Worker     header.SetQuestionCount(kQuestionCount);
1195*cfb92d14SAndroid Build Coastguard Worker     header.SetAnswerCount(kAnswerCount);
1196*cfb92d14SAndroid Build Coastguard Worker     header.SetAdditionalRecordCount(kAdditionalCount);
1197*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Append(header));
1198*cfb92d14SAndroid Build Coastguard Worker     message->SetOffset(headerOffset);
1199*cfb92d14SAndroid Build Coastguard Worker 
1200*cfb92d14SAndroid Build Coastguard Worker     // Question section
1201*cfb92d14SAndroid Build Coastguard Worker 
1202*cfb92d14SAndroid Build Coastguard Worker     serviceNameOffset = message->GetLength() - headerOffset;
1203*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendMultipleLabels(kServiceLabels, *message));
1204*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendName(kDomainName, *message));
1205*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Append(Dns::Question(Dns::ResourceRecord::kTypePtr)));
1206*cfb92d14SAndroid Build Coastguard Worker 
1207*cfb92d14SAndroid Build Coastguard Worker     // Answer section
1208*cfb92d14SAndroid Build Coastguard Worker 
1209*cfb92d14SAndroid Build Coastguard Worker     answerSectionOffset = message->GetLength();
1210*cfb92d14SAndroid Build Coastguard Worker 
1211*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceLabel : kInstanceLabels)
1212*cfb92d14SAndroid Build Coastguard Worker     {
1213*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendPointerLabel(serviceNameOffset, *message));
1214*cfb92d14SAndroid Build Coastguard Worker         ptrRecord.Init();
1215*cfb92d14SAndroid Build Coastguard Worker         ptrRecord.SetTtl(kTtl);
1216*cfb92d14SAndroid Build Coastguard Worker         offset = message->GetLength();
1217*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(ptrRecord));
1218*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendLabel(instanceLabel, *message));
1219*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendPointerLabel(serviceNameOffset, *message));
1220*cfb92d14SAndroid Build Coastguard Worker         ptrRecord.SetLength(message->GetLength() - offset - sizeof(Dns::ResourceRecord));
1221*cfb92d14SAndroid Build Coastguard Worker         message->Write(offset, ptrRecord);
1222*cfb92d14SAndroid Build Coastguard Worker     }
1223*cfb92d14SAndroid Build Coastguard Worker 
1224*cfb92d14SAndroid Build Coastguard Worker     // Additional section
1225*cfb92d14SAndroid Build Coastguard Worker 
1226*cfb92d14SAndroid Build Coastguard Worker     additionalSectionOffset = message->GetLength();
1227*cfb92d14SAndroid Build Coastguard Worker 
1228*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceName : kInstanceNames)
1229*cfb92d14SAndroid Build Coastguard Worker     {
1230*cfb92d14SAndroid Build Coastguard Worker         uint16_t instanceNameOffset = message->GetLength() - headerOffset;
1231*cfb92d14SAndroid Build Coastguard Worker 
1232*cfb92d14SAndroid Build Coastguard Worker         // SRV record
1233*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendName(instanceName, *message));
1234*cfb92d14SAndroid Build Coastguard Worker         srvRecord.Init();
1235*cfb92d14SAndroid Build Coastguard Worker         srvRecord.SetTtl(kTtl);
1236*cfb92d14SAndroid Build Coastguard Worker         srvRecord.SetPort(kSrvPort);
1237*cfb92d14SAndroid Build Coastguard Worker         srvRecord.SetWeight(kSrvWeight);
1238*cfb92d14SAndroid Build Coastguard Worker         srvRecord.SetPriority(kSrvPriority);
1239*cfb92d14SAndroid Build Coastguard Worker         offset = message->GetLength();
1240*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(srvRecord));
1241*cfb92d14SAndroid Build Coastguard Worker         hostNameOffset = message->GetLength() - headerOffset;
1242*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendName(kHostName, *message));
1243*cfb92d14SAndroid Build Coastguard Worker         srvRecord.SetLength(message->GetLength() - offset - sizeof(Dns::ResourceRecord));
1244*cfb92d14SAndroid Build Coastguard Worker         message->Write(offset, srvRecord);
1245*cfb92d14SAndroid Build Coastguard Worker 
1246*cfb92d14SAndroid Build Coastguard Worker         // TXT record
1247*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::AppendPointerLabel(instanceNameOffset, *message));
1248*cfb92d14SAndroid Build Coastguard Worker         txtRecord.Init();
1249*cfb92d14SAndroid Build Coastguard Worker         txtRecord.SetTtl(kTxtTtl);
1250*cfb92d14SAndroid Build Coastguard Worker         txtRecord.SetLength(sizeof(kTxtData));
1251*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(txtRecord));
1252*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(message->Append(kTxtData));
1253*cfb92d14SAndroid Build Coastguard Worker     }
1254*cfb92d14SAndroid Build Coastguard Worker 
1255*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(hostAddress.FromString(kHostAddress));
1256*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::AppendPointerLabel(hostNameOffset, *message));
1257*cfb92d14SAndroid Build Coastguard Worker     aaaaRecord.Init();
1258*cfb92d14SAndroid Build Coastguard Worker     aaaaRecord.SetTtl(kTtl);
1259*cfb92d14SAndroid Build Coastguard Worker     aaaaRecord.SetAddress(hostAddress);
1260*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Append(aaaaRecord));
1261*cfb92d14SAndroid Build Coastguard Worker 
1262*cfb92d14SAndroid Build Coastguard Worker     // Dump the entire message
1263*cfb92d14SAndroid Build Coastguard Worker 
1264*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->GetLength() < kMaxSize, "Message is too long");
1265*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(0, buffer, message->GetLength()));
1266*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("message", buffer, message->GetLength());
1267*cfb92d14SAndroid Build Coastguard Worker 
1268*cfb92d14SAndroid Build Coastguard Worker     printf("----------------------------------------------------------------\n");
1269*cfb92d14SAndroid Build Coastguard Worker     printf("Parse and verify the message\n");
1270*cfb92d14SAndroid Build Coastguard Worker 
1271*cfb92d14SAndroid Build Coastguard Worker     offset = 0;
1272*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->Compare(offset, kMessageString), "Message header does not match");
1273*cfb92d14SAndroid Build Coastguard Worker     offset += sizeof(kMessageString);
1274*cfb92d14SAndroid Build Coastguard Worker 
1275*cfb92d14SAndroid Build Coastguard Worker     // Header
1276*cfb92d14SAndroid Build Coastguard Worker 
1277*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == headerOffset, "headerOffset is incorrect");
1278*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(offset, header));
1279*cfb92d14SAndroid Build Coastguard Worker     offset += sizeof(header);
1280*cfb92d14SAndroid Build Coastguard Worker 
1281*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(header.GetMessageId() == messageId);
1282*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(header.GetType() == Dns::Header::kTypeResponse);
1283*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(header.GetQuestionCount() == kQuestionCount);
1284*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(header.GetAnswerCount() == kAnswerCount);
1285*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(header.GetAdditionalRecordCount() == kAdditionalCount);
1286*cfb92d14SAndroid Build Coastguard Worker 
1287*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
1288*cfb92d14SAndroid Build Coastguard Worker     printf("Question Section\n");
1289*cfb92d14SAndroid Build Coastguard Worker 
1290*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, kServiceName), "Question name does not match");
1291*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->Compare(offset, Dns::Question(Dns::ResourceRecord::kTypePtr)));
1292*cfb92d14SAndroid Build Coastguard Worker     offset += sizeof(Dns::Question);
1293*cfb92d14SAndroid Build Coastguard Worker 
1294*cfb92d14SAndroid Build Coastguard Worker     printf("PTR for \"%s\"\n", kServiceName);
1295*cfb92d14SAndroid Build Coastguard Worker 
1296*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
1297*cfb92d14SAndroid Build Coastguard Worker     printf("Answer Section\n");
1298*cfb92d14SAndroid Build Coastguard Worker 
1299*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == answerSectionOffset, "answer section offset is incorrect");
1300*cfb92d14SAndroid Build Coastguard Worker 
1301*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceLabel : kInstanceLabels)
1302*cfb92d14SAndroid Build Coastguard Worker     {
1303*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, kServiceName));
1304*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord));
1305*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
1306*cfb92d14SAndroid Build Coastguard Worker 
1307*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, name));
1308*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(label, instanceLabel) == 0, "Inst label is incorrect");
1309*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(name, kServiceName) == 0);
1310*cfb92d14SAndroid Build Coastguard Worker 
1311*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" PTR %u %d \"%s.%s\"\n", kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength(), label,
1312*cfb92d14SAndroid Build Coastguard Worker                name);
1313*cfb92d14SAndroid Build Coastguard Worker     }
1314*cfb92d14SAndroid Build Coastguard Worker 
1315*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
1316*cfb92d14SAndroid Build Coastguard Worker 
1317*cfb92d14SAndroid Build Coastguard Worker     offset = answerSectionOffset;
1318*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::ResourceRecord::ParseRecords(*message, offset, kAnswerCount));
1319*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
1320*cfb92d14SAndroid Build Coastguard Worker 
1321*cfb92d14SAndroid Build Coastguard Worker     printf("Use FindRecord() to find and iterate through all the records:\n");
1322*cfb92d14SAndroid Build Coastguard Worker 
1323*cfb92d14SAndroid Build Coastguard Worker     offset     = answerSectionOffset;
1324*cfb92d14SAndroid Build Coastguard Worker     numRecords = kAnswerCount;
1325*cfb92d14SAndroid Build Coastguard Worker 
1326*cfb92d14SAndroid Build Coastguard Worker     while (numRecords > 0)
1327*cfb92d14SAndroid Build Coastguard Worker     {
1328*cfb92d14SAndroid Build Coastguard Worker         uint16_t prevNumRecords = numRecords;
1329*cfb92d14SAndroid Build Coastguard Worker 
1330*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)));
1331*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(numRecords == prevNumRecords - 1, "Incorrect num records");
1332*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord));
1333*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
1334*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, name));
1335*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" PTR %u %d inst:\"%s\" at \"%s\"\n", kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength(),
1336*cfb92d14SAndroid Build Coastguard Worker                label, name);
1337*cfb92d14SAndroid Build Coastguard Worker     }
1338*cfb92d14SAndroid Build Coastguard Worker 
1339*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
1340*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)) ==
1341*cfb92d14SAndroid Build Coastguard Worker                      kErrorNotFound,
1342*cfb92d14SAndroid Build Coastguard Worker                  "FindRecord did not fail with no records");
1343*cfb92d14SAndroid Build Coastguard Worker 
1344*cfb92d14SAndroid Build Coastguard Worker     // Use `ReadRecord()` with a non-matching record type. Verify that it correct skips over the record.
1345*cfb92d14SAndroid Build Coastguard Worker 
1346*cfb92d14SAndroid Build Coastguard Worker     offset     = answerSectionOffset;
1347*cfb92d14SAndroid Build Coastguard Worker     numRecords = kAnswerCount;
1348*cfb92d14SAndroid Build Coastguard Worker 
1349*cfb92d14SAndroid Build Coastguard Worker     while (numRecords > 0)
1350*cfb92d14SAndroid Build Coastguard Worker     {
1351*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)));
1352*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord) == kErrorNotFound,
1353*cfb92d14SAndroid Build Coastguard Worker                      "ReadRecord() did not fail with non-matching type");
1354*cfb92d14SAndroid Build Coastguard Worker     }
1355*cfb92d14SAndroid Build Coastguard Worker 
1356*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
1357*cfb92d14SAndroid Build Coastguard Worker 
1358*cfb92d14SAndroid Build Coastguard Worker     // Use `FindRecord` with a non-matching name. Verify that it correctly skips over all records.
1359*cfb92d14SAndroid Build Coastguard Worker 
1360*cfb92d14SAndroid Build Coastguard Worker     offset     = answerSectionOffset;
1361*cfb92d14SAndroid Build Coastguard Worker     numRecords = kAnswerCount;
1362*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kInstance1Name)) ==
1363*cfb92d14SAndroid Build Coastguard Worker                      kErrorNotFound,
1364*cfb92d14SAndroid Build Coastguard Worker                  "FindRecord did not fail with non-matching name");
1365*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(numRecords == 0, "Incorrect num records");
1366*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
1367*cfb92d14SAndroid Build Coastguard Worker 
1368*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
1369*cfb92d14SAndroid Build Coastguard Worker     printf("Additional Section\n");
1370*cfb92d14SAndroid Build Coastguard Worker 
1371*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceName : kInstanceNames)
1372*cfb92d14SAndroid Build Coastguard Worker     {
1373*cfb92d14SAndroid Build Coastguard Worker         uint16_t savedOffset;
1374*cfb92d14SAndroid Build Coastguard Worker 
1375*cfb92d14SAndroid Build Coastguard Worker         // SRV record
1376*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, instanceName));
1377*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord));
1378*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(srvRecord.GetTtl() == kTtl);
1379*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(srvRecord.GetPort() == kSrvPort);
1380*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(srvRecord.GetWeight() == kSrvWeight);
1381*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(srvRecord.GetPriority() == kSrvPriority);
1382*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(srvRecord.ReadTargetHostName(*message, offset, name));
1383*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(name, kHostName) == 0);
1384*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" SRV %u %d %d %d %d \"%s\"\n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
1385*cfb92d14SAndroid Build Coastguard Worker                srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority(), name);
1386*cfb92d14SAndroid Build Coastguard Worker 
1387*cfb92d14SAndroid Build Coastguard Worker         // TXT record
1388*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::CompareName(*message, offset, instanceName));
1389*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, txtRecord));
1390*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(txtRecord.GetTtl() == kTxtTtl);
1391*cfb92d14SAndroid Build Coastguard Worker         savedOffset = offset;
1392*cfb92d14SAndroid Build Coastguard Worker         len         = sizeof(buffer);
1393*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(txtRecord.ReadTxtData(*message, offset, buffer, len));
1394*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(len == sizeof(kTxtData));
1395*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(buffer, kTxtData, len) == 0);
1396*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" TXT %u %d \"%s\"\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength(),
1397*cfb92d14SAndroid Build Coastguard Worker                reinterpret_cast<const char *>(buffer));
1398*cfb92d14SAndroid Build Coastguard Worker 
1399*cfb92d14SAndroid Build Coastguard Worker         // Partial read of TXT data
1400*cfb92d14SAndroid Build Coastguard Worker         len = sizeof(kTxtData) - 1;
1401*cfb92d14SAndroid Build Coastguard Worker         memset(buffer, 0, sizeof(buffer));
1402*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(txtRecord.ReadTxtData(*message, savedOffset, buffer, len) == kErrorNoBufs);
1403*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(len == sizeof(kTxtData) - 1);
1404*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(buffer, kTxtData, len) == 0);
1405*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(savedOffset == offset);
1406*cfb92d14SAndroid Build Coastguard Worker     }
1407*cfb92d14SAndroid Build Coastguard Worker 
1408*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::Name::CompareName(*message, offset, kHostName));
1409*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, aaaaRecord));
1410*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(aaaaRecord.GetTtl() == kTtl);
1411*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(aaaaRecord.GetAddress() == hostAddress);
1412*cfb92d14SAndroid Build Coastguard Worker     printf("    \"%s\" AAAA %u %d \"%s\"\n", kHostName, aaaaRecord.GetTtl(), aaaaRecord.GetLength(),
1413*cfb92d14SAndroid Build Coastguard Worker            aaaaRecord.GetAddress().ToString().AsCString());
1414*cfb92d14SAndroid Build Coastguard Worker 
1415*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
1416*cfb92d14SAndroid Build Coastguard Worker 
1417*cfb92d14SAndroid Build Coastguard Worker     // Use `ParseRecords()` to parse all records
1418*cfb92d14SAndroid Build Coastguard Worker     offset = additionalSectionOffset;
1419*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::ResourceRecord::ParseRecords(*message, offset, kAdditionalCount));
1420*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
1421*cfb92d14SAndroid Build Coastguard Worker 
1422*cfb92d14SAndroid Build Coastguard Worker     printf("Use FindRecord() to search for specific name:\n");
1423*cfb92d14SAndroid Build Coastguard Worker 
1424*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceName : kInstanceNames)
1425*cfb92d14SAndroid Build Coastguard Worker     {
1426*cfb92d14SAndroid Build Coastguard Worker         offset     = additionalSectionOffset;
1427*cfb92d14SAndroid Build Coastguard Worker         numRecords = kAdditionalCount;
1428*cfb92d14SAndroid Build Coastguard Worker 
1429*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)));
1430*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord));
1431*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::Name::ParseName(*message, offset));
1432*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" SRV %u %d %d %d %d\n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
1433*cfb92d14SAndroid Build Coastguard Worker                srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority());
1434*cfb92d14SAndroid Build Coastguard Worker 
1435*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)));
1436*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, txtRecord));
1437*cfb92d14SAndroid Build Coastguard Worker         offset += txtRecord.GetLength();
1438*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" TXT %u %d\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength());
1439*cfb92d14SAndroid Build Coastguard Worker 
1440*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)) ==
1441*cfb92d14SAndroid Build Coastguard Worker                          kErrorNotFound,
1442*cfb92d14SAndroid Build Coastguard Worker                      "FindRecord() did not fail with no more records");
1443*cfb92d14SAndroid Build Coastguard Worker 
1444*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
1445*cfb92d14SAndroid Build Coastguard Worker     }
1446*cfb92d14SAndroid Build Coastguard Worker 
1447*cfb92d14SAndroid Build Coastguard Worker     offset     = additionalSectionOffset;
1448*cfb92d14SAndroid Build Coastguard Worker     numRecords = kAdditionalCount;
1449*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kHostName)));
1450*cfb92d14SAndroid Build Coastguard Worker 
1451*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, record));
1452*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(record.GetType() == Dns::ResourceRecord::kTypeAaaa);
1453*cfb92d14SAndroid Build Coastguard Worker     offset += record.GetLength();
1454*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
1455*cfb92d14SAndroid Build Coastguard Worker 
1456*cfb92d14SAndroid Build Coastguard Worker     printf("Use FindRecord() to search for specific records:\n");
1457*cfb92d14SAndroid Build Coastguard Worker     printf(" Answer Section\n");
1458*cfb92d14SAndroid Build Coastguard Worker 
1459*cfb92d14SAndroid Build Coastguard Worker     for (index = 0; index < GetArrayLength(kInstanceNames); index++)
1460*cfb92d14SAndroid Build Coastguard Worker     {
1461*cfb92d14SAndroid Build Coastguard Worker         offset = answerSectionOffset;
1462*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(
1463*cfb92d14SAndroid Build Coastguard Worker             Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName), ptrRecord));
1464*cfb92d14SAndroid Build Coastguard Worker 
1465*cfb92d14SAndroid Build Coastguard Worker         printf("   index:%d -> \"%s\" PTR %u %d\n", index, kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength());
1466*cfb92d14SAndroid Build Coastguard Worker     }
1467*cfb92d14SAndroid Build Coastguard Worker 
1468*cfb92d14SAndroid Build Coastguard Worker     // Check `FindRecord()` failure with non-matching name, record type, or bad index.
1469*cfb92d14SAndroid Build Coastguard Worker 
1470*cfb92d14SAndroid Build Coastguard Worker     offset = answerSectionOffset;
1471*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName),
1472*cfb92d14SAndroid Build Coastguard Worker                                                  ptrRecord) == kErrorNotFound,
1473*cfb92d14SAndroid Build Coastguard Worker                  "FindRecord() did not fail with bad index");
1474*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
1475*cfb92d14SAndroid Build Coastguard Worker 
1476*cfb92d14SAndroid Build Coastguard Worker     offset = answerSectionOffset;
1477*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kInstance1Name),
1478*cfb92d14SAndroid Build Coastguard Worker                                                  ptrRecord) == kErrorNotFound,
1479*cfb92d14SAndroid Build Coastguard Worker                  "FindRecord() did not fail with bad index");
1480*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
1481*cfb92d14SAndroid Build Coastguard Worker 
1482*cfb92d14SAndroid Build Coastguard Worker     offset = answerSectionOffset;
1483*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName),
1484*cfb92d14SAndroid Build Coastguard Worker                                                  txtRecord) == kErrorNotFound,
1485*cfb92d14SAndroid Build Coastguard Worker                  "FindRecord() did not fail with bad index");
1486*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
1487*cfb92d14SAndroid Build Coastguard Worker 
1488*cfb92d14SAndroid Build Coastguard Worker     printf(" Additional Section\n");
1489*cfb92d14SAndroid Build Coastguard Worker 
1490*cfb92d14SAndroid Build Coastguard Worker     for (const char *instanceName : kInstanceNames)
1491*cfb92d14SAndroid Build Coastguard Worker     {
1492*cfb92d14SAndroid Build Coastguard Worker         // There is a single SRV and TXT entry for each instance
1493*cfb92d14SAndroid Build Coastguard Worker         offset = additionalSectionOffset;
1494*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 0,
1495*cfb92d14SAndroid Build Coastguard Worker                                                       Dns::Name(instanceName), srvRecord));
1496*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" SRV %u %d %d %d %d \n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
1497*cfb92d14SAndroid Build Coastguard Worker                srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority());
1498*cfb92d14SAndroid Build Coastguard Worker 
1499*cfb92d14SAndroid Build Coastguard Worker         offset = additionalSectionOffset;
1500*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 0,
1501*cfb92d14SAndroid Build Coastguard Worker                                                       Dns::Name(instanceName), txtRecord));
1502*cfb92d14SAndroid Build Coastguard Worker         printf("    \"%s\" TXT %u %d\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength());
1503*cfb92d14SAndroid Build Coastguard Worker 
1504*cfb92d14SAndroid Build Coastguard Worker         offset = additionalSectionOffset;
1505*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 1,
1506*cfb92d14SAndroid Build Coastguard Worker                                                      Dns::Name(instanceName), srvRecord) == kErrorNotFound);
1507*cfb92d14SAndroid Build Coastguard Worker 
1508*cfb92d14SAndroid Build Coastguard Worker         offset = additionalSectionOffset;
1509*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 1,
1510*cfb92d14SAndroid Build Coastguard Worker                                                      Dns::Name(instanceName), txtRecord) == kErrorNotFound);
1511*cfb92d14SAndroid Build Coastguard Worker     }
1512*cfb92d14SAndroid Build Coastguard Worker 
1513*cfb92d14SAndroid Build Coastguard Worker     for (index = 0; index < kAdditionalCount; index++)
1514*cfb92d14SAndroid Build Coastguard Worker     {
1515*cfb92d14SAndroid Build Coastguard Worker         offset = additionalSectionOffset;
1516*cfb92d14SAndroid Build Coastguard Worker         // Find record with empty name (matching any) and any type.
1517*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, index, Dns::Name(), record));
1518*cfb92d14SAndroid Build Coastguard Worker     }
1519*cfb92d14SAndroid Build Coastguard Worker 
1520*cfb92d14SAndroid Build Coastguard Worker     offset = additionalSectionOffset;
1521*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, index, Dns::Name(), record) ==
1522*cfb92d14SAndroid Build Coastguard Worker                  kErrorNotFound);
1523*cfb92d14SAndroid Build Coastguard Worker 
1524*cfb92d14SAndroid Build Coastguard Worker     message->Free();
1525*cfb92d14SAndroid Build Coastguard Worker     testFreeInstance(instance);
1526*cfb92d14SAndroid Build Coastguard Worker }
1527*cfb92d14SAndroid Build Coastguard Worker 
TestDnsTxtEntry(void)1528*cfb92d14SAndroid Build Coastguard Worker void TestDnsTxtEntry(void)
1529*cfb92d14SAndroid Build Coastguard Worker {
1530*cfb92d14SAndroid Build Coastguard Worker     enum
1531*cfb92d14SAndroid Build Coastguard Worker     {
1532*cfb92d14SAndroid Build Coastguard Worker         kMaxTxtDataSize = 255,
1533*cfb92d14SAndroid Build Coastguard Worker     };
1534*cfb92d14SAndroid Build Coastguard Worker 
1535*cfb92d14SAndroid Build Coastguard Worker     struct EncodedTxtData
1536*cfb92d14SAndroid Build Coastguard Worker     {
1537*cfb92d14SAndroid Build Coastguard Worker         const uint8_t *mData;
1538*cfb92d14SAndroid Build Coastguard Worker         uint8_t        mLength;
1539*cfb92d14SAndroid Build Coastguard Worker     };
1540*cfb92d14SAndroid Build Coastguard Worker 
1541*cfb92d14SAndroid Build Coastguard Worker     const char    kKey1[]   = "key";
1542*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue1[] = {'v', 'a', 'l', 'u', 'e'};
1543*cfb92d14SAndroid Build Coastguard Worker 
1544*cfb92d14SAndroid Build Coastguard Worker     const char    kKey2[]   = "E";
1545*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue2[] = {'m', 'c', '^', '2'};
1546*cfb92d14SAndroid Build Coastguard Worker 
1547*cfb92d14SAndroid Build Coastguard Worker     const char    kKey3[]   = "space key";
1548*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue3[] = {'=', 0, '='};
1549*cfb92d14SAndroid Build Coastguard Worker 
1550*cfb92d14SAndroid Build Coastguard Worker     const char    kKey4[]   = "123456789"; // Max recommended length key
1551*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue4[] = {0};
1552*cfb92d14SAndroid Build Coastguard Worker 
1553*cfb92d14SAndroid Build Coastguard Worker     const char    kKey5[]   = "1234567890"; // Longer than recommended key
1554*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue5[] = {'a'};
1555*cfb92d14SAndroid Build Coastguard Worker 
1556*cfb92d14SAndroid Build Coastguard Worker     const char kKey6[] = "boolKey";  // Should be encoded as "boolKey" (without `=`).
1557*cfb92d14SAndroid Build Coastguard Worker     const char kKey7[] = "emptyKey"; // Should be encoded as "emptyKey=".
1558*cfb92d14SAndroid Build Coastguard Worker 
1559*cfb92d14SAndroid Build Coastguard Worker     const char    kKey8[]   = "1234567890123456789012345678901234567890123456789012345678901234567890";
1560*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kValue8[] = "abcd";
1561*cfb92d14SAndroid Build Coastguard Worker 
1562*cfb92d14SAndroid Build Coastguard Worker     // Invalid key
1563*cfb92d14SAndroid Build Coastguard Worker     const char kShortKey[] = "";
1564*cfb92d14SAndroid Build Coastguard Worker 
1565*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt1[] = {9, 'k', 'e', 'y', '=', 'v', 'a', 'l', 'u', 'e'};
1566*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt2[] = {6, 'E', '=', 'm', 'c', '^', '2'};
1567*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt3[] = {13, 's', 'p', 'a', 'c', 'e', ' ', 'k', 'e', 'y', '=', '=', 0, '='};
1568*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt4[] = {11, '1', '2', '3', '4', '5', '6', '7', '8', '9', '=', 0};
1569*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt5[] = {12, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '=', 'a'};
1570*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt6[] = {7, 'b', 'o', 'o', 'l', 'K', 'e', 'y'};
1571*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt7[] = {9, 'e', 'm', 'p', 't', 'y', 'K', 'e', 'y', '='};
1572*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kEncodedTxt8[] = {
1573*cfb92d14SAndroid Build Coastguard Worker         75,                                               // length
1574*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 10
1575*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 20
1576*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30
1577*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 40
1578*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 50
1579*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 60
1580*cfb92d14SAndroid Build Coastguard Worker         '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 70
1581*cfb92d14SAndroid Build Coastguard Worker         '=', 'a', 'b', 'c', 'd',
1582*cfb92d14SAndroid Build Coastguard Worker     };
1583*cfb92d14SAndroid Build Coastguard Worker 
1584*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kInvalidEncodedTxt1[] = {4, 'a', '=', 'b'}; // Incorrect length
1585*cfb92d14SAndroid Build Coastguard Worker 
1586*cfb92d14SAndroid Build Coastguard Worker     // Special encoded txt data with zero strings and string starting
1587*cfb92d14SAndroid Build Coastguard Worker     // with '=' (missing key) which should be skipped over silently.
1588*cfb92d14SAndroid Build Coastguard Worker     const uint8_t kSpecialEncodedTxt[] = {0, 0, 3, 'A', '=', 'B', 2, '=', 'C', 3, 'D', '=', 'E', 3, '=', '1', '2'};
1589*cfb92d14SAndroid Build Coastguard Worker 
1590*cfb92d14SAndroid Build Coastguard Worker     const Dns::TxtEntry kTxtEntries[] = {
1591*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey1, kValue1, sizeof(kValue1)),
1592*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey2, kValue2, sizeof(kValue2)),
1593*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey3, kValue3, sizeof(kValue3)),
1594*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey4, kValue4, sizeof(kValue4)),
1595*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey5, kValue5, sizeof(kValue5)),
1596*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey6, nullptr, 0),
1597*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey7, kValue1, 0),
1598*cfb92d14SAndroid Build Coastguard Worker         Dns::TxtEntry(kKey8, kValue8, sizeof(kValue8)),
1599*cfb92d14SAndroid Build Coastguard Worker     };
1600*cfb92d14SAndroid Build Coastguard Worker 
1601*cfb92d14SAndroid Build Coastguard Worker     const EncodedTxtData kEncodedTxtData[] = {
1602*cfb92d14SAndroid Build Coastguard Worker         {kEncodedTxt1, sizeof(kEncodedTxt1)}, {kEncodedTxt2, sizeof(kEncodedTxt2)},
1603*cfb92d14SAndroid Build Coastguard Worker         {kEncodedTxt3, sizeof(kEncodedTxt3)}, {kEncodedTxt4, sizeof(kEncodedTxt4)},
1604*cfb92d14SAndroid Build Coastguard Worker         {kEncodedTxt5, sizeof(kEncodedTxt5)}, {kEncodedTxt6, sizeof(kEncodedTxt6)},
1605*cfb92d14SAndroid Build Coastguard Worker         {kEncodedTxt7, sizeof(kEncodedTxt7)}};
1606*cfb92d14SAndroid Build Coastguard Worker 
1607*cfb92d14SAndroid Build Coastguard Worker     Instance                      *instance;
1608*cfb92d14SAndroid Build Coastguard Worker     MessagePool                   *messagePool;
1609*cfb92d14SAndroid Build Coastguard Worker     Message                       *message;
1610*cfb92d14SAndroid Build Coastguard Worker     uint8_t                        txtData[kMaxTxtDataSize];
1611*cfb92d14SAndroid Build Coastguard Worker     uint16_t                       txtDataLength;
1612*cfb92d14SAndroid Build Coastguard Worker     uint8_t                        index;
1613*cfb92d14SAndroid Build Coastguard Worker     Dns::TxtEntry                  txtEntry;
1614*cfb92d14SAndroid Build Coastguard Worker     Dns::TxtEntry::Iterator        iterator;
1615*cfb92d14SAndroid Build Coastguard Worker     MutableData<kWithUint16Length> data;
1616*cfb92d14SAndroid Build Coastguard Worker 
1617*cfb92d14SAndroid Build Coastguard Worker     printf("================================================================\n");
1618*cfb92d14SAndroid Build Coastguard Worker     printf("TestDnsTxtEntry()\n");
1619*cfb92d14SAndroid Build Coastguard Worker 
1620*cfb92d14SAndroid Build Coastguard Worker     instance = static_cast<Instance *>(testInitInstance());
1621*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(instance != nullptr);
1622*cfb92d14SAndroid Build Coastguard Worker 
1623*cfb92d14SAndroid Build Coastguard Worker     messagePool = &instance->Get<MessagePool>();
1624*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
1625*cfb92d14SAndroid Build Coastguard Worker 
1626*cfb92d14SAndroid Build Coastguard Worker     data.Init(txtData, sizeof(txtData));
1627*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, GetArrayLength(kTxtEntries), data));
1628*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(data.GetBytes() == txtData);
1629*cfb92d14SAndroid Build Coastguard Worker     txtDataLength = data.GetLength();
1630*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtDataLength < kMaxTxtDataSize, "TXT data is too long");
1631*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("txt data", txtData, txtDataLength);
1632*cfb92d14SAndroid Build Coastguard Worker 
1633*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, GetArrayLength(kTxtEntries), *message));
1634*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtDataLength == message->GetLength());
1635*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
1636*cfb92d14SAndroid Build Coastguard Worker 
1637*cfb92d14SAndroid Build Coastguard Worker     index = 0;
1638*cfb92d14SAndroid Build Coastguard Worker     for (const EncodedTxtData &encodedData : kEncodedTxtData)
1639*cfb92d14SAndroid Build Coastguard Worker     {
1640*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(&txtData[index], encodedData.mData, encodedData.mLength) == 0);
1641*cfb92d14SAndroid Build Coastguard Worker         index += encodedData.mLength;
1642*cfb92d14SAndroid Build Coastguard Worker     }
1643*cfb92d14SAndroid Build Coastguard Worker 
1644*cfb92d14SAndroid Build Coastguard Worker     iterator.Init(txtData, txtDataLength);
1645*cfb92d14SAndroid Build Coastguard Worker 
1646*cfb92d14SAndroid Build Coastguard Worker     for (const Dns::TxtEntry &expectedTxtEntry : kTxtEntries)
1647*cfb92d14SAndroid Build Coastguard Worker     {
1648*cfb92d14SAndroid Build Coastguard Worker         uint8_t expectedKeyLength = static_cast<uint8_t>(strlen(expectedTxtEntry.mKey));
1649*cfb92d14SAndroid Build Coastguard Worker 
1650*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(iterator.GetNextEntry(txtEntry), "TxtEntry::GetNextEntry() failed");
1651*cfb92d14SAndroid Build Coastguard Worker         printf("key:\"%s\" valueLen:%d\n", txtEntry.mKey != nullptr ? txtEntry.mKey : "(null)", txtEntry.mValueLength);
1652*cfb92d14SAndroid Build Coastguard Worker 
1653*cfb92d14SAndroid Build Coastguard Worker         if (expectedKeyLength > Dns::TxtEntry::kMaxIterKeyLength)
1654*cfb92d14SAndroid Build Coastguard Worker         {
1655*cfb92d14SAndroid Build Coastguard Worker             // When the key is longer than recommended max key length,
1656*cfb92d14SAndroid Build Coastguard Worker             // the full encoded string is returned in `mValue` and
1657*cfb92d14SAndroid Build Coastguard Worker             // `mValueLength` and `mKey` should be set to  `nullptr`.
1658*cfb92d14SAndroid Build Coastguard Worker 
1659*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(txtEntry.mKey == nullptr, "TxtEntry key does not match expected value for long key");
1660*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(txtEntry.mValueLength == expectedKeyLength + expectedTxtEntry.mValueLength + sizeof(char),
1661*cfb92d14SAndroid Build Coastguard Worker                          "TxtEntry value length is incorrect for long key");
1662*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(memcmp(txtEntry.mValue, expectedTxtEntry.mKey, expectedKeyLength) == 0);
1663*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(txtEntry.mValue[expectedKeyLength] == static_cast<uint8_t>('='));
1664*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(memcmp(&txtEntry.mValue[expectedKeyLength + sizeof(uint8_t)], expectedTxtEntry.mValue,
1665*cfb92d14SAndroid Build Coastguard Worker                                 expectedTxtEntry.mValueLength) == 0);
1666*cfb92d14SAndroid Build Coastguard Worker             continue;
1667*cfb92d14SAndroid Build Coastguard Worker         }
1668*cfb92d14SAndroid Build Coastguard Worker 
1669*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(strcmp(txtEntry.mKey, expectedTxtEntry.mKey) == 0);
1670*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(txtEntry.mValueLength == expectedTxtEntry.mValueLength);
1671*cfb92d14SAndroid Build Coastguard Worker 
1672*cfb92d14SAndroid Build Coastguard Worker         if (txtEntry.mValueLength != 0)
1673*cfb92d14SAndroid Build Coastguard Worker         {
1674*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(memcmp(txtEntry.mValue, expectedTxtEntry.mValue, txtEntry.mValueLength) == 0);
1675*cfb92d14SAndroid Build Coastguard Worker         }
1676*cfb92d14SAndroid Build Coastguard Worker         else
1677*cfb92d14SAndroid Build Coastguard Worker         {
1678*cfb92d14SAndroid Build Coastguard Worker             // Ensure both `txtEntry.mKey` and `expectedTxtEntry.mKey` are
1679*cfb92d14SAndroid Build Coastguard Worker             // null or both are non-null (for boolean or empty keys).
1680*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit((txtEntry.mKey == nullptr) == (expectedTxtEntry.mKey == nullptr),
1681*cfb92d14SAndroid Build Coastguard Worker                          "TxtEntry value does not match expected value for bool or empty key");
1682*cfb92d14SAndroid Build Coastguard Worker         }
1683*cfb92d14SAndroid Build Coastguard Worker     }
1684*cfb92d14SAndroid Build Coastguard Worker 
1685*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() returned unexpected entry");
1686*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() succeeded after done");
1687*cfb92d14SAndroid Build Coastguard Worker 
1688*cfb92d14SAndroid Build Coastguard Worker     // Verify `AppendEntries()` correctly rejecting invalid key
1689*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mValue       = kValue1;
1690*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mValueLength = sizeof(kValue1);
1691*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mKey         = kShortKey;
1692*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(Dns::TxtEntry::AppendEntries(&txtEntry, 1, *message) == kErrorInvalidArgs,
1693*cfb92d14SAndroid Build Coastguard Worker                  "AppendEntries() did not fail with invalid key");
1694*cfb92d14SAndroid Build Coastguard Worker 
1695*cfb92d14SAndroid Build Coastguard Worker     // Verify appending empty txt data
1696*cfb92d14SAndroid Build Coastguard Worker 
1697*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->SetLength(0));
1698*cfb92d14SAndroid Build Coastguard Worker 
1699*cfb92d14SAndroid Build Coastguard Worker     data.Init(txtData, sizeof(txtData));
1700*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, data), "AppendEntries() failed with empty array");
1701*cfb92d14SAndroid Build Coastguard Worker     txtDataLength = data.GetLength();
1702*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty array");
1703*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty array");
1704*cfb92d14SAndroid Build Coastguard Worker 
1705*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
1706*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->GetLength() == txtDataLength);
1707*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
1708*cfb92d14SAndroid Build Coastguard Worker 
1709*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->SetLength(0));
1710*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mKey         = nullptr;
1711*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mValue       = nullptr;
1712*cfb92d14SAndroid Build Coastguard Worker     txtEntry.mValueLength = 0;
1713*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(Dns::TxtEntry::AppendEntries(&txtEntry, 1, *message), "AppendEntries() failed with empty entry");
1714*cfb92d14SAndroid Build Coastguard Worker     txtDataLength = message->GetLength();
1715*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty entry");
1716*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(message->Read(0, txtData, txtDataLength), "Failed to read txt data from message");
1717*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty entry");
1718*cfb92d14SAndroid Build Coastguard Worker 
1719*cfb92d14SAndroid Build Coastguard Worker     // Verify `Iterator` behavior with invalid txt data.
1720*cfb92d14SAndroid Build Coastguard Worker 
1721*cfb92d14SAndroid Build Coastguard Worker     iterator.Init(kInvalidEncodedTxt1, sizeof(kInvalidEncodedTxt1));
1722*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorParse, "GetNextEntry() did not fail with invalid data");
1723*cfb92d14SAndroid Build Coastguard Worker 
1724*cfb92d14SAndroid Build Coastguard Worker     // Verify `GetNextEntry()` correctly skipping over empty strings and
1725*cfb92d14SAndroid Build Coastguard Worker     // strings starting with '=' (missing key) in encoded txt.
1726*cfb92d14SAndroid Build Coastguard Worker     //
1727*cfb92d14SAndroid Build Coastguard Worker     // kSpecialEncodedTxt:
1728*cfb92d14SAndroid Build Coastguard Worker     // { 0, 3, 'A', '=', 'B', 2, '=', 'C', 3, 'D', '=', 'E', 3, '=', '1', '2' }
1729*cfb92d14SAndroid Build Coastguard Worker 
1730*cfb92d14SAndroid Build Coastguard Worker     iterator.Init(kSpecialEncodedTxt, sizeof(kSpecialEncodedTxt));
1731*cfb92d14SAndroid Build Coastguard Worker 
1732*cfb92d14SAndroid Build Coastguard Worker     // We should get "A=B` (or key="A", and value="B")
1733*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(iterator.GetNextEntry(txtEntry), "GetNextEntry() failed");
1734*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((txtEntry.mKey[0] == 'A') && (txtEntry.mKey[1] == '\0'), "GetNextEntry() got incorrect key");
1735*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((txtEntry.mValueLength == 1) && (txtEntry.mValue[0] == 'B'), "GetNextEntry() got incorrect value");
1736*cfb92d14SAndroid Build Coastguard Worker 
1737*cfb92d14SAndroid Build Coastguard Worker     // We should get "D=E` (or key="D", and value="E")
1738*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(iterator.GetNextEntry(txtEntry), "GetNextEntry() failed");
1739*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((txtEntry.mKey[0] == 'D') && (txtEntry.mKey[1] == '\0'), "GetNextEntry() got incorrect key");
1740*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit((txtEntry.mValueLength == 1) && (txtEntry.mValue[0] == 'E'), "GetNextEntry() got incorrect value");
1741*cfb92d14SAndroid Build Coastguard Worker 
1742*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() returned extra entry");
1743*cfb92d14SAndroid Build Coastguard Worker 
1744*cfb92d14SAndroid Build Coastguard Worker     message->Free();
1745*cfb92d14SAndroid Build Coastguard Worker     testFreeInstance(instance);
1746*cfb92d14SAndroid Build Coastguard Worker }
1747*cfb92d14SAndroid Build Coastguard Worker 
1748*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
1749*cfb92d14SAndroid Build Coastguard Worker 
main(void)1750*cfb92d14SAndroid Build Coastguard Worker int main(void)
1751*cfb92d14SAndroid Build Coastguard Worker {
1752*cfb92d14SAndroid Build Coastguard Worker     ot::TestDnsName();
1753*cfb92d14SAndroid Build Coastguard Worker     ot::TestDnsCompressedName();
1754*cfb92d14SAndroid Build Coastguard Worker     ot::TestHeaderAndResourceRecords();
1755*cfb92d14SAndroid Build Coastguard Worker     ot::TestDnsTxtEntry();
1756*cfb92d14SAndroid Build Coastguard Worker 
1757*cfb92d14SAndroid Build Coastguard Worker     printf("All tests passed\n");
1758*cfb92d14SAndroid Build Coastguard Worker     return 0;
1759*cfb92d14SAndroid Build Coastguard Worker }
1760