1 /*
2 * Copyright (c) 2024, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <openthread/config.h>
30
31 #include "test_platform.h"
32 #include "test_util.hpp"
33
34 #include "common/arg_macros.hpp"
35 #include "common/array.hpp"
36 #include "common/as_core_type.hpp"
37 #include "common/num_utils.hpp"
38 #include "common/owning_list.hpp"
39 #include "common/string.hpp"
40 #include "common/time.hpp"
41 #include "instance/instance.hpp"
42 #include "net/dns_dso.hpp"
43 #include "net/mdns.hpp"
44
45 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
46
47 namespace ot {
48 namespace Dns {
49 namespace Multicast {
50
51 #define ENABLE_TEST_LOG 1 // Enable to get logs from unit test.
52
53 // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
54 #if ENABLE_TEST_LOG
55 #define Log(...) \
56 printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 3600000), (sNow / 60000) % 60, \
57 (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
58 #else
59 #define Log(...)
60 #endif
61
62 //---------------------------------------------------------------------------------------------------------------------
63 // Constants
64
65 static constexpr uint16_t kClassQueryUnicastFlag = (1U << 15);
66 static constexpr uint16_t kClassCacheFlushFlag = (1U << 15);
67 static constexpr uint16_t kClassMask = 0x7fff;
68 static constexpr uint16_t kStringSize = 300;
69 static constexpr uint16_t kMaxDataSize = 400;
70 static constexpr uint16_t kNumAnnounces = 3;
71 static constexpr uint16_t kNumInitalQueries = 3;
72 static constexpr uint16_t kNumRefreshQueries = 4;
73 static constexpr bool kCacheFlush = true;
74 static constexpr uint16_t kMdnsPort = 5353;
75 static constexpr uint16_t kEphemeralPort = 49152;
76 static constexpr uint16_t kLegacyUnicastMessageId = 1;
77 static constexpr uint16_t kMaxLegacyUnicastTtl = 10;
78 static constexpr uint32_t kInfraIfIndex = 1;
79
80 static const char kDeviceIp6Address[] = "fd01::1";
81
82 class DnsMessage;
83
84 //---------------------------------------------------------------------------------------------------------------------
85 // Variables
86
87 static Instance *sInstance;
88
89 static uint32_t sNow = 0;
90 static uint32_t sAlarmTime;
91 static bool sAlarmOn = false;
92
93 OwningList<DnsMessage> sDnsMessages;
94 uint32_t sInfraIfIndex;
95
96 //---------------------------------------------------------------------------------------------------------------------
97 // Prototypes
98
99 static const char *RecordTypeToString(uint16_t aType);
100
101 //---------------------------------------------------------------------------------------------------------------------
102 // Types
103
104 template <typename Type> class Allocatable
105 {
106 public:
Allocate(void)107 static Type *Allocate(void)
108 {
109 void *buf = calloc(1, sizeof(Type));
110
111 VerifyOrQuit(buf != nullptr);
112 return new (buf) Type();
113 }
114
Free(void)115 void Free(void)
116 {
117 static_cast<Type *>(this)->~Type();
118 free(this);
119 }
120 };
121
122 struct DnsName
123 {
124 Name::Buffer mName;
125
ParseFromot::Dns::Multicast::DnsName126 void ParseFrom(const Message &aMessage, uint16_t &aOffset)
127 {
128 SuccessOrQuit(Name::ReadName(aMessage, aOffset, mName));
129 }
130
CopyFromot::Dns::Multicast::DnsName131 void CopyFrom(const char *aName)
132 {
133 if (aName == nullptr)
134 {
135 mName[0] = '\0';
136 }
137 else
138 {
139 uint16_t len = StringLength(aName, sizeof(mName));
140
141 VerifyOrQuit(len < sizeof(mName));
142 memcpy(mName, aName, len + 1);
143 }
144 }
145
AsCStringot::Dns::Multicast::DnsName146 const char *AsCString(void) const { return mName; }
Matchesot::Dns::Multicast::DnsName147 bool Matches(const char *aName) const { return StringMatch(mName, aName, kStringCaseInsensitiveMatch); }
148 };
149
150 typedef String<Name::kMaxNameSize> DnsNameString;
151
152 struct AddrAndTtl
153 {
operator ==ot::Dns::Multicast::AddrAndTtl154 bool operator==(const AddrAndTtl &aOther) const { return (mTtl == aOther.mTtl) && (mAddress == aOther.mAddress); }
155
156 Ip6::Address mAddress;
157 uint32_t mTtl;
158 };
159
160 struct DnsQuestion : public Allocatable<DnsQuestion>, public LinkedListEntry<DnsQuestion>
161 {
162 DnsQuestion *mNext;
163 DnsName mName;
164 uint16_t mType;
165 uint16_t mClass;
166 bool mUnicastResponse;
167
ParseFromot::Dns::Multicast::DnsQuestion168 void ParseFrom(const Message &aMessage, uint16_t &aOffset)
169 {
170 Question question;
171
172 mName.ParseFrom(aMessage, aOffset);
173 SuccessOrQuit(aMessage.Read(aOffset, question));
174 aOffset += sizeof(Question);
175
176 mNext = nullptr;
177 mType = question.GetType();
178 mClass = question.GetClass() & kClassMask;
179 mUnicastResponse = question.GetClass() & kClassQueryUnicastFlag;
180
181 Log(" %s %s %s class:%u", mName.AsCString(), RecordTypeToString(mType), mUnicastResponse ? "QU" : "QM",
182 mClass);
183 }
184
Matchesot::Dns::Multicast::DnsQuestion185 bool Matches(const char *aName) const { return mName.Matches(aName); }
186 };
187
188 struct DnsQuestions : public OwningList<DnsQuestion>
189 {
Containsot::Dns::Multicast::DnsQuestions190 bool Contains(uint16_t aRrType, const DnsNameString &aFullName, bool aUnicastResponse = false) const
191 {
192 bool contains = false;
193 const DnsQuestion *question = FindMatching(aFullName.AsCString());
194
195 VerifyOrExit(question != nullptr);
196 VerifyOrExit(question->mType == aRrType);
197 VerifyOrExit(question->mClass == ResourceRecord::kClassInternet);
198 VerifyOrExit(question->mUnicastResponse == aUnicastResponse);
199 contains = true;
200
201 exit:
202 return contains;
203 }
204
Containsot::Dns::Multicast::DnsQuestions205 bool Contains(const DnsNameString &aFullName, bool aUnicastResponse) const
206 {
207 return Contains(ResourceRecord::kTypeAny, aFullName, aUnicastResponse);
208 }
209 };
210
211 enum TtlCheckMode : uint8_t
212 {
213 kZeroTtl,
214 kNonZeroTtl,
215 kLegacyUnicastTtl,
216 };
217
218 enum Section : uint8_t
219 {
220 kInAnswerSection,
221 kInAdditionalSection,
222 };
223
224 struct Data : public ot::Data<kWithUint16Length>
225 {
Dataot::Dns::Multicast::Data226 Data(const void *aBuffer, uint16_t aLength) { Init(aBuffer, aLength); }
227
Matchesot::Dns::Multicast::Data228 bool Matches(const Array<uint8_t, kMaxDataSize> &aDataArray) const
229 {
230 return (aDataArray.GetLength() == GetLength()) && MatchesBytesIn(aDataArray.GetArrayBuffer());
231 }
232 };
233
234 struct DnsRecord : public Allocatable<DnsRecord>, public LinkedListEntry<DnsRecord>
235 {
236 struct SrvData
237 {
238 uint16_t mPriority;
239 uint16_t mWeight;
240 uint16_t mPort;
241 DnsName mHostName;
242 };
243
244 union RecordData
245 {
RecordData(void)246 RecordData(void) { memset(this, 0, sizeof(*this)); }
247
248 Ip6::Address mIp6Address; // For AAAAA (or A)
249 SrvData mSrv; // For SRV
250 Array<uint8_t, kMaxDataSize> mData; // For TXT or KEY
251 DnsName mPtrName; // For PTR
252 NsecRecord::TypeBitMap mNsecBitmap; // For NSEC
253 };
254
255 DnsRecord *mNext;
256 DnsName mName;
257 uint16_t mType;
258 uint16_t mClass;
259 uint32_t mTtl;
260 bool mCacheFlush;
261 RecordData mData;
262
Matchesot::Dns::Multicast::DnsRecord263 bool Matches(const char *aName) const { return mName.Matches(aName); }
264
ParseFromot::Dns::Multicast::DnsRecord265 void ParseFrom(const Message &aMessage, uint16_t &aOffset)
266 {
267 String<kStringSize> logStr;
268 ResourceRecord record;
269 uint16_t offset;
270
271 mName.ParseFrom(aMessage, aOffset);
272 SuccessOrQuit(aMessage.Read(aOffset, record));
273 aOffset += sizeof(ResourceRecord);
274
275 mNext = nullptr;
276 mType = record.GetType();
277 mClass = record.GetClass() & kClassMask;
278 mCacheFlush = record.GetClass() & kClassCacheFlushFlag;
279 mTtl = record.GetTtl();
280
281 logStr.Append("%s %s%s cls:%u ttl:%u", mName.AsCString(), RecordTypeToString(mType),
282 mCacheFlush ? " cache-flush" : "", mClass, mTtl);
283
284 offset = aOffset;
285
286 switch (mType)
287 {
288 case ResourceRecord::kTypeAaaa:
289 VerifyOrQuit(record.GetLength() == sizeof(Ip6::Address));
290 SuccessOrQuit(aMessage.Read(offset, mData.mIp6Address));
291 logStr.Append(" %s", mData.mIp6Address.ToString().AsCString());
292 break;
293
294 case ResourceRecord::kTypeKey:
295 case ResourceRecord::kTypeTxt:
296 VerifyOrQuit(record.GetLength() > 0);
297 VerifyOrQuit(record.GetLength() < kMaxDataSize);
298 mData.mData.SetLength(record.GetLength());
299 SuccessOrQuit(aMessage.Read(offset, mData.mData.GetArrayBuffer(), record.GetLength()));
300 logStr.Append(" data-len:%u", record.GetLength());
301 break;
302
303 case ResourceRecord::kTypePtr:
304 mData.mPtrName.ParseFrom(aMessage, offset);
305 VerifyOrQuit(offset - aOffset == record.GetLength());
306 logStr.Append(" %s", mData.mPtrName.AsCString());
307 break;
308
309 case ResourceRecord::kTypeSrv:
310 {
311 SrvRecord srv;
312
313 offset -= sizeof(ResourceRecord);
314 SuccessOrQuit(aMessage.Read(offset, srv));
315 offset += sizeof(srv);
316 mData.mSrv.mHostName.ParseFrom(aMessage, offset);
317 VerifyOrQuit(offset - aOffset == record.GetLength());
318 mData.mSrv.mPriority = srv.GetPriority();
319 mData.mSrv.mWeight = srv.GetWeight();
320 mData.mSrv.mPort = srv.GetPort();
321 logStr.Append(" port:%u w:%u prio:%u host:%s", mData.mSrv.mPort, mData.mSrv.mWeight, mData.mSrv.mPriority,
322 mData.mSrv.mHostName.AsCString());
323 break;
324 }
325
326 case ResourceRecord::kTypeNsec:
327 {
328 NsecRecord::TypeBitMap &bitmap = mData.mNsecBitmap;
329
330 SuccessOrQuit(Name::CompareName(aMessage, offset, mName.AsCString()));
331 SuccessOrQuit(aMessage.Read(offset, &bitmap, NsecRecord::TypeBitMap::kMinSize));
332 VerifyOrQuit(bitmap.GetBlockNumber() == 0);
333 VerifyOrQuit(bitmap.GetBitmapLength() <= NsecRecord::TypeBitMap::kMaxLength);
334 SuccessOrQuit(aMessage.Read(offset, &bitmap, bitmap.GetSize()));
335
336 offset += bitmap.GetSize();
337 VerifyOrQuit(offset - aOffset == record.GetLength());
338
339 logStr.Append(" [ ");
340
341 for (uint16_t type = 0; type < bitmap.GetBitmapLength() * kBitsPerByte; type++)
342 {
343 if (bitmap.ContainsType(type))
344 {
345 logStr.Append("%s ", RecordTypeToString(type));
346 }
347 }
348
349 logStr.Append("]");
350 break;
351 }
352
353 default:
354 break;
355 }
356
357 Log(" %s", logStr.AsCString());
358
359 aOffset += record.GetLength();
360 }
361
MatchesTtlot::Dns::Multicast::DnsRecord362 bool MatchesTtl(TtlCheckMode aTtlCheckMode, uint32_t aTtl) const
363 {
364 bool matches = false;
365
366 switch (aTtlCheckMode)
367 {
368 case kZeroTtl:
369 VerifyOrExit(mTtl == 0);
370 break;
371 case kNonZeroTtl:
372 if (aTtl > 0)
373 {
374 VerifyOrQuit(mTtl == aTtl);
375 }
376
377 VerifyOrExit(mTtl > 0);
378 break;
379 case kLegacyUnicastTtl:
380 VerifyOrQuit(mTtl <= kMaxLegacyUnicastTtl);
381 break;
382 }
383
384 matches = true;
385
386 exit:
387 return matches;
388 }
389 };
390
391 struct DnsRecords : public OwningList<DnsRecord>
392 {
ContainsAaaaot::Dns::Multicast::DnsRecords393 bool ContainsAaaa(const DnsNameString &aFullName,
394 const Ip6::Address &aAddress,
395 bool aCacheFlush,
396 TtlCheckMode aTtlCheckMode,
397 uint32_t aTtl = 0) const
398 {
399 bool contains = false;
400
401 for (const DnsRecord &record : *this)
402 {
403 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypeAaaa) &&
404 (record.mData.mIp6Address == aAddress))
405 {
406 VerifyOrExit(record.mClass == ResourceRecord::kClassInternet);
407 VerifyOrExit(record.mCacheFlush == aCacheFlush);
408 VerifyOrExit(record.MatchesTtl(aTtlCheckMode, aTtl));
409 contains = true;
410 ExitNow();
411 }
412 }
413
414 exit:
415 return contains;
416 }
417
ContainsKeyot::Dns::Multicast::DnsRecords418 bool ContainsKey(const DnsNameString &aFullName,
419 const Data &aKeyData,
420 bool aCacheFlush,
421 TtlCheckMode aTtlCheckMode,
422 uint32_t aTtl = 0) const
423 {
424 bool contains = false;
425
426 for (const DnsRecord &record : *this)
427 {
428 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypeKey) &&
429 aKeyData.Matches(record.mData.mData))
430 {
431 VerifyOrExit(record.mClass == ResourceRecord::kClassInternet);
432 VerifyOrExit(record.mCacheFlush == aCacheFlush);
433 VerifyOrExit(record.MatchesTtl(aTtlCheckMode, aTtl));
434 contains = true;
435 ExitNow();
436 }
437 }
438
439 exit:
440 return contains;
441 }
442
ContainsSrvot::Dns::Multicast::DnsRecords443 bool ContainsSrv(const DnsNameString &aFullName,
444 const Core::Service &aService,
445 bool aCacheFlush,
446 TtlCheckMode aTtlCheckMode,
447 uint32_t aTtl = 0) const
448 {
449 bool contains = false;
450 DnsNameString hostName;
451
452 hostName.Append("%s.local.", aService.mHostName);
453
454 for (const DnsRecord &record : *this)
455 {
456 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypeSrv))
457 {
458 VerifyOrExit(record.mClass == ResourceRecord::kClassInternet);
459 VerifyOrExit(record.mCacheFlush == aCacheFlush);
460 VerifyOrExit(record.MatchesTtl(aTtlCheckMode, aTtl));
461 VerifyOrExit(record.mData.mSrv.mPort == aService.mPort);
462 VerifyOrExit(record.mData.mSrv.mPriority == aService.mPriority);
463 VerifyOrExit(record.mData.mSrv.mWeight == aService.mWeight);
464 VerifyOrExit(record.mData.mSrv.mHostName.Matches(hostName.AsCString()));
465 contains = true;
466 ExitNow();
467 }
468 }
469
470 exit:
471 return contains;
472 }
473
ContainsTxtot::Dns::Multicast::DnsRecords474 bool ContainsTxt(const DnsNameString &aFullName,
475 const Core::Service &aService,
476 bool aCacheFlush,
477 TtlCheckMode aTtlCheckMode,
478 uint32_t aTtl = 0) const
479 {
480 static const uint8_t kEmptyTxtData[1] = {0};
481
482 bool contains = false;
483 Data txtData(aService.mTxtData, aService.mTxtDataLength);
484
485 if ((aService.mTxtData == nullptr) || (aService.mTxtDataLength == 0))
486 {
487 txtData.Init(kEmptyTxtData, sizeof(kEmptyTxtData));
488 }
489
490 for (const DnsRecord &record : *this)
491 {
492 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypeTxt) &&
493 txtData.Matches(record.mData.mData))
494 {
495 VerifyOrExit(record.mClass == ResourceRecord::kClassInternet);
496 VerifyOrExit(record.mCacheFlush == aCacheFlush);
497 VerifyOrExit(record.MatchesTtl(aTtlCheckMode, aTtl));
498 contains = true;
499 ExitNow();
500 }
501 }
502
503 exit:
504 return contains;
505 }
506
ContainsPtrot::Dns::Multicast::DnsRecords507 bool ContainsPtr(const DnsNameString &aFullName,
508 const DnsNameString &aPtrName,
509 TtlCheckMode aTtlCheckMode,
510 uint32_t aTtl = 0) const
511 {
512 bool contains = false;
513
514 for (const DnsRecord &record : *this)
515 {
516 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypePtr) &&
517 (record.mData.mPtrName.Matches(aPtrName.AsCString())))
518 {
519 VerifyOrExit(record.mClass == ResourceRecord::kClassInternet);
520 VerifyOrExit(!record.mCacheFlush); // PTR should never use cache-flush
521 VerifyOrExit(record.MatchesTtl(aTtlCheckMode, aTtl));
522 contains = true;
523 ExitNow();
524 }
525 }
526
527 exit:
528 return contains;
529 }
530
ContainsServicesPtrot::Dns::Multicast::DnsRecords531 bool ContainsServicesPtr(const DnsNameString &aServiceType) const
532 {
533 DnsNameString allServices;
534
535 allServices.Append("_services._dns-sd._udp.local.");
536
537 return ContainsPtr(allServices, aServiceType, kNonZeroTtl, 0);
538 }
539
ContainsNsecot::Dns::Multicast::DnsRecords540 bool ContainsNsec(const DnsNameString &aFullName, uint16_t aRecordType) const
541 {
542 bool contains = false;
543
544 for (const DnsRecord &record : *this)
545 {
546 if (record.Matches(aFullName.AsCString()) && (record.mType == ResourceRecord::kTypeNsec))
547 {
548 VerifyOrQuit(!contains); // Ensure only one NSEC record
549 VerifyOrExit(record.mData.mNsecBitmap.ContainsType(aRecordType));
550 contains = true;
551 }
552 }
553
554 exit:
555 return contains;
556 }
557 };
558
559 // Bit-flags used in `Validate()` with a `Service`
560 // to specify which records should be checked in the announce
561 // message.
562
563 typedef uint8_t AnnounceCheckFlags;
564
565 static constexpr uint8_t kCheckSrv = (1 << 0);
566 static constexpr uint8_t kCheckTxt = (1 << 1);
567 static constexpr uint8_t kCheckPtr = (1 << 2);
568 static constexpr uint8_t kCheckServicesPtr = (1 << 3);
569
570 enum GoodBye : bool // Used to indicate "goodbye" records (with zero TTL)
571 {
572 kNotGoodBye = false,
573 kGoodBye = true,
574 };
575
576 enum DnsMessageType : uint8_t
577 {
578 kMulticastQuery,
579 kMulticastResponse,
580 kUnicastResponse,
581 kLegacyUnicastResponse,
582 };
583
584 struct DnsMessage : public Allocatable<DnsMessage>, public LinkedListEntry<DnsMessage>
585 {
586 DnsMessage *mNext;
587 uint32_t mTimestamp;
588 DnsMessageType mType;
589 Core::AddressInfo mUnicastDest;
590 Header mHeader;
591 DnsQuestions mQuestions;
592 DnsRecords mAnswerRecords;
593 DnsRecords mAuthRecords;
594 DnsRecords mAdditionalRecords;
595
DnsMessageot::Dns::Multicast::DnsMessage596 DnsMessage(void)
597 : mNext(nullptr)
598 , mTimestamp(sNow)
599 {
600 }
601
RecordsForot::Dns::Multicast::DnsMessage602 const DnsRecords &RecordsFor(Section aSection) const
603 {
604 const DnsRecords *records = nullptr;
605
606 switch (aSection)
607 {
608 case kInAnswerSection:
609 records = &mAnswerRecords;
610 break;
611 case kInAdditionalSection:
612 records = &mAdditionalRecords;
613 break;
614 }
615
616 VerifyOrQuit(records != nullptr);
617
618 return *records;
619 }
620
ParseRecordsot::Dns::Multicast::DnsMessage621 void ParseRecords(const Message &aMessage,
622 uint16_t &aOffset,
623 uint16_t aNumRecords,
624 OwningList<DnsRecord> &aRecords,
625 const char *aSectionName)
626 {
627 if (aNumRecords > 0)
628 {
629 Log(" %s", aSectionName);
630 }
631
632 for (; aNumRecords > 0; aNumRecords--)
633 {
634 DnsRecord *record = DnsRecord::Allocate();
635
636 record->ParseFrom(aMessage, aOffset);
637 aRecords.PushAfterTail(*record);
638 }
639 }
640
ParseFromot::Dns::Multicast::DnsMessage641 void ParseFrom(const Message &aMessage)
642 {
643 uint16_t offset = 0;
644
645 SuccessOrQuit(aMessage.Read(offset, mHeader));
646 offset += sizeof(Header);
647
648 Log(" %s id:%u qt:%u t:%u rcode:%u [q:%u ans:%u auth:%u addn:%u]",
649 mHeader.GetType() == Header::kTypeQuery ? "Query" : "Response", mHeader.GetMessageId(),
650 mHeader.GetQueryType(), mHeader.IsTruncationFlagSet(), mHeader.GetResponseCode(),
651 mHeader.GetQuestionCount(), mHeader.GetAnswerCount(), mHeader.GetAuthorityRecordCount(),
652 mHeader.GetAdditionalRecordCount());
653
654 if (mHeader.GetQuestionCount() > 0)
655 {
656 Log(" Question");
657 }
658
659 for (uint16_t num = mHeader.GetQuestionCount(); num > 0; num--)
660 {
661 DnsQuestion *question = DnsQuestion::Allocate();
662
663 question->ParseFrom(aMessage, offset);
664 mQuestions.PushAfterTail(*question);
665 }
666
667 ParseRecords(aMessage, offset, mHeader.GetAnswerCount(), mAnswerRecords, "Answer");
668 ParseRecords(aMessage, offset, mHeader.GetAuthorityRecordCount(), mAuthRecords, "Authority");
669 ParseRecords(aMessage, offset, mHeader.GetAdditionalRecordCount(), mAdditionalRecords, "Additional");
670 }
671
ValidateHeaderot::Dns::Multicast::DnsMessage672 void ValidateHeader(DnsMessageType aType,
673 uint16_t aQuestionCount,
674 uint16_t aAnswerCount,
675 uint16_t aAuthCount,
676 uint16_t aAdditionalCount) const
677 {
678 VerifyOrQuit(mType == aType);
679 VerifyOrQuit(mHeader.GetQuestionCount() == aQuestionCount);
680 VerifyOrQuit(mHeader.GetAnswerCount() == aAnswerCount);
681 VerifyOrQuit(mHeader.GetAuthorityRecordCount() == aAuthCount);
682 VerifyOrQuit(mHeader.GetAdditionalRecordCount() == aAdditionalCount);
683
684 if (aType == kUnicastResponse)
685 {
686 Ip6::Address ip6Address;
687
688 SuccessOrQuit(ip6Address.FromString(kDeviceIp6Address));
689
690 VerifyOrQuit(mUnicastDest.mPort == kMdnsPort);
691 VerifyOrQuit(mUnicastDest.GetAddress() == ip6Address);
692 }
693
694 if (aType == kLegacyUnicastResponse)
695 {
696 VerifyOrQuit(mHeader.GetMessageId() == kLegacyUnicastMessageId);
697 VerifyOrQuit(mUnicastDest.mPort == kEphemeralPort);
698 }
699 }
700
DetermineFullNameForKeyot::Dns::Multicast::DnsMessage701 static void DetermineFullNameForKey(const Core::Key &aKey, DnsNameString &aFullName)
702 {
703 if (aKey.mServiceType != nullptr)
704 {
705 aFullName.Append("%s.%s.local.", aKey.mName, aKey.mServiceType);
706 }
707 else
708 {
709 aFullName.Append("%s.local.", aKey.mName);
710 }
711 }
712
DetermineTtlCheckModeot::Dns::Multicast::DnsMessage713 static TtlCheckMode DetermineTtlCheckMode(DnsMessageType aMessageType, bool aIsGoodBye)
714 {
715 TtlCheckMode ttlCheck;
716
717 if (aMessageType == kLegacyUnicastResponse)
718 {
719 ttlCheck = kLegacyUnicastTtl;
720 }
721 else
722 {
723 ttlCheck = aIsGoodBye ? kZeroTtl : kNonZeroTtl;
724 }
725
726 return ttlCheck;
727 }
728
ValidateAsProbeForot::Dns::Multicast::DnsMessage729 void ValidateAsProbeFor(const Core::Host &aHost, bool aUnicastResponse) const
730 {
731 DnsNameString fullName;
732
733 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
734 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
735
736 fullName.Append("%s.local.", aHost.mHostName);
737 VerifyOrQuit(mQuestions.Contains(fullName, aUnicastResponse));
738
739 for (uint16_t index = 0; index < aHost.mAddressesLength; index++)
740 {
741 VerifyOrQuit(mAuthRecords.ContainsAaaa(fullName, AsCoreType(&aHost.mAddresses[index]), !kCacheFlush,
742 kNonZeroTtl, aHost.mTtl));
743 }
744 }
745
ValidateAsProbeForot::Dns::Multicast::DnsMessage746 void ValidateAsProbeFor(const Core::Service &aService, bool aUnicastResponse) const
747 {
748 DnsNameString serviceName;
749
750 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
751 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
752
753 serviceName.Append("%s.%s.local.", aService.mServiceInstance, aService.mServiceType);
754
755 VerifyOrQuit(mQuestions.Contains(serviceName, aUnicastResponse));
756
757 VerifyOrQuit(mAuthRecords.ContainsSrv(serviceName, aService, !kCacheFlush, kNonZeroTtl, aService.mTtl));
758 VerifyOrQuit(mAuthRecords.ContainsTxt(serviceName, aService, !kCacheFlush, kNonZeroTtl, aService.mTtl));
759 }
760
ValidateAsProbeForot::Dns::Multicast::DnsMessage761 void ValidateAsProbeFor(const Core::Key &aKey, bool aUnicastResponse) const
762 {
763 DnsNameString fullName;
764
765 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
766 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
767
768 DetermineFullNameForKey(aKey, fullName);
769
770 VerifyOrQuit(mQuestions.Contains(fullName, aUnicastResponse));
771 VerifyOrQuit(mAuthRecords.ContainsKey(fullName, Data(aKey.mKeyData, aKey.mKeyDataLength), !kCacheFlush,
772 kNonZeroTtl, aKey.mTtl));
773 }
774
Validateot::Dns::Multicast::DnsMessage775 void Validate(const Core::Host &aHost, Section aSection, GoodBye aIsGoodBye = kNotGoodBye) const
776 {
777 DnsNameString fullName;
778 TtlCheckMode ttlCheck;
779
780 bool cacheFlushSet = (mType == kLegacyUnicastResponse) ? !kCacheFlush : kCacheFlush;
781
782 ttlCheck = DetermineTtlCheckMode(mType, aIsGoodBye);
783
784 VerifyOrQuit(mHeader.GetType() == Header::kTypeResponse);
785
786 fullName.Append("%s.local.", aHost.mHostName);
787
788 for (uint16_t index = 0; index < aHost.mAddressesLength; index++)
789 {
790 VerifyOrQuit(RecordsFor(aSection).ContainsAaaa(fullName, AsCoreType(&aHost.mAddresses[index]),
791 cacheFlushSet, ttlCheck, aHost.mTtl));
792 }
793
794 if (!aIsGoodBye && (aSection == kInAnswerSection))
795 {
796 VerifyOrQuit(mAdditionalRecords.ContainsNsec(fullName, ResourceRecord::kTypeAaaa));
797 }
798 }
799
Validateot::Dns::Multicast::DnsMessage800 void Validate(const Core::Service &aService,
801 Section aSection,
802 AnnounceCheckFlags aCheckFlags,
803 GoodBye aIsGoodBye = kNotGoodBye) const
804 {
805 DnsNameString serviceName;
806 DnsNameString serviceType;
807 TtlCheckMode ttlCheck;
808 bool checkNsec = false;
809 bool cacheFlushSet = (mType == kLegacyUnicastResponse) ? !kCacheFlush : kCacheFlush;
810
811 ttlCheck = DetermineTtlCheckMode(mType, aIsGoodBye);
812
813 VerifyOrQuit(mHeader.GetType() == Header::kTypeResponse);
814
815 serviceName.Append("%s.%s.local.", aService.mServiceInstance, aService.mServiceType);
816 serviceType.Append("%s.local.", aService.mServiceType);
817
818 if (aCheckFlags & kCheckSrv)
819 {
820 VerifyOrQuit(
821 RecordsFor(aSection).ContainsSrv(serviceName, aService, cacheFlushSet, ttlCheck, aService.mTtl));
822
823 checkNsec = true;
824 }
825
826 if (aCheckFlags & kCheckTxt)
827 {
828 VerifyOrQuit(
829 RecordsFor(aSection).ContainsTxt(serviceName, aService, cacheFlushSet, ttlCheck, aService.mTtl));
830
831 checkNsec = true;
832 }
833
834 if (aCheckFlags & kCheckPtr)
835 {
836 VerifyOrQuit(RecordsFor(aSection).ContainsPtr(serviceType, serviceName, ttlCheck, aService.mTtl));
837 }
838
839 if (aCheckFlags & kCheckServicesPtr)
840 {
841 VerifyOrQuit(RecordsFor(aSection).ContainsServicesPtr(serviceType));
842 }
843
844 if (!aIsGoodBye && checkNsec && (aSection == kInAnswerSection))
845 {
846 VerifyOrQuit(mAdditionalRecords.ContainsNsec(serviceName, ResourceRecord::kTypeSrv));
847 VerifyOrQuit(mAdditionalRecords.ContainsNsec(serviceName, ResourceRecord::kTypeTxt));
848 }
849 }
850
Validateot::Dns::Multicast::DnsMessage851 void Validate(const Core::Key &aKey, Section aSection, GoodBye aIsGoodBye = kNotGoodBye) const
852 {
853 DnsNameString fullName;
854 TtlCheckMode ttlCheck;
855 bool cacheFlushSet = (mType == kLegacyUnicastResponse) ? !kCacheFlush : kCacheFlush;
856
857 VerifyOrQuit(mHeader.GetType() == Header::kTypeResponse);
858
859 DetermineFullNameForKey(aKey, fullName);
860
861 ttlCheck = DetermineTtlCheckMode(mType, aIsGoodBye);
862
863 VerifyOrQuit(RecordsFor(aSection).ContainsKey(fullName, Data(aKey.mKeyData, aKey.mKeyDataLength), cacheFlushSet,
864 ttlCheck, aKey.mTtl));
865
866 if (!aIsGoodBye && (aSection == kInAnswerSection))
867 {
868 VerifyOrQuit(mAdditionalRecords.ContainsNsec(fullName, ResourceRecord::kTypeKey));
869 }
870 }
871
ValidateSubTypeot::Dns::Multicast::DnsMessage872 void ValidateSubType(const char *aSubLabel, const Core::Service &aService, GoodBye aIsGoodBye = kNotGoodBye) const
873 {
874 DnsNameString serviceName;
875 DnsNameString subServiceType;
876
877 VerifyOrQuit(mHeader.GetType() == Header::kTypeResponse);
878
879 serviceName.Append("%s.%s.local.", aService.mServiceInstance, aService.mServiceType);
880 subServiceType.Append("%s._sub.%s.local.", aSubLabel, aService.mServiceType);
881
882 VerifyOrQuit(mAnswerRecords.ContainsPtr(subServiceType, serviceName, aIsGoodBye ? kZeroTtl : kNonZeroTtl,
883 aService.mTtl));
884 }
885
ValidateAsQueryForot::Dns::Multicast::DnsMessage886 void ValidateAsQueryFor(const Core::Browser &aBrowser) const
887 {
888 DnsNameString fullServiceType;
889
890 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
891 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
892
893 if (aBrowser.mSubTypeLabel == nullptr)
894 {
895 fullServiceType.Append("%s.local.", aBrowser.mServiceType);
896 }
897 else
898 {
899 fullServiceType.Append("%s._sub.%s.local", aBrowser.mSubTypeLabel, aBrowser.mServiceType);
900 }
901
902 VerifyOrQuit(mQuestions.Contains(ResourceRecord::kTypePtr, fullServiceType));
903 }
904
ValidateAsQueryForot::Dns::Multicast::DnsMessage905 void ValidateAsQueryFor(const Core::SrvResolver &aResolver) const
906 {
907 DnsNameString fullName;
908
909 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
910 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
911
912 fullName.Append("%s.%s.local.", aResolver.mServiceInstance, aResolver.mServiceType);
913
914 VerifyOrQuit(mQuestions.Contains(ResourceRecord::kTypeSrv, fullName));
915 }
916
ValidateAsQueryForot::Dns::Multicast::DnsMessage917 void ValidateAsQueryFor(const Core::TxtResolver &aResolver) const
918 {
919 DnsNameString fullName;
920
921 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
922 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
923
924 fullName.Append("%s.%s.local.", aResolver.mServiceInstance, aResolver.mServiceType);
925
926 VerifyOrQuit(mQuestions.Contains(ResourceRecord::kTypeTxt, fullName));
927 }
928
ValidateAsQueryForot::Dns::Multicast::DnsMessage929 void ValidateAsQueryFor(const Core::AddressResolver &aResolver) const
930 {
931 DnsNameString fullName;
932
933 VerifyOrQuit(mHeader.GetType() == Header::kTypeQuery);
934 VerifyOrQuit(!mHeader.IsTruncationFlagSet());
935
936 fullName.Append("%s.local.", aResolver.mHostName);
937
938 VerifyOrQuit(mQuestions.Contains(ResourceRecord::kTypeAaaa, fullName));
939 }
940 };
941
942 struct RegCallback
943 {
Resetot::Dns::Multicast::RegCallback944 void Reset(void) { mWasCalled = false; }
945
946 bool mWasCalled;
947 Error mError;
948 };
949
950 static constexpr uint16_t kMaxCallbacks = 8;
951
952 static RegCallback sRegCallbacks[kMaxCallbacks];
953
HandleCallback(otInstance * aInstance,otMdnsRequestId aRequestId,otError aError)954 static void HandleCallback(otInstance *aInstance, otMdnsRequestId aRequestId, otError aError)
955 {
956 Log("Register callback - ResuestId:%u Error:%s", aRequestId, otThreadErrorToString(aError));
957
958 VerifyOrQuit(aInstance == sInstance);
959 VerifyOrQuit(aRequestId < kMaxCallbacks);
960
961 VerifyOrQuit(!sRegCallbacks[aRequestId].mWasCalled);
962
963 sRegCallbacks[aRequestId].mWasCalled = true;
964 sRegCallbacks[aRequestId].mError = aError;
965 }
966
HandleSuccessCallback(otInstance * aInstance,otMdnsRequestId aRequestId,otError aError)967 static void HandleSuccessCallback(otInstance *aInstance, otMdnsRequestId aRequestId, otError aError)
968 {
969 HandleCallback(aInstance, aRequestId, aError);
970 SuccessOrQuit(aError);
971 }
972
973 struct ConflictCallback
974 {
Resetot::Dns::Multicast::ConflictCallback975 void Reset(void) { mWasCalled = false; }
976
Handleot::Dns::Multicast::ConflictCallback977 void Handle(const char *aName, const char *aServiceType)
978 {
979 VerifyOrQuit(!mWasCalled);
980
981 mWasCalled = true;
982 mName.Clear();
983 mName.Append("%s", aName);
984
985 mHasServiceType = (aServiceType != nullptr);
986 VerifyOrExit(mHasServiceType);
987 mServiceType.Clear();
988 mServiceType.Append("%s", aServiceType);
989
990 exit:
991 return;
992 }
993
994 bool mWasCalled;
995 bool mHasServiceType;
996 DnsNameString mName;
997 DnsNameString mServiceType;
998 };
999
1000 static ConflictCallback sConflictCallback;
1001
HandleConflict(otInstance * aInstance,const char * aName,const char * aServiceType)1002 static void HandleConflict(otInstance *aInstance, const char *aName, const char *aServiceType)
1003 {
1004 Log("Conflict callback - %s %s", aName, (aServiceType == nullptr) ? "" : aServiceType);
1005
1006 VerifyOrQuit(aInstance == sInstance);
1007 sConflictCallback.Handle(aName, aServiceType);
1008 }
1009
1010 //---------------------------------------------------------------------------------------------------------------------
1011 // Helper functions and methods
1012
RecordTypeToString(uint16_t aType)1013 static const char *RecordTypeToString(uint16_t aType)
1014 {
1015 const char *str = "Other";
1016
1017 switch (aType)
1018 {
1019 case ResourceRecord::kTypeZero:
1020 str = "ZERO";
1021 break;
1022 case ResourceRecord::kTypeA:
1023 str = "A";
1024 break;
1025 case ResourceRecord::kTypeSoa:
1026 str = "SOA";
1027 break;
1028 case ResourceRecord::kTypeCname:
1029 str = "CNAME";
1030 break;
1031 case ResourceRecord::kTypePtr:
1032 str = "PTR";
1033 break;
1034 case ResourceRecord::kTypeTxt:
1035 str = "TXT";
1036 break;
1037 case ResourceRecord::kTypeSig:
1038 str = "SIG";
1039 break;
1040 case ResourceRecord::kTypeKey:
1041 str = "KEY";
1042 break;
1043 case ResourceRecord::kTypeAaaa:
1044 str = "AAAA";
1045 break;
1046 case ResourceRecord::kTypeSrv:
1047 str = "SRV";
1048 break;
1049 case ResourceRecord::kTypeOpt:
1050 str = "OPT";
1051 break;
1052 case ResourceRecord::kTypeNsec:
1053 str = "NSEC";
1054 break;
1055 case ResourceRecord::kTypeAny:
1056 str = "ANY";
1057 break;
1058 }
1059
1060 return str;
1061 }
1062
ParseMessage(const Message & aMessage,const Core::AddressInfo * aUnicastDest)1063 static void ParseMessage(const Message &aMessage, const Core::AddressInfo *aUnicastDest)
1064 {
1065 DnsMessage *msg = DnsMessage::Allocate();
1066
1067 msg->ParseFrom(aMessage);
1068
1069 switch (msg->mHeader.GetType())
1070 {
1071 case Header::kTypeQuery:
1072 msg->mType = kMulticastQuery;
1073 VerifyOrQuit(aUnicastDest == nullptr);
1074 break;
1075
1076 case Header::kTypeResponse:
1077 if (aUnicastDest == nullptr)
1078 {
1079 msg->mType = kMulticastResponse;
1080 }
1081 else
1082 {
1083 msg->mType = (aUnicastDest->mPort == kEphemeralPort) ? kLegacyUnicastResponse : kUnicastResponse;
1084 msg->mUnicastDest = *aUnicastDest;
1085 }
1086 }
1087
1088 sDnsMessages.PushAfterTail(*msg);
1089 }
1090
SendQuery(const char * aName,uint16_t aRecordType,uint16_t aRecordClass=ResourceRecord::kClassInternet,bool aTruncated=false,bool aLegacyUnicastQuery=false)1091 static void SendQuery(const char *aName,
1092 uint16_t aRecordType,
1093 uint16_t aRecordClass = ResourceRecord::kClassInternet,
1094 bool aTruncated = false,
1095 bool aLegacyUnicastQuery = false)
1096 {
1097 Message *message;
1098 Header header;
1099 Core::AddressInfo senderAddrInfo;
1100
1101 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1102 VerifyOrQuit(message != nullptr);
1103
1104 header.Clear();
1105 header.SetType(Header::kTypeQuery);
1106 header.SetQuestionCount(1);
1107
1108 if (aLegacyUnicastQuery)
1109 {
1110 header.SetMessageId(kLegacyUnicastMessageId);
1111 }
1112
1113 if (aTruncated)
1114 {
1115 header.SetTruncationFlag();
1116 }
1117
1118 SuccessOrQuit(message->Append(header));
1119 SuccessOrQuit(Name::AppendName(aName, *message));
1120 SuccessOrQuit(message->Append(Question(aRecordType, aRecordClass)));
1121
1122 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1123 senderAddrInfo.mPort = aLegacyUnicastQuery ? kEphemeralPort : kMdnsPort;
1124 senderAddrInfo.mInfraIfIndex = 0;
1125
1126 Log("Sending query for %s %s", aName, RecordTypeToString(aRecordType));
1127
1128 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1129 }
1130
SendQueryForTwo(const char * aName1,uint16_t aRecordType1,const char * aName2,uint16_t aRecordType2,bool aIsLegacyUnicast=false)1131 static void SendQueryForTwo(const char *aName1,
1132 uint16_t aRecordType1,
1133 const char *aName2,
1134 uint16_t aRecordType2,
1135 bool aIsLegacyUnicast = false)
1136 {
1137 // Send query with two questions.
1138
1139 Message *message;
1140 Header header;
1141 Core::AddressInfo senderAddrInfo;
1142
1143 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1144 VerifyOrQuit(message != nullptr);
1145
1146 header.Clear();
1147 header.SetType(Header::kTypeQuery);
1148 header.SetQuestionCount(2);
1149
1150 SuccessOrQuit(message->Append(header));
1151 SuccessOrQuit(Name::AppendName(aName1, *message));
1152 SuccessOrQuit(message->Append(Question(aRecordType1, ResourceRecord::kClassInternet)));
1153 SuccessOrQuit(Name::AppendName(aName2, *message));
1154 SuccessOrQuit(message->Append(Question(aRecordType2, ResourceRecord::kClassInternet)));
1155
1156 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1157 senderAddrInfo.mPort = aIsLegacyUnicast ? kEphemeralPort : kMdnsPort;
1158 senderAddrInfo.mInfraIfIndex = 0;
1159
1160 Log("Sending query for %s %s and %s %s", aName1, RecordTypeToString(aRecordType1), aName2,
1161 RecordTypeToString(aRecordType2));
1162
1163 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1164 }
1165
SendPtrResponse(const char * aName,const char * aPtrName,uint32_t aTtl,Section aSection)1166 static void SendPtrResponse(const char *aName, const char *aPtrName, uint32_t aTtl, Section aSection)
1167 {
1168 Message *message;
1169 Header header;
1170 PtrRecord ptr;
1171 Core::AddressInfo senderAddrInfo;
1172
1173 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1174 VerifyOrQuit(message != nullptr);
1175
1176 header.Clear();
1177 header.SetType(Header::kTypeResponse);
1178
1179 switch (aSection)
1180 {
1181 case kInAnswerSection:
1182 header.SetAnswerCount(1);
1183 break;
1184 case kInAdditionalSection:
1185 header.SetAdditionalRecordCount(1);
1186 break;
1187 }
1188
1189 SuccessOrQuit(message->Append(header));
1190 SuccessOrQuit(Name::AppendName(aName, *message));
1191
1192 ptr.Init();
1193 ptr.SetTtl(aTtl);
1194 ptr.SetLength(StringLength(aPtrName, Name::kMaxNameSize) + 1);
1195 SuccessOrQuit(message->Append(ptr));
1196 SuccessOrQuit(Name::AppendName(aPtrName, *message));
1197
1198 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1199 senderAddrInfo.mPort = kMdnsPort;
1200 senderAddrInfo.mInfraIfIndex = 0;
1201
1202 Log("Sending PTR response for %s with %s, ttl:%lu", aName, aPtrName, ToUlong(aTtl));
1203
1204 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1205 }
1206
SendSrvResponse(const char * aServiceName,const char * aHostName,uint16_t aPort,uint16_t aPriority,uint16_t aWeight,uint32_t aTtl,Section aSection)1207 static void SendSrvResponse(const char *aServiceName,
1208 const char *aHostName,
1209 uint16_t aPort,
1210 uint16_t aPriority,
1211 uint16_t aWeight,
1212 uint32_t aTtl,
1213 Section aSection)
1214 {
1215 Message *message;
1216 Header header;
1217 SrvRecord srv;
1218 Core::AddressInfo senderAddrInfo;
1219
1220 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1221 VerifyOrQuit(message != nullptr);
1222
1223 header.Clear();
1224 header.SetType(Header::kTypeResponse);
1225
1226 switch (aSection)
1227 {
1228 case kInAnswerSection:
1229 header.SetAnswerCount(1);
1230 break;
1231 case kInAdditionalSection:
1232 header.SetAdditionalRecordCount(1);
1233 break;
1234 }
1235
1236 SuccessOrQuit(message->Append(header));
1237 SuccessOrQuit(Name::AppendName(aServiceName, *message));
1238
1239 srv.Init();
1240 srv.SetTtl(aTtl);
1241 srv.SetPort(aPort);
1242 srv.SetPriority(aPriority);
1243 srv.SetWeight(aWeight);
1244 srv.SetLength(sizeof(srv) - sizeof(ResourceRecord) + StringLength(aHostName, Name::kMaxNameSize) + 1);
1245 SuccessOrQuit(message->Append(srv));
1246 SuccessOrQuit(Name::AppendName(aHostName, *message));
1247
1248 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1249 senderAddrInfo.mPort = kMdnsPort;
1250 senderAddrInfo.mInfraIfIndex = 0;
1251
1252 Log("Sending SRV response for %s, host:%s, port:%u, ttl:%lu", aServiceName, aHostName, aPort, ToUlong(aTtl));
1253
1254 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1255 }
1256
SendTxtResponse(const char * aServiceName,const uint8_t * aTxtData,uint16_t aTxtDataLength,uint32_t aTtl,Section aSection)1257 static void SendTxtResponse(const char *aServiceName,
1258 const uint8_t *aTxtData,
1259 uint16_t aTxtDataLength,
1260 uint32_t aTtl,
1261 Section aSection)
1262 {
1263 Message *message;
1264 Header header;
1265 TxtRecord txt;
1266 Core::AddressInfo senderAddrInfo;
1267
1268 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1269 VerifyOrQuit(message != nullptr);
1270
1271 header.Clear();
1272 header.SetType(Header::kTypeResponse);
1273
1274 switch (aSection)
1275 {
1276 case kInAnswerSection:
1277 header.SetAnswerCount(1);
1278 break;
1279 case kInAdditionalSection:
1280 header.SetAdditionalRecordCount(1);
1281 break;
1282 }
1283
1284 SuccessOrQuit(message->Append(header));
1285 SuccessOrQuit(Name::AppendName(aServiceName, *message));
1286
1287 txt.Init();
1288 txt.SetTtl(aTtl);
1289 txt.SetLength(aTxtDataLength);
1290 SuccessOrQuit(message->Append(txt));
1291 SuccessOrQuit(message->AppendBytes(aTxtData, aTxtDataLength));
1292
1293 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1294 senderAddrInfo.mPort = kMdnsPort;
1295 senderAddrInfo.mInfraIfIndex = 0;
1296
1297 Log("Sending TXT response for %s, len:%u, ttl:%lu", aServiceName, aTxtDataLength, ToUlong(aTtl));
1298
1299 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1300 }
1301
SendHostAddrResponse(const char * aHostName,AddrAndTtl * aAddrAndTtls,uint32_t aNumAddrs,bool aCacheFlush,Section aSection)1302 static void SendHostAddrResponse(const char *aHostName,
1303 AddrAndTtl *aAddrAndTtls,
1304 uint32_t aNumAddrs,
1305 bool aCacheFlush,
1306 Section aSection)
1307 {
1308 Message *message;
1309 Header header;
1310 AaaaRecord record;
1311 Core::AddressInfo senderAddrInfo;
1312
1313 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1314 VerifyOrQuit(message != nullptr);
1315
1316 header.Clear();
1317 header.SetType(Header::kTypeResponse);
1318
1319 switch (aSection)
1320 {
1321 case kInAnswerSection:
1322 header.SetAnswerCount(aNumAddrs);
1323 break;
1324 case kInAdditionalSection:
1325 header.SetAdditionalRecordCount(aNumAddrs);
1326 break;
1327 }
1328
1329 SuccessOrQuit(message->Append(header));
1330
1331 record.Init();
1332
1333 if (aCacheFlush)
1334 {
1335 record.SetClass(record.GetClass() | kClassCacheFlushFlag);
1336 }
1337
1338 Log("Sending AAAA response for %s numAddrs:%u, cach-flush:%u", aHostName, aNumAddrs, aCacheFlush);
1339
1340 for (uint32_t index = 0; index < aNumAddrs; index++)
1341 {
1342 record.SetTtl(aAddrAndTtls[index].mTtl);
1343 record.SetAddress(aAddrAndTtls[index].mAddress);
1344
1345 SuccessOrQuit(Name::AppendName(aHostName, *message));
1346 SuccessOrQuit(message->Append(record));
1347
1348 Log(" - %s, ttl:%lu", aAddrAndTtls[index].mAddress.ToString().AsCString(), ToUlong(aAddrAndTtls[index].mTtl));
1349 }
1350
1351 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1352 senderAddrInfo.mPort = kMdnsPort;
1353 senderAddrInfo.mInfraIfIndex = 0;
1354
1355 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1356 }
1357
SendResponseWithEmptyKey(const char * aName,Section aSection)1358 static void SendResponseWithEmptyKey(const char *aName, Section aSection)
1359 {
1360 Message *message;
1361 Header header;
1362 ResourceRecord record;
1363 Core::AddressInfo senderAddrInfo;
1364
1365 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1366 VerifyOrQuit(message != nullptr);
1367
1368 header.Clear();
1369 header.SetType(Header::kTypeResponse);
1370
1371 switch (aSection)
1372 {
1373 case kInAnswerSection:
1374 header.SetAnswerCount(1);
1375 break;
1376 case kInAdditionalSection:
1377 header.SetAdditionalRecordCount(1);
1378 break;
1379 }
1380
1381 SuccessOrQuit(message->Append(header));
1382 SuccessOrQuit(Name::AppendName(aName, *message));
1383
1384 record.Init(ResourceRecord::kTypeKey);
1385 record.SetTtl(4500);
1386 record.SetLength(0);
1387 SuccessOrQuit(message->Append(record));
1388
1389 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1390 senderAddrInfo.mPort = kMdnsPort;
1391 senderAddrInfo.mInfraIfIndex = 0;
1392
1393 Log("Sending response with empty key for %s", aName);
1394
1395 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1396 }
1397
1398 struct KnownAnswer
1399 {
1400 const char *mPtrAnswer;
1401 uint32_t mTtl;
1402 };
1403
SendPtrQueryWithKnownAnswers(const char * aName,const KnownAnswer * aKnownAnswers,uint16_t aNumAnswers)1404 static void SendPtrQueryWithKnownAnswers(const char *aName, const KnownAnswer *aKnownAnswers, uint16_t aNumAnswers)
1405 {
1406 Message *message;
1407 Header header;
1408 Core::AddressInfo senderAddrInfo;
1409 uint16_t nameOffset;
1410
1411 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1412 VerifyOrQuit(message != nullptr);
1413
1414 header.Clear();
1415 header.SetType(Header::kTypeQuery);
1416 header.SetQuestionCount(1);
1417 header.SetAnswerCount(aNumAnswers);
1418
1419 SuccessOrQuit(message->Append(header));
1420 nameOffset = message->GetLength();
1421 SuccessOrQuit(Name::AppendName(aName, *message));
1422 SuccessOrQuit(message->Append(Question(ResourceRecord::kTypePtr, ResourceRecord::kClassInternet)));
1423
1424 for (uint16_t index = 0; index < aNumAnswers; index++)
1425 {
1426 PtrRecord ptr;
1427
1428 ptr.Init();
1429 ptr.SetTtl(aKnownAnswers[index].mTtl);
1430 ptr.SetLength(StringLength(aKnownAnswers[index].mPtrAnswer, Name::kMaxNameSize) + 1);
1431
1432 SuccessOrQuit(Name::AppendPointerLabel(nameOffset, *message));
1433 SuccessOrQuit(message->Append(ptr));
1434 SuccessOrQuit(Name::AppendName(aKnownAnswers[index].mPtrAnswer, *message));
1435 }
1436
1437 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1438 senderAddrInfo.mPort = kMdnsPort;
1439 senderAddrInfo.mInfraIfIndex = 0;
1440
1441 Log("Sending query for %s PTR with %u known-answers", aName, aNumAnswers);
1442
1443 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1444 }
1445
SendEmtryPtrQueryWithKnownAnswers(const char * aName,const KnownAnswer * aKnownAnswers,uint16_t aNumAnswers)1446 static void SendEmtryPtrQueryWithKnownAnswers(const char *aName, const KnownAnswer *aKnownAnswers, uint16_t aNumAnswers)
1447 {
1448 Message *message;
1449 Header header;
1450 Core::AddressInfo senderAddrInfo;
1451 uint16_t nameOffset = 0;
1452
1453 message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther);
1454 VerifyOrQuit(message != nullptr);
1455
1456 header.Clear();
1457 header.SetType(Header::kTypeQuery);
1458 header.SetAnswerCount(aNumAnswers);
1459
1460 SuccessOrQuit(message->Append(header));
1461
1462 for (uint16_t index = 0; index < aNumAnswers; index++)
1463 {
1464 PtrRecord ptr;
1465
1466 ptr.Init();
1467 ptr.SetTtl(aKnownAnswers[index].mTtl);
1468 ptr.SetLength(StringLength(aKnownAnswers[index].mPtrAnswer, Name::kMaxNameSize) + 1);
1469
1470 if (nameOffset == 0)
1471 {
1472 nameOffset = message->GetLength();
1473 SuccessOrQuit(Name::AppendName(aName, *message));
1474 }
1475 else
1476 {
1477 SuccessOrQuit(Name::AppendPointerLabel(nameOffset, *message));
1478 }
1479
1480 SuccessOrQuit(message->Append(ptr));
1481 SuccessOrQuit(Name::AppendName(aKnownAnswers[index].mPtrAnswer, *message));
1482 }
1483
1484 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1485 senderAddrInfo.mPort = kMdnsPort;
1486 senderAddrInfo.mInfraIfIndex = 0;
1487
1488 Log("Sending empty query with %u known-answers for %s", aNumAnswers, aName);
1489
1490 otPlatMdnsHandleReceive(sInstance, message, /* aIsUnicast */ false, &senderAddrInfo);
1491 }
1492
1493 //----------------------------------------------------------------------------------------------------------------------
1494 // `otPlatLog`
1495
1496 extern "C" {
1497
1498 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
otPlatLog(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,...)1499 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
1500 {
1501 OT_UNUSED_VARIABLE(aLogLevel);
1502 OT_UNUSED_VARIABLE(aLogRegion);
1503 OT_UNUSED_VARIABLE(aFormat);
1504
1505 #if ENABLE_TEST_LOG
1506 va_list args;
1507
1508 printf(" ");
1509 va_start(args, aFormat);
1510 vprintf(aFormat, args);
1511 va_end(args);
1512
1513 printf("\n");
1514 #endif
1515 }
1516
1517 #endif
1518
1519 //----------------------------------------------------------------------------------------------------------------------
1520 // `otPlatAlarm`
1521
otPlatAlarmMilliStop(otInstance *)1522 void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
1523
otPlatAlarmMilliStartAt(otInstance *,uint32_t aT0,uint32_t aDt)1524 void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
1525 {
1526 sAlarmOn = true;
1527 sAlarmTime = aT0 + aDt;
1528 }
1529
otPlatAlarmMilliGetNow(void)1530 uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
1531
1532 //----------------------------------------------------------------------------------------------------------------------
1533 // Heap allocation
1534
1535 Array<void *, 500> sHeapAllocatedPtrs;
1536
1537 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
1538
otPlatCAlloc(size_t aNum,size_t aSize)1539 void *otPlatCAlloc(size_t aNum, size_t aSize)
1540 {
1541 void *ptr = calloc(aNum, aSize);
1542
1543 SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
1544
1545 return ptr;
1546 }
1547
otPlatFree(void * aPtr)1548 void otPlatFree(void *aPtr)
1549 {
1550 if (aPtr != nullptr)
1551 {
1552 void **entry = sHeapAllocatedPtrs.Find(aPtr);
1553
1554 VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
1555 sHeapAllocatedPtrs.Remove(*entry);
1556 }
1557
1558 free(aPtr);
1559 }
1560
1561 #endif
1562
1563 //----------------------------------------------------------------------------------------------------------------------
1564 // `otPlatMdns`
1565
otPlatMdnsSetListeningEnabled(otInstance * aInstance,bool aEnable,uint32_t aInfraIfIndex)1566 otError otPlatMdnsSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex)
1567 {
1568 VerifyOrQuit(aInstance == sInstance);
1569 sInfraIfIndex = aInfraIfIndex;
1570
1571 Log("otPlatMdnsSetListeningEnabled(%s)", aEnable ? "true" : "false");
1572
1573 return kErrorNone;
1574 }
1575
otPlatMdnsSendMulticast(otInstance * aInstance,otMessage * aMessage,uint32_t aInfraIfIndex)1576 void otPlatMdnsSendMulticast(otInstance *aInstance, otMessage *aMessage, uint32_t aInfraIfIndex)
1577 {
1578 Message &message = AsCoreType(aMessage);
1579 Core::AddressInfo senderAddrInfo;
1580
1581 VerifyOrQuit(aInfraIfIndex == sInfraIfIndex);
1582
1583 Log("otPlatMdnsSendMulticast(msg-len:%u)", message.GetLength());
1584 ParseMessage(message, nullptr);
1585
1586 // Pass the multicast message back.
1587
1588 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1589 senderAddrInfo.mPort = kMdnsPort;
1590 senderAddrInfo.mInfraIfIndex = 0;
1591
1592 otPlatMdnsHandleReceive(sInstance, aMessage, /* aIsUnicast */ false, &senderAddrInfo);
1593 }
1594
otPlatMdnsSendUnicast(otInstance * aInstance,otMessage * aMessage,const otPlatMdnsAddressInfo * aAddress)1595 void otPlatMdnsSendUnicast(otInstance *aInstance, otMessage *aMessage, const otPlatMdnsAddressInfo *aAddress)
1596 {
1597 Message &message = AsCoreType(aMessage);
1598 const Core::AddressInfo &address = AsCoreType(aAddress);
1599 Ip6::Address deviceAddress;
1600
1601 Log("otPlatMdnsSendUnicast() - [%s]:%u", address.GetAddress().ToString().AsCString(), address.mPort);
1602 ParseMessage(message, AsCoreTypePtr(aAddress));
1603
1604 SuccessOrQuit(deviceAddress.FromString(kDeviceIp6Address));
1605
1606 if ((address.GetAddress() == deviceAddress) && (address.mPort == kMdnsPort))
1607 {
1608 Core::AddressInfo senderAddrInfo;
1609
1610 SuccessOrQuit(AsCoreType(&senderAddrInfo.mAddress).FromString(kDeviceIp6Address));
1611 senderAddrInfo.mPort = kMdnsPort;
1612 senderAddrInfo.mInfraIfIndex = 0;
1613
1614 Log("otPlatMdnsSendUnicast() - unicast msg matches this device address, passing it back");
1615 otPlatMdnsHandleReceive(sInstance, &message, /* aIsUnicast */ true, &senderAddrInfo);
1616 }
1617 else
1618 {
1619 message.Free();
1620 }
1621 }
1622
1623 } // extern "C"
1624
1625 //---------------------------------------------------------------------------------------------------------------------
1626
ProcessTasklets(void)1627 void ProcessTasklets(void)
1628 {
1629 while (otTaskletsArePending(sInstance))
1630 {
1631 otTaskletsProcess(sInstance);
1632 }
1633 }
1634
AdvanceTime(uint32_t aDuration)1635 void AdvanceTime(uint32_t aDuration)
1636 {
1637 uint32_t time = sNow + aDuration;
1638
1639 Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
1640
1641 while (TimeMilli(sAlarmTime) <= TimeMilli(time))
1642 {
1643 ProcessTasklets();
1644 sNow = sAlarmTime;
1645 otPlatAlarmMilliFired(sInstance);
1646 }
1647
1648 ProcessTasklets();
1649 sNow = time;
1650 }
1651
InitTest(void)1652 Core *InitTest(void)
1653 {
1654 sNow = 0;
1655 sAlarmOn = false;
1656
1657 sDnsMessages.Clear();
1658
1659 for (RegCallback ®Callbck : sRegCallbacks)
1660 {
1661 regCallbck.Reset();
1662 }
1663
1664 sConflictCallback.Reset();
1665
1666 sInstance = testInitInstance();
1667
1668 VerifyOrQuit(sInstance != nullptr);
1669
1670 return &sInstance->Get<Core>();
1671 }
1672
1673 //----------------------------------------------------------------------------------------------------------------------
1674
1675 static const uint8_t kKey1[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
1676 static const uint8_t kKey2[] = {0x12, 0x34, 0x56};
1677 static const uint8_t kTxtData1[] = {3, 'a', '=', '1', 0};
1678 static const uint8_t kTxtData2[] = {1, 'b', 0};
1679 static const uint8_t kEmptyTxtData[] = {0};
1680
1681 //---------------------------------------------------------------------------------------------------------------------
1682
TestHostReg(void)1683 void TestHostReg(void)
1684 {
1685 Core *mdns = InitTest();
1686 Core::Host host;
1687 Ip6::Address hostAddresses[3];
1688 const DnsMessage *dnsMsg;
1689 uint16_t heapAllocations;
1690 DnsNameString hostFullName;
1691
1692 Log("-------------------------------------------------------------------------------------------");
1693 Log("TestHostReg");
1694
1695 AdvanceTime(1);
1696
1697 heapAllocations = sHeapAllocatedPtrs.GetLength();
1698 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
1699
1700 SuccessOrQuit(hostAddresses[0].FromString("fd00::aaaa"));
1701 SuccessOrQuit(hostAddresses[1].FromString("fd00::bbbb"));
1702 SuccessOrQuit(hostAddresses[2].FromString("fd00::cccc"));
1703
1704 host.mHostName = "myhost";
1705 host.mAddresses = hostAddresses;
1706 host.mAddressesLength = 3;
1707 host.mTtl = 1500;
1708
1709 hostFullName.Append("%s.local.", host.mHostName);
1710
1711 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1712 Log("Register a `HostEntry`, check probes and announcements");
1713
1714 sDnsMessages.Clear();
1715
1716 sRegCallbacks[0].Reset();
1717 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
1718
1719 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
1720 {
1721 sDnsMessages.Clear();
1722
1723 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
1724 AdvanceTime(250);
1725
1726 VerifyOrQuit(!sDnsMessages.IsEmpty());
1727 dnsMsg = sDnsMessages.GetHead();
1728 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 3, /* Addnl */ 0);
1729 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ (probeCount == 0));
1730 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1731 }
1732
1733 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1734 {
1735 sDnsMessages.Clear();
1736
1737 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
1738 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
1739
1740 VerifyOrQuit(!sDnsMessages.IsEmpty());
1741 dnsMsg = sDnsMessages.GetHead();
1742 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
1743 dnsMsg->Validate(host, kInAnswerSection);
1744 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1745 }
1746
1747 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1748 Log("Send a query for AAAA record and validate the response");
1749
1750 AdvanceTime(2000);
1751
1752 sDnsMessages.Clear();
1753 SendQuery(hostFullName.AsCString(), ResourceRecord::kTypeAaaa);
1754
1755 AdvanceTime(1000);
1756
1757 dnsMsg = sDnsMessages.GetHead();
1758 VerifyOrQuit(dnsMsg != nullptr);
1759 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
1760 dnsMsg->Validate(host, kInAnswerSection);
1761
1762 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1763 Log("Send a query for ANY record and validate the response");
1764
1765 AdvanceTime(2000);
1766
1767 sDnsMessages.Clear();
1768 SendQuery(hostFullName.AsCString(), ResourceRecord::kTypeAny);
1769
1770 AdvanceTime(1000);
1771
1772 dnsMsg = sDnsMessages.GetHead();
1773 VerifyOrQuit(dnsMsg != nullptr);
1774 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
1775 dnsMsg->Validate(host, kInAnswerSection);
1776
1777 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1778 Log("Send a query for non-existing record and validate the response with NSEC");
1779
1780 AdvanceTime(2000);
1781
1782 sDnsMessages.Clear();
1783 SendQuery(hostFullName.AsCString(), ResourceRecord::kTypeA);
1784
1785 AdvanceTime(1000);
1786
1787 dnsMsg = sDnsMessages.GetHead();
1788 VerifyOrQuit(dnsMsg != nullptr);
1789 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 1);
1790 VerifyOrQuit(dnsMsg->mAdditionalRecords.ContainsNsec(hostFullName, ResourceRecord::kTypeAaaa));
1791
1792 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1793 Log("Update number of host addresses and validate new announcements");
1794
1795 host.mAddressesLength = 2;
1796
1797 sRegCallbacks[1].Reset();
1798 sDnsMessages.Clear();
1799 SuccessOrQuit(mdns->RegisterHost(host, 1, HandleSuccessCallback));
1800
1801 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1802 {
1803 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
1804 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
1805
1806 VerifyOrQuit(!sDnsMessages.IsEmpty());
1807 dnsMsg = sDnsMessages.GetHead();
1808 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
1809 dnsMsg->Validate(host, kInAnswerSection);
1810 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1811 sDnsMessages.Clear();
1812 }
1813
1814 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1815 Log("Change the addresses and validate the first announce");
1816
1817 host.mAddressesLength = 3;
1818
1819 sRegCallbacks[0].Reset();
1820 sDnsMessages.Clear();
1821 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
1822
1823 AdvanceTime(300);
1824 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
1825
1826 VerifyOrQuit(!sDnsMessages.IsEmpty());
1827 dnsMsg = sDnsMessages.GetHead();
1828 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
1829 dnsMsg->Validate(host, kInAnswerSection);
1830 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1831
1832 Log("Change the address list again before second announce");
1833
1834 host.mAddressesLength = 1;
1835
1836 sRegCallbacks[1].Reset();
1837 sDnsMessages.Clear();
1838 SuccessOrQuit(mdns->RegisterHost(host, 1, HandleSuccessCallback));
1839
1840 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1841 {
1842 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
1843 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
1844
1845 VerifyOrQuit(!sDnsMessages.IsEmpty());
1846 dnsMsg = sDnsMessages.GetHead();
1847 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
1848 dnsMsg->Validate(host, kInAnswerSection);
1849 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1850 sDnsMessages.Clear();
1851 }
1852
1853 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1854 Log("Change `HostEntry` TTL and validate announcements");
1855
1856 host.mTtl = 120;
1857
1858 sRegCallbacks[1].Reset();
1859 sDnsMessages.Clear();
1860 SuccessOrQuit(mdns->RegisterHost(host, 1, HandleSuccessCallback));
1861
1862 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1863 {
1864 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
1865 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
1866
1867 VerifyOrQuit(!sDnsMessages.IsEmpty());
1868 dnsMsg = sDnsMessages.GetHead();
1869 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
1870 dnsMsg->Validate(host, kInAnswerSection);
1871 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1872 sDnsMessages.Clear();
1873 }
1874
1875 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1876 Log("Send a query for AAAA record and validate the response");
1877
1878 AdvanceTime(2000);
1879
1880 sDnsMessages.Clear();
1881 SendQuery(hostFullName.AsCString(), ResourceRecord::kTypeAaaa);
1882
1883 AdvanceTime(1000);
1884
1885 dnsMsg = sDnsMessages.GetHead();
1886 VerifyOrQuit(dnsMsg != nullptr);
1887 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
1888 dnsMsg->Validate(host, kInAnswerSection);
1889
1890 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1891 Log("Unregister the host and validate the goodbye announces");
1892
1893 sDnsMessages.Clear();
1894 SuccessOrQuit(mdns->UnregisterHost(host));
1895
1896 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1897 {
1898 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
1899
1900 VerifyOrQuit(!sDnsMessages.IsEmpty());
1901 dnsMsg = sDnsMessages.GetHead();
1902 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
1903 dnsMsg->Validate(host, kInAnswerSection, kGoodBye);
1904 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1905 sDnsMessages.Clear();
1906 }
1907
1908 AdvanceTime(15000);
1909 VerifyOrQuit(sDnsMessages.IsEmpty());
1910
1911 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1912 Log("Register a host with no address (first time)");
1913
1914 host.mHostName = "newhost";
1915 host.mAddresses = nullptr;
1916 host.mAddressesLength = 0;
1917 host.mTtl = 1500;
1918
1919 sRegCallbacks[2].Reset();
1920 SuccessOrQuit(mdns->RegisterHost(host, 2, HandleSuccessCallback));
1921
1922 AdvanceTime(1);
1923 VerifyOrQuit(sRegCallbacks[2].mWasCalled);
1924
1925 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1926 Log("Register the same host now with an address");
1927
1928 host.mAddresses = &hostAddresses[0];
1929 host.mAddressesLength = 1;
1930
1931 sRegCallbacks[3].Reset();
1932 SuccessOrQuit(mdns->RegisterHost(host, 3, HandleSuccessCallback));
1933
1934 AdvanceTime(15000);
1935 VerifyOrQuit(sRegCallbacks[3].mWasCalled);
1936
1937 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1938 Log("Register the same host again now with no address");
1939
1940 host.mAddressesLength = 0;
1941
1942 sRegCallbacks[4].Reset();
1943 sDnsMessages.Clear();
1944 SuccessOrQuit(mdns->RegisterHost(host, 4, HandleSuccessCallback));
1945
1946 AdvanceTime(1);
1947 VerifyOrQuit(sRegCallbacks[4].mWasCalled);
1948
1949 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
1950 {
1951 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
1952
1953 VerifyOrQuit(!sDnsMessages.IsEmpty());
1954 dnsMsg = sDnsMessages.GetHead();
1955 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
1956 dnsMsg->Validate(host, kInAnswerSection, kGoodBye);
1957 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
1958 sDnsMessages.Clear();
1959 }
1960
1961 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1962 Log("Register the same host again now adding an address");
1963
1964 host.mAddresses = &hostAddresses[1];
1965 host.mAddressesLength = 1;
1966
1967 sRegCallbacks[5].Reset();
1968 SuccessOrQuit(mdns->RegisterHost(host, 5, HandleSuccessCallback));
1969
1970 AdvanceTime(15000);
1971 VerifyOrQuit(sRegCallbacks[5].mWasCalled);
1972
1973 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1974
1975 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
1976 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
1977
1978 Log("End of test");
1979
1980 testFreeInstance(sInstance);
1981 }
1982
1983 //---------------------------------------------------------------------------------------------------------------------
1984
TestKeyReg(void)1985 void TestKeyReg(void)
1986 {
1987 Core *mdns = InitTest();
1988 Core::Key key;
1989 const DnsMessage *dnsMsg;
1990 uint16_t heapAllocations;
1991
1992 Log("-------------------------------------------------------------------------------------------");
1993 Log("TestKeyReg");
1994
1995 AdvanceTime(1);
1996
1997 heapAllocations = sHeapAllocatedPtrs.GetLength();
1998 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
1999
2000 // Run all tests twice. first with key for a host name, followed
2001 // by key for service instance name.
2002
2003 for (uint8_t iter = 0; iter < 2; iter++)
2004 {
2005 DnsNameString fullName;
2006
2007 if (iter == 0)
2008 {
2009 Log("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
2010 Log("Registering key for 'myhost' host name");
2011 key.mName = "myhost";
2012 key.mServiceType = nullptr;
2013
2014 fullName.Append("%s.local.", key.mName);
2015 }
2016 else
2017 {
2018 Log("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
2019 Log("Registering key for 'mysrv._srv._udo' service name");
2020
2021 key.mName = "mysrv";
2022 key.mServiceType = "_srv._udp";
2023
2024 fullName.Append("%s.%s.local.", key.mName, key.mServiceType);
2025 }
2026
2027 key.mKeyData = kKey1;
2028 key.mKeyDataLength = sizeof(kKey1);
2029 key.mTtl = 8000;
2030
2031 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2032 Log("Register a key record and check probes and announcements");
2033
2034 sDnsMessages.Clear();
2035
2036 sRegCallbacks[0].Reset();
2037 SuccessOrQuit(mdns->RegisterKey(key, 0, HandleSuccessCallback));
2038
2039 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
2040 {
2041 sDnsMessages.Clear();
2042
2043 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2044 AdvanceTime(250);
2045
2046 VerifyOrQuit(!sDnsMessages.IsEmpty());
2047 dnsMsg = sDnsMessages.GetHead();
2048 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 1, /* Addnl */ 0);
2049 dnsMsg->ValidateAsProbeFor(key, /* aUnicastRequest */ (probeCount == 0));
2050 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2051 }
2052
2053 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2054 {
2055 sDnsMessages.Clear();
2056
2057 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
2058 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
2059
2060 VerifyOrQuit(!sDnsMessages.IsEmpty());
2061 dnsMsg = sDnsMessages.GetHead();
2062 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2063 dnsMsg->Validate(key, kInAnswerSection);
2064 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2065 }
2066
2067 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2068 Log("Send a query for KEY record and validate the response");
2069
2070 AdvanceTime(2000);
2071
2072 sDnsMessages.Clear();
2073 SendQuery(fullName.AsCString(), ResourceRecord::kTypeKey);
2074
2075 AdvanceTime(1000);
2076
2077 dnsMsg = sDnsMessages.GetHead();
2078 VerifyOrQuit(dnsMsg != nullptr);
2079 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2080 dnsMsg->Validate(key, kInAnswerSection);
2081
2082 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2083 Log("Send a query for ANY record and validate the response");
2084
2085 AdvanceTime(2000);
2086
2087 sDnsMessages.Clear();
2088 SendQuery(fullName.AsCString(), ResourceRecord::kTypeAny);
2089
2090 AdvanceTime(1000);
2091
2092 dnsMsg = sDnsMessages.GetHead();
2093 VerifyOrQuit(dnsMsg != nullptr);
2094 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2095 dnsMsg->Validate(key, kInAnswerSection);
2096
2097 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2098 Log("Send a query for non-existing record and validate the response with NSEC");
2099
2100 AdvanceTime(2000);
2101
2102 sDnsMessages.Clear();
2103 SendQuery(fullName.AsCString(), ResourceRecord::kTypeA);
2104
2105 AdvanceTime(1000);
2106
2107 dnsMsg = sDnsMessages.GetHead();
2108 VerifyOrQuit(dnsMsg != nullptr);
2109 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 1);
2110 VerifyOrQuit(dnsMsg->mAdditionalRecords.ContainsNsec(fullName, ResourceRecord::kTypeKey));
2111
2112 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2113 Log("Change the TTL");
2114
2115 key.mTtl = 0; // Use default
2116
2117 sRegCallbacks[1].Reset();
2118 sDnsMessages.Clear();
2119 SuccessOrQuit(mdns->RegisterKey(key, 1, HandleSuccessCallback));
2120
2121 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2122 {
2123 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2124 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2125
2126 VerifyOrQuit(!sDnsMessages.IsEmpty());
2127 dnsMsg = sDnsMessages.GetHead();
2128 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2129 dnsMsg->Validate(key, kInAnswerSection);
2130 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2131
2132 sDnsMessages.Clear();
2133 }
2134
2135 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2136 Log("Change the key");
2137
2138 key.mKeyData = kKey2;
2139 key.mKeyDataLength = sizeof(kKey2);
2140
2141 sRegCallbacks[1].Reset();
2142 sDnsMessages.Clear();
2143 SuccessOrQuit(mdns->RegisterKey(key, 1, HandleSuccessCallback));
2144
2145 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2146 {
2147 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2148 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2149
2150 VerifyOrQuit(!sDnsMessages.IsEmpty());
2151 dnsMsg = sDnsMessages.GetHead();
2152 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2153 dnsMsg->Validate(key, kInAnswerSection);
2154 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2155
2156 sDnsMessages.Clear();
2157 }
2158
2159 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2160 Log("Unregister the key and validate the goodbye announces");
2161
2162 sDnsMessages.Clear();
2163 SuccessOrQuit(mdns->UnregisterKey(key));
2164
2165 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2166 {
2167 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2168
2169 VerifyOrQuit(!sDnsMessages.IsEmpty());
2170 dnsMsg = sDnsMessages.GetHead();
2171 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
2172 dnsMsg->Validate(key, kInAnswerSection, kGoodBye);
2173 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2174
2175 sDnsMessages.Clear();
2176 }
2177 }
2178
2179 AdvanceTime(15000);
2180 VerifyOrQuit(sDnsMessages.IsEmpty());
2181
2182 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
2183 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
2184
2185 Log("End of test");
2186
2187 testFreeInstance(sInstance);
2188 }
2189
2190 //---------------------------------------------------------------------------------------------------------------------
2191
TestServiceReg(void)2192 void TestServiceReg(void)
2193 {
2194 Core *mdns = InitTest();
2195 Core::Service service;
2196 const DnsMessage *dnsMsg;
2197 uint16_t heapAllocations;
2198 DnsNameString fullServiceName;
2199 DnsNameString fullServiceType;
2200
2201 Log("-------------------------------------------------------------------------------------------");
2202 Log("TestServiceReg");
2203
2204 AdvanceTime(1);
2205
2206 heapAllocations = sHeapAllocatedPtrs.GetLength();
2207 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
2208
2209 service.mHostName = "myhost";
2210 service.mServiceInstance = "myservice";
2211 service.mServiceType = "_srv._udp";
2212 service.mSubTypeLabels = nullptr;
2213 service.mSubTypeLabelsLength = 0;
2214 service.mTxtData = kTxtData1;
2215 service.mTxtDataLength = sizeof(kTxtData1);
2216 service.mPort = 1234;
2217 service.mPriority = 1;
2218 service.mWeight = 2;
2219 service.mTtl = 1000;
2220
2221 fullServiceName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
2222 fullServiceType.Append("%s.local.", service.mServiceType);
2223
2224 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2225 Log("Register a `ServiceEntry`, check probes and announcements");
2226
2227 sDnsMessages.Clear();
2228
2229 sRegCallbacks[0].Reset();
2230 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
2231
2232 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
2233 {
2234 sDnsMessages.Clear();
2235
2236 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2237 AdvanceTime(250);
2238
2239 VerifyOrQuit(!sDnsMessages.IsEmpty());
2240 dnsMsg = sDnsMessages.GetHead();
2241 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
2242 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
2243 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2244 }
2245
2246 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2247 {
2248 sDnsMessages.Clear();
2249
2250 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
2251 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
2252
2253 VerifyOrQuit(!sDnsMessages.IsEmpty());
2254 dnsMsg = sDnsMessages.GetHead();
2255 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
2256 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
2257 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2258 }
2259
2260 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2261 Log("Send a query for SRV record and validate the response");
2262
2263 AdvanceTime(2000);
2264
2265 sDnsMessages.Clear();
2266 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeSrv);
2267
2268 AdvanceTime(1000);
2269
2270 dnsMsg = sDnsMessages.GetHead();
2271 VerifyOrQuit(dnsMsg != nullptr);
2272 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2273 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv);
2274
2275 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2276 Log("Send a query for TXT record and validate the response");
2277
2278 AdvanceTime(2000);
2279
2280 sDnsMessages.Clear();
2281 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeTxt);
2282
2283 AdvanceTime(1000);
2284
2285 dnsMsg = sDnsMessages.GetHead();
2286 VerifyOrQuit(dnsMsg != nullptr);
2287 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2288 dnsMsg->Validate(service, kInAnswerSection, kCheckTxt);
2289
2290 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2291 Log("Send a query for ANY record and validate the response");
2292
2293 AdvanceTime(2000);
2294
2295 sDnsMessages.Clear();
2296 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeAny);
2297
2298 AdvanceTime(1000);
2299
2300 dnsMsg = sDnsMessages.GetHead();
2301 VerifyOrQuit(dnsMsg != nullptr);
2302 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
2303 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt);
2304
2305 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2306 Log("Send a query for PTR record for service type and validate the response");
2307
2308 AdvanceTime(2000);
2309
2310 sDnsMessages.Clear();
2311 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr);
2312
2313 AdvanceTime(1000);
2314
2315 dnsMsg = sDnsMessages.GetHead();
2316 VerifyOrQuit(dnsMsg != nullptr);
2317 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
2318 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
2319 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
2320
2321 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2322 Log("Send a query for PTR record for `services._dns-sd` and validate the response");
2323
2324 AdvanceTime(2000);
2325
2326 sDnsMessages.Clear();
2327 SendQuery("_services._dns-sd._udp.local.", ResourceRecord::kTypePtr);
2328
2329 AdvanceTime(1000);
2330
2331 dnsMsg = sDnsMessages.GetHead();
2332 VerifyOrQuit(dnsMsg != nullptr);
2333 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
2334 dnsMsg->Validate(service, kInAnswerSection, kCheckServicesPtr);
2335
2336 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2337 Log("Update service port number and validate new announcements of SRV record");
2338
2339 service.mPort = 4567;
2340
2341 sRegCallbacks[1].Reset();
2342 sDnsMessages.Clear();
2343 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2344
2345 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2346 {
2347 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2348 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2349
2350 VerifyOrQuit(!sDnsMessages.IsEmpty());
2351 dnsMsg = sDnsMessages.GetHead();
2352 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2353 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv);
2354 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2355 sDnsMessages.Clear();
2356 }
2357
2358 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2359 Log("Update TXT data and validate new announcements of TXT record");
2360
2361 service.mTxtData = nullptr;
2362 service.mTxtDataLength = 0;
2363
2364 sRegCallbacks[1].Reset();
2365 sDnsMessages.Clear();
2366 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2367
2368 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2369 {
2370 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2371 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2372
2373 VerifyOrQuit(!sDnsMessages.IsEmpty());
2374 dnsMsg = sDnsMessages.GetHead();
2375 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2376 dnsMsg->Validate(service, kInAnswerSection, kCheckTxt);
2377 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2378 sDnsMessages.Clear();
2379 }
2380
2381 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2382 Log("Update both service and TXT data and validate new announcements of both records");
2383
2384 service.mTxtData = kTxtData2;
2385 service.mTxtDataLength = sizeof(kTxtData2);
2386 service.mWeight = 0;
2387
2388 sRegCallbacks[1].Reset();
2389 sDnsMessages.Clear();
2390 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2391
2392 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2393 {
2394 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2395 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2396
2397 VerifyOrQuit(!sDnsMessages.IsEmpty());
2398 dnsMsg = sDnsMessages.GetHead();
2399 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
2400 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt);
2401 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2402 sDnsMessages.Clear();
2403 }
2404
2405 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2406 Log("Update service host name and validate new announcements of SRV record");
2407
2408 service.mHostName = "newhost";
2409
2410 sRegCallbacks[1].Reset();
2411 sDnsMessages.Clear();
2412 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2413
2414 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2415 {
2416 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2417 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2418
2419 VerifyOrQuit(!sDnsMessages.IsEmpty());
2420 dnsMsg = sDnsMessages.GetHead();
2421 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2422 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv);
2423 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2424 sDnsMessages.Clear();
2425 }
2426
2427 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2428 Log("Update TTL and validate new announcements of SRV, TXT and PTR records");
2429
2430 service.mTtl = 0;
2431
2432 sRegCallbacks[1].Reset();
2433 sDnsMessages.Clear();
2434 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2435
2436 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2437 {
2438 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2439 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2440
2441 VerifyOrQuit(!sDnsMessages.IsEmpty());
2442 dnsMsg = sDnsMessages.GetHead();
2443 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
2444 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr);
2445 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2446 sDnsMessages.Clear();
2447 }
2448
2449 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2450 Log("Unregister the service and validate the goodbye announces");
2451
2452 sDnsMessages.Clear();
2453 SuccessOrQuit(mdns->UnregisterService(service));
2454
2455 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2456 {
2457 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2458
2459 VerifyOrQuit(!sDnsMessages.IsEmpty());
2460 dnsMsg = sDnsMessages.GetHead();
2461 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 0);
2462 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
2463 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2464 sDnsMessages.Clear();
2465 }
2466
2467 AdvanceTime(15000);
2468 VerifyOrQuit(sDnsMessages.IsEmpty());
2469
2470 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
2471 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
2472
2473 Log("End of test");
2474
2475 testFreeInstance(sInstance);
2476 }
2477
2478 //---------------------------------------------------------------------------------------------------------------------
2479
TestUnregisterBeforeProbeFinished(void)2480 void TestUnregisterBeforeProbeFinished(void)
2481 {
2482 const uint8_t kKey1[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
2483
2484 Core *mdns = InitTest();
2485 Core::Host host;
2486 Core::Service service;
2487 Core::Key key;
2488 Ip6::Address hostAddresses[3];
2489 const DnsMessage *dnsMsg;
2490 uint16_t heapAllocations;
2491
2492 Log("-------------------------------------------------------------------------------------------");
2493 Log("TestUnregisterBeforeProbeFinished");
2494
2495 AdvanceTime(1);
2496
2497 heapAllocations = sHeapAllocatedPtrs.GetLength();
2498 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
2499
2500 SuccessOrQuit(hostAddresses[0].FromString("fd00::aaaa"));
2501 SuccessOrQuit(hostAddresses[1].FromString("fd00::bbbb"));
2502 SuccessOrQuit(hostAddresses[2].FromString("fd00::cccc"));
2503
2504 host.mHostName = "myhost";
2505 host.mAddresses = hostAddresses;
2506 host.mAddressesLength = 3;
2507 host.mTtl = 1500;
2508
2509 service.mHostName = "myhost";
2510 service.mServiceInstance = "myservice";
2511 service.mServiceType = "_srv._udp";
2512 service.mSubTypeLabels = nullptr;
2513 service.mSubTypeLabelsLength = 0;
2514 service.mTxtData = kTxtData1;
2515 service.mTxtDataLength = sizeof(kTxtData1);
2516 service.mPort = 1234;
2517 service.mPriority = 1;
2518 service.mWeight = 2;
2519 service.mTtl = 1000;
2520
2521 key.mName = "mysrv";
2522 key.mServiceType = "_srv._udp";
2523 key.mKeyData = kKey1;
2524 key.mKeyDataLength = sizeof(kKey1);
2525 key.mTtl = 8000;
2526
2527 // Repeat the same test 3 times for host and service and key registration.
2528
2529 for (uint8_t iter = 0; iter < 3; iter++)
2530 {
2531 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2532 Log("Register an entry, check for the first two probes");
2533
2534 sDnsMessages.Clear();
2535
2536 sRegCallbacks[0].Reset();
2537
2538 switch (iter)
2539 {
2540 case 0:
2541 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
2542 break;
2543 case 1:
2544 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
2545 break;
2546 case 2:
2547 SuccessOrQuit(mdns->RegisterKey(key, 0, HandleSuccessCallback));
2548 break;
2549 }
2550
2551 for (uint8_t probeCount = 0; probeCount < 2; probeCount++)
2552 {
2553 sDnsMessages.Clear();
2554
2555 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2556 AdvanceTime(250);
2557
2558 VerifyOrQuit(!sDnsMessages.IsEmpty());
2559 dnsMsg = sDnsMessages.GetHead();
2560
2561 switch (iter)
2562 {
2563 case 0:
2564 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 3, /* Addnl */ 0);
2565 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ (probeCount == 0));
2566 break;
2567 case 1:
2568 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
2569 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
2570 break;
2571 case 2:
2572 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 1, /* Addnl */ 0);
2573 dnsMsg->ValidateAsProbeFor(key, /* aUnicastRequest */ (probeCount == 0));
2574 break;
2575 }
2576
2577 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2578 }
2579
2580 sDnsMessages.Clear();
2581 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2582
2583 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2584 Log("Unregister the entry before the last probe and make sure probing stops");
2585
2586 switch (iter)
2587 {
2588 case 0:
2589 SuccessOrQuit(mdns->UnregisterHost(host));
2590 break;
2591 case 1:
2592 SuccessOrQuit(mdns->UnregisterService(service));
2593 break;
2594 case 2:
2595 SuccessOrQuit(mdns->UnregisterKey(key));
2596 break;
2597 }
2598
2599 AdvanceTime(20 * 1000);
2600 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2601
2602 VerifyOrQuit(sDnsMessages.IsEmpty());
2603 }
2604
2605 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
2606 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
2607
2608 Log("End of test");
2609
2610 testFreeInstance(sInstance);
2611 }
2612
2613 //---------------------------------------------------------------------------------------------------------------------
2614
TestServiceSubTypeReg(void)2615 void TestServiceSubTypeReg(void)
2616 {
2617 static const char *const kSubTypes1[] = {"_s1", "_r2", "_vXy", "_last"};
2618 static const char *const kSubTypes2[] = {"_vxy", "_r1", "_r2", "_zzz"};
2619
2620 Core *mdns = InitTest();
2621 Core::Service service;
2622 const DnsMessage *dnsMsg;
2623 uint16_t heapAllocations;
2624 DnsNameString fullServiceName;
2625 DnsNameString fullServiceType;
2626 DnsNameString fullSubServiceType;
2627
2628 Log("-------------------------------------------------------------------------------------------");
2629 Log("TestServiceSubTypeReg");
2630
2631 AdvanceTime(1);
2632
2633 heapAllocations = sHeapAllocatedPtrs.GetLength();
2634 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
2635
2636 service.mHostName = "tarnished";
2637 service.mServiceInstance = "elden";
2638 service.mServiceType = "_ring._udp";
2639 service.mSubTypeLabels = kSubTypes1;
2640 service.mSubTypeLabelsLength = 3;
2641 service.mTxtData = kTxtData1;
2642 service.mTxtDataLength = sizeof(kTxtData1);
2643 service.mPort = 1234;
2644 service.mPriority = 1;
2645 service.mWeight = 2;
2646 service.mTtl = 6000;
2647
2648 fullServiceName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
2649 fullServiceType.Append("%s.local.", service.mServiceType);
2650
2651 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2652 Log("Register a `ServiceEntry` with sub-types, check probes and announcements");
2653
2654 sDnsMessages.Clear();
2655
2656 sRegCallbacks[0].Reset();
2657 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
2658
2659 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
2660 {
2661 sDnsMessages.Clear();
2662
2663 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
2664 AdvanceTime(250);
2665
2666 VerifyOrQuit(!sDnsMessages.IsEmpty());
2667 dnsMsg = sDnsMessages.GetHead();
2668 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
2669 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
2670 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2671 }
2672
2673 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2674 {
2675 sDnsMessages.Clear();
2676
2677 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
2678 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
2679
2680 VerifyOrQuit(!sDnsMessages.IsEmpty());
2681 dnsMsg = sDnsMessages.GetHead();
2682 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 7, /* Auth */ 0, /* Addnl */ 1);
2683 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
2684
2685 for (uint16_t index = 0; index < service.mSubTypeLabelsLength; index++)
2686 {
2687 dnsMsg->ValidateSubType(service.mSubTypeLabels[index], service);
2688 }
2689
2690 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2691 }
2692
2693 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2694 Log("Send a query for SRV record and validate the response");
2695
2696 AdvanceTime(2000);
2697
2698 sDnsMessages.Clear();
2699 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeSrv);
2700
2701 AdvanceTime(1000);
2702
2703 dnsMsg = sDnsMessages.GetHead();
2704 VerifyOrQuit(dnsMsg != nullptr);
2705 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2706 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv);
2707
2708 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2709 Log("Send a query for TXT record and validate the response");
2710
2711 AdvanceTime(2000);
2712
2713 sDnsMessages.Clear();
2714 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeTxt);
2715
2716 AdvanceTime(1000);
2717
2718 dnsMsg = sDnsMessages.GetHead();
2719 VerifyOrQuit(dnsMsg != nullptr);
2720 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
2721 dnsMsg->Validate(service, kInAnswerSection, kCheckTxt);
2722
2723 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2724 Log("Send a query for ANY record and validate the response");
2725
2726 AdvanceTime(2000);
2727
2728 sDnsMessages.Clear();
2729 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeAny);
2730
2731 AdvanceTime(1000);
2732
2733 dnsMsg = sDnsMessages.GetHead();
2734 VerifyOrQuit(dnsMsg != nullptr);
2735 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
2736 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt);
2737
2738 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2739 Log("Send a query for PTR record for service type and validate the response");
2740
2741 AdvanceTime(2000);
2742
2743 sDnsMessages.Clear();
2744 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr);
2745
2746 AdvanceTime(1000);
2747
2748 dnsMsg = sDnsMessages.GetHead();
2749 VerifyOrQuit(dnsMsg != nullptr);
2750 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
2751 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
2752 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
2753
2754 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2755 Log("Send a query for PTR record for `services._dns-sd` and validate the response");
2756
2757 AdvanceTime(2000);
2758
2759 sDnsMessages.Clear();
2760 SendQuery("_services._dns-sd._udp.local.", ResourceRecord::kTypePtr);
2761
2762 AdvanceTime(1000);
2763
2764 dnsMsg = sDnsMessages.GetHead();
2765 VerifyOrQuit(dnsMsg != nullptr);
2766 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
2767 dnsMsg->Validate(service, kInAnswerSection, kCheckServicesPtr);
2768
2769 for (uint16_t index = 0; index < service.mSubTypeLabelsLength; index++)
2770 {
2771 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2772 Log("Send a PTR query for sub-type `%s` and validate the response", service.mSubTypeLabels[index]);
2773
2774 fullSubServiceType.Clear();
2775 fullSubServiceType.Append("%s._sub.%s", service.mSubTypeLabels[index], fullServiceType.AsCString());
2776
2777 AdvanceTime(2000);
2778
2779 sDnsMessages.Clear();
2780 SendQuery(fullSubServiceType.AsCString(), ResourceRecord::kTypePtr);
2781
2782 AdvanceTime(1000);
2783
2784 dnsMsg = sDnsMessages.GetHead();
2785 VerifyOrQuit(dnsMsg != nullptr);
2786 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
2787 dnsMsg->ValidateSubType(service.mSubTypeLabels[index], service);
2788 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
2789 }
2790
2791 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2792 Log("Send a PTR query for non-existing sub-type and validate there is no response");
2793
2794 AdvanceTime(2000);
2795
2796 fullSubServiceType.Clear();
2797 fullSubServiceType.Append("_none._sub.%s", fullServiceType.AsCString());
2798
2799 sDnsMessages.Clear();
2800 SendQuery(fullSubServiceType.AsCString(), ResourceRecord::kTypePtr);
2801
2802 AdvanceTime(2000);
2803 VerifyOrQuit(sDnsMessages.IsEmpty());
2804
2805 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2806 Log("Register a new sub-type and validate announcements of PTR record for it");
2807
2808 service.mSubTypeLabelsLength = 4;
2809
2810 sRegCallbacks[1].Reset();
2811 sDnsMessages.Clear();
2812 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2813
2814 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2815 {
2816 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2817 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2818
2819 VerifyOrQuit(!sDnsMessages.IsEmpty());
2820 dnsMsg = sDnsMessages.GetHead();
2821 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
2822 dnsMsg->ValidateSubType(service.mSubTypeLabels[3], service);
2823 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
2824 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2825 sDnsMessages.Clear();
2826 }
2827
2828 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2829 Log("Remove a previous sub-type and validate announcements of its removal");
2830
2831 service.mSubTypeLabels++;
2832 service.mSubTypeLabelsLength = 3;
2833
2834 sRegCallbacks[1].Reset();
2835 sDnsMessages.Clear();
2836 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2837
2838 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2839 {
2840 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2841 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2842
2843 VerifyOrQuit(!sDnsMessages.IsEmpty());
2844 dnsMsg = sDnsMessages.GetHead();
2845 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
2846 dnsMsg->ValidateSubType(kSubTypes1[0], service, kGoodBye);
2847 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2848 sDnsMessages.Clear();
2849 }
2850
2851 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2852 Log("Update TTL and validate announcement of all records");
2853
2854 service.mTtl = 0;
2855
2856 sRegCallbacks[1].Reset();
2857 sDnsMessages.Clear();
2858 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2859
2860 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2861 {
2862 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2863 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2864
2865 VerifyOrQuit(!sDnsMessages.IsEmpty());
2866 dnsMsg = sDnsMessages.GetHead();
2867 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 6, /* Auth */ 0, /* Addnl */ 1);
2868 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr);
2869
2870 for (uint16_t index = 0; index < service.mSubTypeLabelsLength; index++)
2871 {
2872 dnsMsg->ValidateSubType(service.mSubTypeLabels[index], service);
2873 }
2874
2875 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2876 sDnsMessages.Clear();
2877 }
2878
2879 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2880 Log("Add and remove sub-types at the same time and check proper announcements");
2881
2882 // Registered sub-types: _r2, _vXy, _last
2883 // New sub-types list : _vxy, _r1, _r2, _zzz
2884 //
2885 // Should announce removal of `_last` and addition of
2886 // `_r1` and `_zzz`. The `_vxy` should match with `_vXy`.
2887
2888 service.mSubTypeLabels = kSubTypes2;
2889 service.mSubTypeLabelsLength = 4;
2890
2891 sRegCallbacks[1].Reset();
2892 sDnsMessages.Clear();
2893 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
2894
2895 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2896 {
2897 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2898 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
2899
2900 VerifyOrQuit(!sDnsMessages.IsEmpty());
2901 dnsMsg = sDnsMessages.GetHead();
2902 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 2);
2903
2904 dnsMsg->ValidateSubType(kSubTypes1[3], service, kGoodBye);
2905 dnsMsg->ValidateSubType(kSubTypes2[1], service);
2906 dnsMsg->ValidateSubType(kSubTypes2[3], service);
2907 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
2908
2909 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2910 sDnsMessages.Clear();
2911 }
2912
2913 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
2914 Log("Unregister the service and validate the goodbye announces for service and its sub-types");
2915
2916 sDnsMessages.Clear();
2917 SuccessOrQuit(mdns->UnregisterService(service));
2918
2919 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
2920 {
2921 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
2922
2923 VerifyOrQuit(!sDnsMessages.IsEmpty());
2924 dnsMsg = sDnsMessages.GetHead();
2925 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 7, /* Auth */ 0, /* Addnl */ 0);
2926 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
2927
2928 for (uint16_t index = 0; index < service.mSubTypeLabelsLength; index++)
2929 {
2930 dnsMsg->ValidateSubType(service.mSubTypeLabels[index], service, kGoodBye);
2931 }
2932
2933 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
2934 sDnsMessages.Clear();
2935 }
2936
2937 AdvanceTime(15000);
2938 VerifyOrQuit(sDnsMessages.IsEmpty());
2939
2940 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
2941 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
2942
2943 Log("End of test");
2944
2945 testFreeInstance(sInstance);
2946 }
2947
TestHostOrServiceAndKeyReg(void)2948 void TestHostOrServiceAndKeyReg(void)
2949 {
2950 Core *mdns = InitTest();
2951 Core::Host host;
2952 Core::Service service;
2953 Core::Key key;
2954 Ip6::Address hostAddresses[2];
2955 const DnsMessage *dnsMsg;
2956 uint16_t heapAllocations;
2957
2958 Log("-------------------------------------------------------------------------------------------");
2959 Log("TestHostOrServiceAndKeyReg");
2960
2961 AdvanceTime(1);
2962
2963 heapAllocations = sHeapAllocatedPtrs.GetLength();
2964 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
2965
2966 SuccessOrQuit(hostAddresses[0].FromString("fd00::1"));
2967 SuccessOrQuit(hostAddresses[1].FromString("fd00::2"));
2968
2969 host.mHostName = "myhost";
2970 host.mAddresses = hostAddresses;
2971 host.mAddressesLength = 2;
2972 host.mTtl = 5000;
2973
2974 key.mKeyData = kKey1;
2975 key.mKeyDataLength = sizeof(kKey1);
2976 key.mTtl = 80000;
2977
2978 service.mHostName = "myhost";
2979 service.mServiceInstance = "myservice";
2980 service.mServiceType = "_srv._udp";
2981 service.mSubTypeLabels = nullptr;
2982 service.mSubTypeLabelsLength = 0;
2983 service.mTxtData = kTxtData1;
2984 service.mTxtDataLength = sizeof(kTxtData1);
2985 service.mPort = 1234;
2986 service.mPriority = 1;
2987 service.mWeight = 2;
2988 service.mTtl = 1000;
2989
2990 // Run all test step twice, first time registering host and key,
2991 // second time registering service and key.
2992
2993 for (uint8_t iter = 0; iter < 2; iter++)
2994 {
2995 if (iter == 0)
2996 {
2997 key.mName = host.mHostName;
2998 key.mServiceType = nullptr;
2999 }
3000 else
3001 {
3002 key.mName = service.mServiceInstance;
3003 key.mServiceType = service.mServiceType;
3004 }
3005
3006 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3007 Log("Register a %s entry, check the first probe is sent", iter == 0 ? "host" : "service");
3008
3009 sDnsMessages.Clear();
3010
3011 sRegCallbacks[0].Reset();
3012
3013 if (iter == 0)
3014 {
3015 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
3016 }
3017 else
3018 {
3019 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
3020 }
3021
3022 sDnsMessages.Clear();
3023
3024 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
3025 AdvanceTime(250);
3026
3027 VerifyOrQuit(!sDnsMessages.IsEmpty());
3028 dnsMsg = sDnsMessages.GetHead();
3029
3030 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
3031
3032 if (iter == 0)
3033 {
3034 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ true);
3035 }
3036 else
3037 {
3038 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ true);
3039 }
3040
3041 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3042
3043 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3044 Log("Register a `KeyEntry` for same name, check that probes continue");
3045
3046 sRegCallbacks[1].Reset();
3047 SuccessOrQuit(mdns->RegisterKey(key, 1, HandleSuccessCallback));
3048
3049 for (uint8_t probeCount = 1; probeCount < 3; probeCount++)
3050 {
3051 sDnsMessages.Clear();
3052
3053 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
3054 VerifyOrQuit(!sRegCallbacks[1].mWasCalled);
3055
3056 AdvanceTime(250);
3057
3058 VerifyOrQuit(!sDnsMessages.IsEmpty());
3059 dnsMsg = sDnsMessages.GetHead();
3060 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 3, /* Addnl */ 0);
3061
3062 if (iter == 0)
3063 {
3064 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ false);
3065 }
3066 else
3067 {
3068 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ false);
3069 }
3070
3071 dnsMsg->ValidateAsProbeFor(key, /* aUnicastRequest */ (probeCount == 0));
3072 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3073 }
3074
3075 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3076 Log("Validate Announces for both entry and key");
3077
3078 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3079 {
3080 sDnsMessages.Clear();
3081
3082 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3083 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
3084 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
3085
3086 VerifyOrQuit(!sDnsMessages.IsEmpty());
3087 dnsMsg = sDnsMessages.GetHead();
3088
3089 if (iter == 0)
3090 {
3091 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
3092 dnsMsg->Validate(host, kInAnswerSection);
3093 }
3094 else
3095 {
3096 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 5, /* Auth */ 0, /* Addnl */ 1);
3097 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3098 }
3099
3100 dnsMsg->Validate(key, kInAnswerSection);
3101 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3102 }
3103
3104 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3105 Log("Unregister the entry and validate its goodbye announces");
3106
3107 sDnsMessages.Clear();
3108
3109 if (iter == 0)
3110 {
3111 SuccessOrQuit(mdns->UnregisterHost(host));
3112 }
3113 else
3114 {
3115 SuccessOrQuit(mdns->UnregisterService(service));
3116 }
3117
3118 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3119 {
3120 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
3121
3122 VerifyOrQuit(!sDnsMessages.IsEmpty());
3123 dnsMsg = sDnsMessages.GetHead();
3124
3125 if (iter == 0)
3126 {
3127 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
3128 dnsMsg->Validate(host, kInAnswerSection, kGoodBye);
3129 }
3130 else
3131 {
3132 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 1);
3133 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
3134 }
3135
3136 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3137 sDnsMessages.Clear();
3138 }
3139
3140 AdvanceTime(15000);
3141 VerifyOrQuit(sDnsMessages.IsEmpty());
3142
3143 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3144 Log("Register the entry again, validate its announcements");
3145
3146 sDnsMessages.Clear();
3147
3148 sRegCallbacks[2].Reset();
3149
3150 if (iter == 0)
3151 {
3152 SuccessOrQuit(mdns->RegisterHost(host, 2, HandleSuccessCallback));
3153 }
3154 else
3155 {
3156 SuccessOrQuit(mdns->RegisterService(service, 2, HandleSuccessCallback));
3157 }
3158
3159 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3160 {
3161 sDnsMessages.Clear();
3162
3163 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3164 VerifyOrQuit(sRegCallbacks[2].mWasCalled);
3165
3166 VerifyOrQuit(!sDnsMessages.IsEmpty());
3167 dnsMsg = sDnsMessages.GetHead();
3168
3169 if (iter == 0)
3170 {
3171 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
3172 dnsMsg->Validate(host, kInAnswerSection);
3173 }
3174 else
3175 {
3176 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
3177 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3178 }
3179
3180 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3181 }
3182
3183 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3184 Log("Unregister the key and validate its goodbye announcements");
3185
3186 sDnsMessages.Clear();
3187 SuccessOrQuit(mdns->UnregisterKey(key));
3188
3189 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3190 {
3191 AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000);
3192
3193 VerifyOrQuit(!sDnsMessages.IsEmpty());
3194 dnsMsg = sDnsMessages.GetHead();
3195 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
3196 dnsMsg->Validate(key, kInAnswerSection, kGoodBye);
3197 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3198 sDnsMessages.Clear();
3199 }
3200
3201 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3202 Log("Register the key again, validate its announcements");
3203
3204 sDnsMessages.Clear();
3205
3206 sRegCallbacks[3].Reset();
3207 SuccessOrQuit(mdns->RegisterKey(key, 3, HandleSuccessCallback));
3208
3209 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3210 {
3211 sDnsMessages.Clear();
3212
3213 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3214 VerifyOrQuit(sRegCallbacks[3].mWasCalled);
3215
3216 VerifyOrQuit(!sDnsMessages.IsEmpty());
3217 dnsMsg = sDnsMessages.GetHead();
3218 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
3219 dnsMsg->Validate(key, kInAnswerSection);
3220 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3221 }
3222
3223 sDnsMessages.Clear();
3224 AdvanceTime(15000);
3225 VerifyOrQuit(sDnsMessages.IsEmpty());
3226
3227 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3228 Log("Unregister key first, validate two of its goodbye announcements");
3229
3230 sDnsMessages.Clear();
3231
3232 SuccessOrQuit(mdns->UnregisterKey(key));
3233
3234 for (uint8_t anncCount = 0; anncCount < 2; anncCount++)
3235 {
3236 sDnsMessages.Clear();
3237
3238 AdvanceTime((anncCount == 0) ? 1 : (1U << (anncCount - 1)) * 1000);
3239
3240 VerifyOrQuit(!sDnsMessages.IsEmpty());
3241 dnsMsg = sDnsMessages.GetHead();
3242 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
3243 dnsMsg->Validate(key, kInAnswerSection, kGoodBye);
3244 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3245 }
3246
3247 Log("Unregister entry as well");
3248
3249 if (iter == 0)
3250 {
3251 SuccessOrQuit(mdns->UnregisterHost(host));
3252 }
3253 else
3254 {
3255 SuccessOrQuit(mdns->UnregisterService(service));
3256 }
3257
3258 AdvanceTime(15000);
3259
3260 for (uint16_t anncCount = 0; anncCount < 4; anncCount++)
3261 {
3262 dnsMsg = dnsMsg->GetNext();
3263 VerifyOrQuit(dnsMsg != nullptr);
3264
3265 if (anncCount == 2)
3266 {
3267 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
3268 dnsMsg->Validate(key, kInAnswerSection, kGoodBye);
3269 }
3270 else if (iter == 0)
3271 {
3272 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 0);
3273 dnsMsg->Validate(host, kInAnswerSection, kGoodBye);
3274 }
3275 else
3276 {
3277 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 3, /* Auth */ 0, /* Addnl */ 0);
3278 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
3279 }
3280 }
3281
3282 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3283
3284 sDnsMessages.Clear();
3285 AdvanceTime(15000);
3286 VerifyOrQuit(sDnsMessages.IsEmpty());
3287 }
3288
3289 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
3290 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
3291
3292 Log("End of test");
3293
3294 testFreeInstance(sInstance);
3295 }
3296
3297 //---------------------------------------------------------------------------------------------------------------------
3298
TestQuery(void)3299 void TestQuery(void)
3300 {
3301 static const char *const kSubTypes[] = {"_s", "_r"};
3302
3303 Core *mdns = InitTest();
3304 Core::Host host1;
3305 Core::Host host2;
3306 Core::Service service1;
3307 Core::Service service2;
3308 Core::Service service3;
3309 Core::Key key1;
3310 Core::Key key2;
3311 Ip6::Address host1Addresses[3];
3312 Ip6::Address host2Addresses[2];
3313 const DnsMessage *dnsMsg;
3314 uint16_t heapAllocations;
3315 DnsNameString host1FullName;
3316 DnsNameString host2FullName;
3317 DnsNameString service1FullName;
3318 DnsNameString service2FullName;
3319 DnsNameString service3FullName;
3320 KnownAnswer knownAnswers[2];
3321
3322 Log("-------------------------------------------------------------------------------------------");
3323 Log("TestQuery");
3324
3325 AdvanceTime(1);
3326
3327 heapAllocations = sHeapAllocatedPtrs.GetLength();
3328 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
3329
3330 SuccessOrQuit(host1Addresses[0].FromString("fd00::1:aaaa"));
3331 SuccessOrQuit(host1Addresses[1].FromString("fd00::1:bbbb"));
3332 SuccessOrQuit(host1Addresses[2].FromString("fd00::1:cccc"));
3333 host1.mHostName = "host1";
3334 host1.mAddresses = host1Addresses;
3335 host1.mAddressesLength = 3;
3336 host1.mTtl = 1500;
3337 host1FullName.Append("%s.local.", host1.mHostName);
3338
3339 SuccessOrQuit(host2Addresses[0].FromString("fd00::2:eeee"));
3340 SuccessOrQuit(host2Addresses[1].FromString("fd00::2:ffff"));
3341 host2.mHostName = "host2";
3342 host2.mAddresses = host2Addresses;
3343 host2.mAddressesLength = 2;
3344 host2.mTtl = 1500;
3345 host2FullName.Append("%s.local.", host2.mHostName);
3346
3347 service1.mHostName = host1.mHostName;
3348 service1.mServiceInstance = "srv1";
3349 service1.mServiceType = "_srv._udp";
3350 service1.mSubTypeLabels = kSubTypes;
3351 service1.mSubTypeLabelsLength = 2;
3352 service1.mTxtData = kTxtData1;
3353 service1.mTxtDataLength = sizeof(kTxtData1);
3354 service1.mPort = 1111;
3355 service1.mPriority = 0;
3356 service1.mWeight = 0;
3357 service1.mTtl = 1500;
3358 service1FullName.Append("%s.%s.local.", service1.mServiceInstance, service1.mServiceType);
3359
3360 service2.mHostName = host1.mHostName;
3361 service2.mServiceInstance = "srv2";
3362 service2.mServiceType = "_tst._tcp";
3363 service2.mSubTypeLabels = nullptr;
3364 service2.mSubTypeLabelsLength = 0;
3365 service2.mTxtData = nullptr;
3366 service2.mTxtDataLength = 0;
3367 service2.mPort = 2222;
3368 service2.mPriority = 2;
3369 service2.mWeight = 2;
3370 service2.mTtl = 1500;
3371 service2FullName.Append("%s.%s.local.", service2.mServiceInstance, service2.mServiceType);
3372
3373 service3.mHostName = host2.mHostName;
3374 service3.mServiceInstance = "srv3";
3375 service3.mServiceType = "_srv._udp";
3376 service3.mSubTypeLabels = kSubTypes;
3377 service3.mSubTypeLabelsLength = 1;
3378 service3.mTxtData = kTxtData2;
3379 service3.mTxtDataLength = sizeof(kTxtData2);
3380 service3.mPort = 3333;
3381 service3.mPriority = 3;
3382 service3.mWeight = 3;
3383 service3.mTtl = 1500;
3384 service3FullName.Append("%s.%s.local.", service3.mServiceInstance, service3.mServiceType);
3385
3386 key1.mName = host2.mHostName;
3387 key1.mServiceType = nullptr;
3388 key1.mKeyData = kKey1;
3389 key1.mKeyDataLength = sizeof(kKey1);
3390 key1.mTtl = 8000;
3391
3392 key2.mName = service3.mServiceInstance;
3393 key2.mServiceType = service3.mServiceType;
3394 key2.mKeyData = kKey1;
3395 key2.mKeyDataLength = sizeof(kKey1);
3396 key2.mTtl = 8000;
3397
3398 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3399 Log("Register 2 hosts and 3 services and 2 keys");
3400
3401 sDnsMessages.Clear();
3402
3403 for (RegCallback ®Callbck : sRegCallbacks)
3404 {
3405 regCallbck.Reset();
3406 }
3407
3408 SuccessOrQuit(mdns->RegisterHost(host1, 0, HandleSuccessCallback));
3409 SuccessOrQuit(mdns->RegisterHost(host2, 1, HandleSuccessCallback));
3410 SuccessOrQuit(mdns->RegisterService(service1, 2, HandleSuccessCallback));
3411 SuccessOrQuit(mdns->RegisterService(service2, 3, HandleSuccessCallback));
3412 SuccessOrQuit(mdns->RegisterService(service3, 4, HandleSuccessCallback));
3413 SuccessOrQuit(mdns->RegisterKey(key1, 5, HandleSuccessCallback));
3414 SuccessOrQuit(mdns->RegisterKey(key2, 6, HandleSuccessCallback));
3415
3416 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3417 Log("Validate probes for all entries");
3418
3419 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
3420 {
3421 sDnsMessages.Clear();
3422 AdvanceTime(250);
3423
3424 VerifyOrQuit(!sDnsMessages.IsEmpty());
3425 dnsMsg = sDnsMessages.GetHead();
3426
3427 for (uint16_t index = 0; index < 7; index++)
3428 {
3429 VerifyOrQuit(!sRegCallbacks[index].mWasCalled);
3430 }
3431
3432 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 5, /* Ans */ 0, /* Auth */ 13, /* Addnl */ 0);
3433
3434 dnsMsg->ValidateAsProbeFor(host1, /* aUnicastRequest */ (probeCount == 0));
3435 dnsMsg->ValidateAsProbeFor(host2, /* aUnicastRequest */ (probeCount == 0));
3436 dnsMsg->ValidateAsProbeFor(service1, /* aUnicastRequest */ (probeCount == 0));
3437 dnsMsg->ValidateAsProbeFor(service2, /* aUnicastRequest */ (probeCount == 0));
3438 dnsMsg->ValidateAsProbeFor(service3, /* aUnicastRequest */ (probeCount == 0));
3439 dnsMsg->ValidateAsProbeFor(key1, /* aUnicastRequest */ (probeCount == 0));
3440 dnsMsg->ValidateAsProbeFor(key2, /* aUnicastRequest */ (probeCount == 0));
3441
3442 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3443 }
3444
3445 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3446 Log("Validate announcements for all entries");
3447
3448 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3449 {
3450 sDnsMessages.Clear();
3451
3452 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3453
3454 for (uint16_t index = 0; index < 7; index++)
3455 {
3456 VerifyOrQuit(sRegCallbacks[index].mWasCalled);
3457 }
3458
3459 VerifyOrQuit(!sDnsMessages.IsEmpty());
3460 dnsMsg = sDnsMessages.GetHead();
3461
3462 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 21, /* Auth */ 0, /* Addnl */ 5);
3463
3464 dnsMsg->Validate(host1, kInAnswerSection);
3465 dnsMsg->Validate(host2, kInAnswerSection);
3466 dnsMsg->Validate(service1, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3467 dnsMsg->Validate(service2, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3468 dnsMsg->Validate(service2, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3469 dnsMsg->Validate(key1, kInAnswerSection);
3470 dnsMsg->Validate(key2, kInAnswerSection);
3471
3472 for (uint16_t index = 0; index < service1.mSubTypeLabelsLength; index++)
3473 {
3474 dnsMsg->ValidateSubType(service1.mSubTypeLabels[index], service1);
3475 }
3476
3477 for (uint16_t index = 0; index < service3.mSubTypeLabelsLength; index++)
3478 {
3479 dnsMsg->ValidateSubType(service3.mSubTypeLabels[index], service3);
3480 }
3481
3482 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3483 }
3484
3485 sDnsMessages.Clear();
3486 AdvanceTime(15000);
3487 VerifyOrQuit(sDnsMessages.IsEmpty());
3488
3489 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3490 Log("Send a PTR query (browse) for `_srv._udp` and validate two answers and additional data");
3491
3492 AdvanceTime(2000);
3493 sDnsMessages.Clear();
3494
3495 SendQuery("_srv._udp.local.", ResourceRecord::kTypePtr);
3496
3497 AdvanceTime(200);
3498
3499 dnsMsg = sDnsMessages.GetHead();
3500 VerifyOrQuit(dnsMsg != nullptr);
3501 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3502
3503 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 9);
3504
3505 dnsMsg->Validate(service1, kInAnswerSection, kCheckPtr);
3506 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3507 dnsMsg->Validate(service1, kInAdditionalSection, kCheckSrv | kCheckTxt);
3508 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3509 dnsMsg->Validate(host1, kInAdditionalSection);
3510 dnsMsg->Validate(host2, kInAdditionalSection);
3511
3512 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3513 Log("Resend the same query but request a unicast response, validate the response");
3514
3515 sDnsMessages.Clear();
3516 SendQuery("_srv._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassInternet | kClassQueryUnicastFlag);
3517
3518 AdvanceTime(200);
3519
3520 dnsMsg = sDnsMessages.GetHead();
3521 VerifyOrQuit(dnsMsg != nullptr);
3522 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3523
3524 dnsMsg->ValidateHeader(kUnicastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 9);
3525
3526 dnsMsg->Validate(service1, kInAnswerSection, kCheckPtr);
3527 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3528 dnsMsg->Validate(service1, kInAdditionalSection, kCheckSrv | kCheckTxt);
3529 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3530 dnsMsg->Validate(host1, kInAdditionalSection);
3531 dnsMsg->Validate(host2, kInAdditionalSection);
3532
3533 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3534 Log("Resend the same multicast query and validate that response is not emitted (rate limit)");
3535
3536 sDnsMessages.Clear();
3537 SendQuery("_srv._udp.local.", ResourceRecord::kTypePtr);
3538
3539 AdvanceTime(1000);
3540 VerifyOrQuit(sDnsMessages.IsEmpty());
3541
3542 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3543 Log("Wait for > 1 second and resend the query and validate that now a response is emitted");
3544
3545 SendQuery("_srv._udp.local.", ResourceRecord::kTypePtr);
3546
3547 AdvanceTime(200);
3548
3549 dnsMsg = sDnsMessages.GetHead();
3550 VerifyOrQuit(dnsMsg != nullptr);
3551 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3552
3553 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 9);
3554
3555 dnsMsg->Validate(service1, kInAnswerSection, kCheckPtr);
3556 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3557 dnsMsg->Validate(service1, kInAdditionalSection, kCheckSrv | kCheckTxt);
3558 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3559 dnsMsg->Validate(host1, kInAdditionalSection);
3560 dnsMsg->Validate(host2, kInAdditionalSection);
3561
3562 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3563 Log("Browse for sub-type `_s._sub._srv._udp` and validate two answers");
3564
3565 sDnsMessages.Clear();
3566 SendQuery("_s._sub._srv._udp.local.", ResourceRecord::kTypePtr);
3567
3568 AdvanceTime(200);
3569
3570 dnsMsg = sDnsMessages.GetHead();
3571 VerifyOrQuit(dnsMsg != nullptr);
3572 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3573
3574 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 9);
3575
3576 dnsMsg->ValidateSubType("_s", service1);
3577 dnsMsg->ValidateSubType("_s", service3);
3578 dnsMsg->Validate(service1, kInAdditionalSection, kCheckSrv | kCheckTxt);
3579 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3580 dnsMsg->Validate(host1, kInAdditionalSection);
3581 dnsMsg->Validate(host2, kInAdditionalSection);
3582
3583 // Send same query again and make sure it is ignored (rate limit).
3584
3585 sDnsMessages.Clear();
3586 SendQuery("_s._sub._srv._udp.local.", ResourceRecord::kTypePtr);
3587
3588 AdvanceTime(1000);
3589 VerifyOrQuit(sDnsMessages.IsEmpty());
3590
3591 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3592 Log("Validate that query with `ANY class` instead of `IN class` is responded");
3593
3594 AdvanceTime(2000);
3595
3596 sDnsMessages.Clear();
3597 SendQuery("_r._sub._srv._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassAny);
3598
3599 AdvanceTime(200);
3600
3601 dnsMsg = sDnsMessages.GetHead();
3602 VerifyOrQuit(dnsMsg != nullptr);
3603 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3604
3605 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 5);
3606 dnsMsg->ValidateSubType("_r", service1);
3607 dnsMsg->Validate(service1, kInAdditionalSection, kCheckSrv | kCheckTxt);
3608 dnsMsg->Validate(host1, kInAdditionalSection);
3609
3610 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3611 Log("Validate that query with other `class` is ignored");
3612
3613 AdvanceTime(2000);
3614
3615 sDnsMessages.Clear();
3616 SendQuery("_r._sub._srv._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassNone);
3617
3618 AdvanceTime(2000);
3619 VerifyOrQuit(sDnsMessages.IsEmpty());
3620
3621 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3622 Log("Validate that query for non-registered name is ignored");
3623
3624 sDnsMessages.Clear();
3625 SendQuery("_u._sub._srv._udp.local.", ResourceRecord::kTypeAny);
3626 SendQuery("host3.local.", ResourceRecord::kTypeAny);
3627
3628 AdvanceTime(2000);
3629 VerifyOrQuit(sDnsMessages.IsEmpty());
3630
3631 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3632 Log("Query for SRV for `srv1._srv._udp` and validate answer and additional data");
3633
3634 sDnsMessages.Clear();
3635
3636 SendQuery("srv1._srv._udp.local.", ResourceRecord::kTypeSrv);
3637
3638 AdvanceTime(200);
3639
3640 dnsMsg = sDnsMessages.GetHead();
3641 VerifyOrQuit(dnsMsg != nullptr);
3642 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3643
3644 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 4);
3645
3646 dnsMsg->Validate(service1, kInAnswerSection, kCheckSrv);
3647 dnsMsg->Validate(host1, kInAdditionalSection);
3648
3649 //--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
3650 // Query with multiple questions
3651
3652 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3653 Log("Send a query with two questions (SRV for service1 and AAAA for host1). Validate response");
3654
3655 AdvanceTime(2000);
3656
3657 sDnsMessages.Clear();
3658 SendQueryForTwo("srv1._srv._udp.local.", ResourceRecord::kTypeSrv, "host1.local.", ResourceRecord::kTypeAaaa);
3659
3660 AdvanceTime(200);
3661
3662 dnsMsg = sDnsMessages.GetHead();
3663 VerifyOrQuit(dnsMsg != nullptr);
3664 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3665
3666 // Since AAAA record are already present in Answer they should not be appended
3667 // in Additional anymore (for the SRV query).
3668
3669 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 2);
3670
3671 dnsMsg->Validate(service1, kInAnswerSection, kCheckSrv);
3672 dnsMsg->Validate(host1, kInAnswerSection);
3673
3674 //--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
3675 // Known-answer suppression
3676
3677 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3678 Log("Send a PTR query for `_srv._udp` and include `srv1` as known-answer and validate response");
3679
3680 knownAnswers[0].mPtrAnswer = "srv1._srv._udp.local.";
3681 knownAnswers[0].mTtl = 1500;
3682
3683 AdvanceTime(1000);
3684
3685 sDnsMessages.Clear();
3686 SendPtrQueryWithKnownAnswers("_srv._udp.local.", knownAnswers, 1);
3687
3688 AdvanceTime(200);
3689
3690 dnsMsg = sDnsMessages.GetHead();
3691 VerifyOrQuit(dnsMsg != nullptr);
3692 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3693
3694 // Response should include `service3` only
3695
3696 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 4);
3697 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3698 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3699 dnsMsg->Validate(host2, kInAdditionalSection);
3700
3701 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3702 Log("Send a PTR query again with both services as known-answer, validate no response is emitted");
3703
3704 knownAnswers[1].mPtrAnswer = "srv3._srv._udp.local.";
3705 knownAnswers[1].mTtl = 1500;
3706
3707 AdvanceTime(1000);
3708
3709 sDnsMessages.Clear();
3710 SendPtrQueryWithKnownAnswers("_srv._udp.local.", knownAnswers, 2);
3711
3712 AdvanceTime(2000);
3713 VerifyOrQuit(sDnsMessages.IsEmpty());
3714
3715 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3716 Log("Send a PTR query for `_srv._udp` and include `srv1` as known-answer and validate response");
3717
3718 knownAnswers[0].mPtrAnswer = "srv1._srv._udp.local.";
3719 knownAnswers[0].mTtl = 1500;
3720
3721 AdvanceTime(1000);
3722
3723 sDnsMessages.Clear();
3724 SendPtrQueryWithKnownAnswers("_srv._udp.local.", knownAnswers, 1);
3725
3726 AdvanceTime(200);
3727
3728 dnsMsg = sDnsMessages.GetHead();
3729 VerifyOrQuit(dnsMsg != nullptr);
3730 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3731
3732 // Response should include `service3` only
3733
3734 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 4);
3735 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3736 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3737 dnsMsg->Validate(host2, kInAdditionalSection);
3738
3739 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3740 Log("Change the TTL for known-answer to less than half of record TTL and validate response");
3741
3742 knownAnswers[1].mTtl = 1500 / 2 - 1;
3743
3744 AdvanceTime(1000);
3745
3746 sDnsMessages.Clear();
3747 SendPtrQueryWithKnownAnswers("_srv._udp.local.", knownAnswers, 2);
3748
3749 AdvanceTime(200);
3750
3751 dnsMsg = sDnsMessages.GetHead();
3752 VerifyOrQuit(dnsMsg != nullptr);
3753 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3754
3755 // Response should include `service3` only since anwer TTL
3756 // is less than half of registered TTL
3757
3758 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 4);
3759 dnsMsg->Validate(service3, kInAnswerSection, kCheckPtr);
3760 dnsMsg->Validate(service3, kInAdditionalSection, kCheckSrv | kCheckTxt);
3761 dnsMsg->Validate(host2, kInAdditionalSection);
3762
3763 //--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
3764 // Query during Goodbye announcements
3765
3766 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3767 Log("Unregister `service1` and wait for its two announcements and validate them");
3768
3769 sDnsMessages.Clear();
3770 SuccessOrQuit(mdns->UnregisterService(service1));
3771
3772 for (uint8_t anncCount = 0; anncCount < kNumAnnounces - 1; anncCount++)
3773 {
3774 sDnsMessages.Clear();
3775
3776 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3777
3778 dnsMsg = sDnsMessages.GetHead();
3779 VerifyOrQuit(dnsMsg != nullptr);
3780 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3781
3782 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 5, /* Auth */ 0, /* Addnl */ 0);
3783 dnsMsg->Validate(service1, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
3784
3785 for (uint16_t index = 0; index < service1.mSubTypeLabelsLength; index++)
3786 {
3787 dnsMsg->ValidateSubType(service1.mSubTypeLabels[index], service1, kGoodBye);
3788 }
3789 }
3790
3791 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3792 Log("Send a query for removed `service1` before its final announcement, validate no response");
3793
3794 sDnsMessages.Clear();
3795
3796 AdvanceTime(1100);
3797 SendQuery("srv1._srv._udp.local.", ResourceRecord::kTypeSrv);
3798
3799 AdvanceTime(200);
3800
3801 VerifyOrQuit(sDnsMessages.IsEmpty());
3802
3803 // Wait for final announcement and validate it
3804
3805 AdvanceTime(2000);
3806
3807 dnsMsg = sDnsMessages.GetHead();
3808 VerifyOrQuit(dnsMsg != nullptr);
3809 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3810
3811 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 5, /* Auth */ 0, /* Addnl */ 0);
3812 dnsMsg->Validate(service1, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr, kGoodBye);
3813
3814 for (uint16_t index = 0; index < service1.mSubTypeLabelsLength; index++)
3815 {
3816 dnsMsg->ValidateSubType(service1.mSubTypeLabels[index], service1, kGoodBye);
3817 }
3818
3819 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
3820 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
3821
3822 Log("End of test");
3823
3824 testFreeInstance(sInstance);
3825 }
3826
3827 //----------------------------------------------------------------------------------------------------------------------
3828
TestMultiPacket(void)3829 void TestMultiPacket(void)
3830 {
3831 static const char *const kSubTypes[] = {"_s1", "_r2", "vxy"};
3832
3833 Core *mdns = InitTest();
3834 Core::Service service;
3835 const DnsMessage *dnsMsg;
3836 uint16_t heapAllocations;
3837 DnsNameString fullServiceName;
3838 DnsNameString fullServiceType;
3839 KnownAnswer knownAnswers[2];
3840
3841 Log("-------------------------------------------------------------------------------------------");
3842 Log("TestMultiPacket");
3843
3844 AdvanceTime(1);
3845
3846 heapAllocations = sHeapAllocatedPtrs.GetLength();
3847 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
3848
3849 service.mHostName = "myhost";
3850 service.mServiceInstance = "mysrv";
3851 service.mServiceType = "_tst._udp";
3852 service.mSubTypeLabels = kSubTypes;
3853 service.mSubTypeLabelsLength = 3;
3854 service.mTxtData = kTxtData1;
3855 service.mTxtDataLength = sizeof(kTxtData1);
3856 service.mPort = 2222;
3857 service.mPriority = 3;
3858 service.mWeight = 4;
3859 service.mTtl = 2000;
3860
3861 fullServiceName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
3862 fullServiceType.Append("%s.local.", service.mServiceType);
3863
3864 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3865 Log("Register a `ServiceEntry` with sub-types, check probes and announcements");
3866
3867 sDnsMessages.Clear();
3868
3869 sRegCallbacks[0].Reset();
3870 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
3871
3872 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
3873 {
3874 sDnsMessages.Clear();
3875
3876 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
3877 AdvanceTime(250);
3878
3879 VerifyOrQuit(!sDnsMessages.IsEmpty());
3880 dnsMsg = sDnsMessages.GetHead();
3881 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
3882 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
3883 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3884 }
3885
3886 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
3887 {
3888 sDnsMessages.Clear();
3889
3890 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
3891 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
3892
3893 VerifyOrQuit(!sDnsMessages.IsEmpty());
3894 dnsMsg = sDnsMessages.GetHead();
3895 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 7, /* Auth */ 0, /* Addnl */ 1);
3896 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
3897
3898 for (uint16_t index = 0; index < service.mSubTypeLabelsLength; index++)
3899 {
3900 dnsMsg->ValidateSubType(service.mSubTypeLabels[index], service);
3901 }
3902
3903 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
3904 }
3905
3906 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3907 Log("Send a query for PTR record for service type and validate the response");
3908
3909 AdvanceTime(2000);
3910
3911 sDnsMessages.Clear();
3912 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr);
3913
3914 AdvanceTime(1000);
3915
3916 dnsMsg = sDnsMessages.GetHead();
3917 VerifyOrQuit(dnsMsg != nullptr);
3918 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
3919 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
3920 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
3921
3922 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3923 Log("Send a PTR query again but mark it as truncated");
3924
3925 AdvanceTime(2000);
3926
3927 sDnsMessages.Clear();
3928 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
3929 /* aTruncated */ true);
3930
3931 Log("Since message is marked as `truncated`, mDNS should wait at least 400 msec");
3932
3933 AdvanceTime(400);
3934 VerifyOrQuit(sDnsMessages.IsEmpty());
3935
3936 AdvanceTime(2000);
3937 dnsMsg = sDnsMessages.GetHead();
3938 VerifyOrQuit(dnsMsg != nullptr);
3939 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
3940 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
3941 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
3942
3943 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3944 Log("Send a PTR query again as truncated followed-up by a non-matching answer");
3945
3946 AdvanceTime(2000);
3947
3948 sDnsMessages.Clear();
3949 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
3950 /* aTruncated */ true);
3951 AdvanceTime(10);
3952
3953 knownAnswers[0].mPtrAnswer = "other._tst._udp.local.";
3954 knownAnswers[0].mTtl = 1500;
3955
3956 SendEmtryPtrQueryWithKnownAnswers(fullServiceType.AsCString(), knownAnswers, 1);
3957
3958 AdvanceTime(1000);
3959 dnsMsg = sDnsMessages.GetHead();
3960 VerifyOrQuit(dnsMsg != nullptr);
3961 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 2);
3962 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
3963 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
3964
3965 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3966 Log("Send a PTR query again as truncated now followed-up by matching known-answer");
3967
3968 AdvanceTime(2000);
3969
3970 sDnsMessages.Clear();
3971 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
3972 /* aTruncated */ true);
3973 AdvanceTime(10);
3974
3975 knownAnswers[1].mPtrAnswer = "mysrv._tst._udp.local.";
3976 knownAnswers[1].mTtl = 1500;
3977
3978 SendEmtryPtrQueryWithKnownAnswers(fullServiceType.AsCString(), knownAnswers, 2);
3979
3980 Log("We expect no response since the followed-up message contains a matching known-answer");
3981 AdvanceTime(5000);
3982 VerifyOrQuit(sDnsMessages.IsEmpty());
3983
3984 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
3985 Log("Send a truncated query for PTR record for `services._dns-sd`");
3986
3987 AdvanceTime(2000);
3988
3989 sDnsMessages.Clear();
3990 SendQuery("_services._dns-sd._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
3991 /* aTruncated */ true);
3992
3993 Log("Response should be sent after longer wait time");
3994 AdvanceTime(1000);
3995
3996 dnsMsg = sDnsMessages.GetHead();
3997 VerifyOrQuit(dnsMsg != nullptr);
3998 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
3999 dnsMsg->Validate(service, kInAnswerSection, kCheckServicesPtr);
4000
4001 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4002 Log("Send a truncated query for PTR record for `services._dns-sd` folloed by known-aswer");
4003
4004 AdvanceTime(2000);
4005
4006 sDnsMessages.Clear();
4007 SendQuery("_services._dns-sd._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
4008 /* aTruncated */ true);
4009
4010 AdvanceTime(20);
4011 knownAnswers[0].mPtrAnswer = "_other._udp.local.";
4012 knownAnswers[0].mTtl = 4500;
4013
4014 SendEmtryPtrQueryWithKnownAnswers("_services._dns-sd._udp.local.", knownAnswers, 1);
4015
4016 Log("Response should be sent again due to answer not matching");
4017 AdvanceTime(1000);
4018
4019 dnsMsg = sDnsMessages.GetHead();
4020 VerifyOrQuit(dnsMsg != nullptr);
4021 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
4022 dnsMsg->Validate(service, kInAnswerSection, kCheckServicesPtr);
4023
4024 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4025 Log("Send the same truncated query again but follow-up with a matching known-answer message");
4026
4027 AdvanceTime(2000);
4028
4029 sDnsMessages.Clear();
4030 SendQuery("_services._dns-sd._udp.local.", ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
4031 /* aTruncated */ true);
4032
4033 AdvanceTime(20);
4034 knownAnswers[1].mPtrAnswer = "_tst._udp.local.";
4035 knownAnswers[1].mTtl = 4500;
4036
4037 SendEmtryPtrQueryWithKnownAnswers("_services._dns-sd._udp.local.", knownAnswers, 2);
4038
4039 Log("We expect no response since the followed-up message contains a matching known-answer");
4040 AdvanceTime(5000);
4041 VerifyOrQuit(sDnsMessages.IsEmpty());
4042
4043 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4044 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4045
4046 Log("End of test");
4047
4048 testFreeInstance(sInstance);
4049 }
4050
TestResponseAggregation(void)4051 void TestResponseAggregation(void)
4052 {
4053 Core *mdns = InitTest();
4054 Core::Service tcpService;
4055 Core::Service udpService;
4056 const DnsMessage *dnsMsg;
4057 uint16_t heapAllocations;
4058 DnsNameString fullTcpServiceName;
4059 DnsNameString fullTcpServiceType;
4060 DnsNameString fullUdpServiceName;
4061 DnsNameString fullUdpServiceType;
4062
4063 Log("-------------------------------------------------------------------------------------------");
4064 Log("TestResponseAggregation");
4065
4066 AdvanceTime(1);
4067
4068 heapAllocations = sHeapAllocatedPtrs.GetLength();
4069 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
4070
4071 tcpService.mHostName = "host";
4072 tcpService.mServiceInstance = "srv1";
4073 tcpService.mServiceType = "_matter._tcp";
4074 tcpService.mSubTypeLabels = nullptr;
4075 tcpService.mSubTypeLabelsLength = 0;
4076 tcpService.mTxtData = kTxtData1;
4077 tcpService.mTxtDataLength = sizeof(kTxtData1);
4078 tcpService.mPort = 1111;
4079 tcpService.mPriority = 1;
4080 tcpService.mWeight = 2;
4081 tcpService.mTtl = 4500;
4082
4083 udpService.mHostName = "host";
4084 udpService.mServiceInstance = "srv2";
4085 udpService.mServiceType = "_srv._udp";
4086 udpService.mSubTypeLabels = nullptr;
4087 udpService.mSubTypeLabelsLength = 0;
4088 udpService.mTxtData = kTxtData2;
4089 udpService.mTxtDataLength = sizeof(kTxtData2);
4090 udpService.mPort = 2222;
4091 udpService.mPriority = 6;
4092 udpService.mWeight = 2;
4093 udpService.mTtl = 4500;
4094
4095 fullTcpServiceName.Append("%s.%s.local.", tcpService.mServiceInstance, tcpService.mServiceType);
4096 fullTcpServiceType.Append("%s.local.", tcpService.mServiceType);
4097
4098 fullUdpServiceName.Append("%s.%s.local.", udpService.mServiceInstance, udpService.mServiceType);
4099 fullUdpServiceType.Append("%s.local.", udpService.mServiceType);
4100
4101 Log("-------------------------------------------------------------------------------------------");
4102 Log("Register a first `ServiceEntry`, check probes and announcements");
4103
4104 sDnsMessages.Clear();
4105
4106 sRegCallbacks[0].Reset();
4107 SuccessOrQuit(mdns->RegisterService(tcpService, 0, HandleSuccessCallback));
4108
4109 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4110 {
4111 sDnsMessages.Clear();
4112
4113 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4114 AdvanceTime(250);
4115
4116 VerifyOrQuit(!sDnsMessages.IsEmpty());
4117 dnsMsg = sDnsMessages.GetHead();
4118 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4119 dnsMsg->ValidateAsProbeFor(tcpService, /* aUnicastRequest */ (probeCount == 0));
4120 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4121 }
4122
4123 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4124 {
4125 sDnsMessages.Clear();
4126
4127 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4128 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4129
4130 VerifyOrQuit(!sDnsMessages.IsEmpty());
4131 dnsMsg = sDnsMessages.GetHead();
4132 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
4133 dnsMsg->Validate(tcpService, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
4134
4135 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4136 }
4137
4138 Log("-------------------------------------------------------------------------------------------");
4139 Log("Register a second `ServiceEntry`, check probes and announcements");
4140
4141 sDnsMessages.Clear();
4142
4143 sRegCallbacks[0].Reset();
4144 SuccessOrQuit(mdns->RegisterService(udpService, 0, HandleSuccessCallback));
4145
4146 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4147 {
4148 sDnsMessages.Clear();
4149
4150 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4151 AdvanceTime(250);
4152
4153 VerifyOrQuit(!sDnsMessages.IsEmpty());
4154 dnsMsg = sDnsMessages.GetHead();
4155 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4156 dnsMsg->ValidateAsProbeFor(udpService, /* aUnicastRequest */ (probeCount == 0));
4157 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4158 }
4159
4160 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4161 {
4162 sDnsMessages.Clear();
4163
4164 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4165 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4166
4167 VerifyOrQuit(!sDnsMessages.IsEmpty());
4168 dnsMsg = sDnsMessages.GetHead();
4169 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
4170 dnsMsg->Validate(udpService, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
4171 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4172 }
4173
4174 Log("-------------------------------------------------------------------------------------------");
4175 Log("Send two PTR queries back to back and validate the response is aggregated");
4176
4177 AdvanceTime(2000);
4178
4179 sDnsMessages.Clear();
4180 SendQuery(fullTcpServiceType.AsCString(), ResourceRecord::kTypePtr);
4181 AdvanceTime(5);
4182 SendQuery(fullUdpServiceType.AsCString(), ResourceRecord::kTypePtr);
4183
4184 AdvanceTime(1000);
4185
4186 dnsMsg = sDnsMessages.GetHead();
4187 VerifyOrQuit(dnsMsg != nullptr);
4188 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 4);
4189 dnsMsg->Validate(tcpService, kInAnswerSection, kCheckPtr);
4190 dnsMsg->Validate(tcpService, kInAdditionalSection, kCheckSrv | kCheckTxt);
4191 dnsMsg->Validate(udpService, kInAnswerSection, kCheckPtr);
4192 dnsMsg->Validate(udpService, kInAdditionalSection, kCheckSrv | kCheckTxt);
4193 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4194
4195 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4196 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4197
4198 Log("End of test");
4199
4200 testFreeInstance(sInstance);
4201 }
4202
4203 //---------------------------------------------------------------------------------------------------------------------
4204
TestQuestionUnicastDisallowed(void)4205 void TestQuestionUnicastDisallowed(void)
4206 {
4207 Core *mdns = InitTest();
4208 Core::Host host;
4209 Ip6::Address hostAddresses[1];
4210 const DnsMessage *dnsMsg;
4211 uint16_t heapAllocations;
4212 DnsNameString hostFullName;
4213
4214 Log("-------------------------------------------------------------------------------------------");
4215 Log("TestQuestionUnicastDisallowed");
4216
4217 AdvanceTime(1);
4218
4219 heapAllocations = sHeapAllocatedPtrs.GetLength();
4220 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
4221
4222 SuccessOrQuit(hostAddresses[0].FromString("fd00::1234"));
4223
4224 host.mHostName = "myhost";
4225 host.mAddresses = hostAddresses;
4226 host.mAddressesLength = 1;
4227 host.mTtl = 1500;
4228
4229 mdns->SetQuestionUnicastAllowed(false);
4230 VerifyOrQuit(!mdns->IsQuestionUnicastAllowed());
4231
4232 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4233 Log("Register a `HostEntry`, check probes and announcements");
4234
4235 sDnsMessages.Clear();
4236
4237 sRegCallbacks[0].Reset();
4238 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
4239
4240 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4241 {
4242 sDnsMessages.Clear();
4243
4244 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4245 AdvanceTime(250);
4246
4247 VerifyOrQuit(!sDnsMessages.IsEmpty());
4248 dnsMsg = sDnsMessages.GetHead();
4249 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 1, /* Addnl */ 0);
4250 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ false);
4251 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4252 }
4253
4254 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4255 {
4256 sDnsMessages.Clear();
4257
4258 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4259 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4260
4261 VerifyOrQuit(!sDnsMessages.IsEmpty());
4262 dnsMsg = sDnsMessages.GetHead();
4263 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
4264 dnsMsg->Validate(host, kInAnswerSection);
4265 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4266 }
4267
4268 sDnsMessages.Clear();
4269 AdvanceTime(15000);
4270 VerifyOrQuit(sDnsMessages.IsEmpty());
4271
4272 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4273 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4274
4275 Log("End of test");
4276
4277 testFreeInstance(sInstance);
4278 }
4279
4280 //---------------------------------------------------------------------------------------------------------------------
4281
TestTxMessageSizeLimit(void)4282 void TestTxMessageSizeLimit(void)
4283 {
4284 Core *mdns = InitTest();
4285 Core::Host host;
4286 Core::Service service;
4287 Core::Key hostKey;
4288 Core::Key serviceKey;
4289 Ip6::Address hostAddresses[3];
4290 uint8_t keyData[300];
4291 const DnsMessage *dnsMsg;
4292 uint16_t heapAllocations;
4293 DnsNameString hostFullName;
4294 DnsNameString serviceFullName;
4295
4296 memset(keyData, 1, sizeof(keyData));
4297
4298 Log("-------------------------------------------------------------------------------------------");
4299 Log("TestTxMessageSizeLimit");
4300
4301 AdvanceTime(1);
4302
4303 heapAllocations = sHeapAllocatedPtrs.GetLength();
4304 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
4305
4306 SuccessOrQuit(hostAddresses[0].FromString("fd00::1:aaaa"));
4307 SuccessOrQuit(hostAddresses[1].FromString("fd00::1:bbbb"));
4308 SuccessOrQuit(hostAddresses[2].FromString("fd00::1:cccc"));
4309 host.mHostName = "myhost";
4310 host.mAddresses = hostAddresses;
4311 host.mAddressesLength = 3;
4312 host.mTtl = 1500;
4313 hostFullName.Append("%s.local.", host.mHostName);
4314
4315 service.mHostName = host.mHostName;
4316 service.mServiceInstance = "mysrv";
4317 service.mServiceType = "_srv._udp";
4318 service.mSubTypeLabels = nullptr;
4319 service.mSubTypeLabelsLength = 0;
4320 service.mTxtData = kTxtData1;
4321 service.mTxtDataLength = sizeof(kTxtData1);
4322 service.mPort = 1111;
4323 service.mPriority = 0;
4324 service.mWeight = 0;
4325 service.mTtl = 1500;
4326 serviceFullName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
4327
4328 hostKey.mName = host.mHostName;
4329 hostKey.mServiceType = nullptr;
4330 hostKey.mKeyData = keyData;
4331 hostKey.mKeyDataLength = 300;
4332 hostKey.mTtl = 8000;
4333
4334 serviceKey.mName = service.mServiceInstance;
4335 serviceKey.mServiceType = service.mServiceType;
4336 serviceKey.mKeyData = keyData;
4337 serviceKey.mKeyDataLength = 300;
4338 serviceKey.mTtl = 8000;
4339
4340 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4341 Log("Set `MaxMessageSize` to 340 and use large key record data to trigger size limit behavior");
4342
4343 mdns->SetMaxMessageSize(340);
4344
4345 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4346 Log("Register host and service and keys for each");
4347
4348 sDnsMessages.Clear();
4349
4350 for (RegCallback ®Callbck : sRegCallbacks)
4351 {
4352 regCallbck.Reset();
4353 }
4354
4355 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
4356 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
4357 SuccessOrQuit(mdns->RegisterKey(hostKey, 2, HandleSuccessCallback));
4358 SuccessOrQuit(mdns->RegisterKey(serviceKey, 3, HandleSuccessCallback));
4359
4360 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4361 Log("Validate probes for all entries");
4362 Log("Probes for host and service should be broken into separate message due to size limit");
4363
4364 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4365 {
4366 sDnsMessages.Clear();
4367 AdvanceTime(250);
4368
4369 VerifyOrQuit(!sDnsMessages.IsEmpty());
4370 dnsMsg = sDnsMessages.GetHead();
4371
4372 for (uint16_t index = 0; index < 4; index++)
4373 {
4374 VerifyOrQuit(!sRegCallbacks[index].mWasCalled);
4375 }
4376
4377 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 4, /* Addnl */ 0);
4378 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ (probeCount == 0));
4379 dnsMsg->ValidateAsProbeFor(hostKey, /* aUnicastRequest */ (probeCount == 0));
4380
4381 dnsMsg = dnsMsg->GetNext();
4382 VerifyOrQuit(dnsMsg != nullptr);
4383
4384 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 3, /* Addnl */ 0);
4385 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
4386 dnsMsg->ValidateAsProbeFor(serviceKey, /* aUnicastRequest */ (probeCount == 0));
4387
4388 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4389 }
4390
4391 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4392 Log("Validate announcements for all entries");
4393 Log("Announces should also be broken into separate message due to size limit");
4394
4395 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4396 {
4397 sDnsMessages.Clear();
4398
4399 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4400
4401 for (uint16_t index = 0; index < 4; index++)
4402 {
4403 VerifyOrQuit(sRegCallbacks[index].mWasCalled);
4404 }
4405
4406 VerifyOrQuit(!sDnsMessages.IsEmpty());
4407 dnsMsg = sDnsMessages.GetHead();
4408
4409 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
4410 dnsMsg->Validate(host, kInAnswerSection);
4411 dnsMsg->Validate(hostKey, kInAnswerSection);
4412
4413 dnsMsg = dnsMsg->GetNext();
4414 VerifyOrQuit(dnsMsg != nullptr);
4415
4416 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 4);
4417 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr);
4418 dnsMsg->Validate(serviceKey, kInAnswerSection);
4419
4420 dnsMsg = dnsMsg->GetNext();
4421 VerifyOrQuit(dnsMsg != nullptr);
4422
4423 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
4424 dnsMsg->Validate(service, kInAnswerSection, kCheckServicesPtr);
4425
4426 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4427 }
4428
4429 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4430 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4431
4432 Log("End of test");
4433
4434 testFreeInstance(sInstance);
4435 }
4436
4437 //---------------------------------------------------------------------------------------------------------------------
4438
TestHostConflict(void)4439 void TestHostConflict(void)
4440 {
4441 Core *mdns = InitTest();
4442 Core::Host host;
4443 Ip6::Address hostAddresses[2];
4444 const DnsMessage *dnsMsg;
4445 uint16_t heapAllocations;
4446 DnsNameString hostFullName;
4447
4448 Log("-------------------------------------------------------------------------------------------");
4449 Log("TestHostConflict");
4450
4451 AdvanceTime(1);
4452
4453 heapAllocations = sHeapAllocatedPtrs.GetLength();
4454 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
4455
4456 SuccessOrQuit(hostAddresses[0].FromString("fd00::1"));
4457 SuccessOrQuit(hostAddresses[1].FromString("fd00::2"));
4458
4459 host.mHostName = "myhost";
4460 host.mAddresses = hostAddresses;
4461 host.mAddressesLength = 2;
4462 host.mTtl = 1500;
4463
4464 hostFullName.Append("%s.local.", host.mHostName);
4465
4466 // Run the test twice, first run send response with record in Answer section,
4467 // section run in Additional Data section.
4468
4469 sConflictCallback.Reset();
4470 mdns->SetConflictCallback(HandleConflict);
4471
4472 for (uint8_t iter = 0; iter < 2; iter++)
4473 {
4474 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4475 Log("Register a `HostEntry`, wait for first probe");
4476
4477 sDnsMessages.Clear();
4478
4479 sRegCallbacks[0].Reset();
4480 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleCallback));
4481
4482 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4483 AdvanceTime(250);
4484
4485 VerifyOrQuit(!sDnsMessages.IsEmpty());
4486 dnsMsg = sDnsMessages.GetHead();
4487 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4488 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ true);
4489 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4490
4491 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4492 Log("Send a response claiming the name with record in %s section", (iter == 0) ? "answer" : "additional");
4493
4494 SendResponseWithEmptyKey(hostFullName.AsCString(), (iter == 0) ? kInAnswerSection : kInAdditionalSection);
4495 AdvanceTime(1);
4496
4497 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4498 VerifyOrQuit(sRegCallbacks[0].mError == kErrorDuplicated);
4499
4500 VerifyOrQuit(!sConflictCallback.mWasCalled);
4501
4502 sDnsMessages.Clear();
4503
4504 SuccessOrQuit(mdns->UnregisterHost(host));
4505
4506 AdvanceTime(15000);
4507 VerifyOrQuit(sDnsMessages.IsEmpty());
4508 }
4509
4510 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4511 Log("Register a `HostEntry` and respond to probe to trigger conflict");
4512
4513 sRegCallbacks[0].Reset();
4514 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleCallback));
4515
4516 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4517
4518 SendResponseWithEmptyKey(hostFullName.AsCString(), kInAnswerSection);
4519 AdvanceTime(1);
4520
4521 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4522 VerifyOrQuit(sRegCallbacks[0].mError == kErrorDuplicated);
4523 VerifyOrQuit(!sConflictCallback.mWasCalled);
4524
4525 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4526 Log("Register the conflicted `HostEntry` again, and make sure no probes are sent");
4527
4528 sRegCallbacks[1].Reset();
4529 sConflictCallback.Reset();
4530 sDnsMessages.Clear();
4531
4532 SuccessOrQuit(mdns->RegisterHost(host, 1, HandleCallback));
4533 AdvanceTime(5000);
4534
4535 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
4536 VerifyOrQuit(sRegCallbacks[1].mError == kErrorDuplicated);
4537 VerifyOrQuit(!sConflictCallback.mWasCalled);
4538
4539 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4540 Log("Unregister the conflicted host and register it again immediately, make sure we see probes");
4541
4542 SuccessOrQuit(mdns->UnregisterHost(host));
4543
4544 sConflictCallback.Reset();
4545 sRegCallbacks[0].Reset();
4546 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
4547
4548 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4549 {
4550 sDnsMessages.Clear();
4551
4552 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4553 AdvanceTime(250);
4554
4555 VerifyOrQuit(!sDnsMessages.IsEmpty());
4556 dnsMsg = sDnsMessages.GetHead();
4557 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4558 dnsMsg->ValidateAsProbeFor(host, /* aUnicastRequest */ (probeCount == 0));
4559 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4560 }
4561
4562 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4563 {
4564 sDnsMessages.Clear();
4565
4566 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4567 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4568
4569 VerifyOrQuit(!sDnsMessages.IsEmpty());
4570 dnsMsg = sDnsMessages.GetHead();
4571 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 1);
4572 dnsMsg->Validate(host, kInAnswerSection);
4573 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4574 }
4575
4576 VerifyOrQuit(!sConflictCallback.mWasCalled);
4577
4578 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4579 Log("Send a response for host name and validate that conflict is detected and callback is called");
4580
4581 SendResponseWithEmptyKey(hostFullName.AsCString(), kInAnswerSection);
4582 AdvanceTime(1);
4583
4584 VerifyOrQuit(sConflictCallback.mWasCalled);
4585 VerifyOrQuit(StringMatch(sConflictCallback.mName.AsCString(), host.mHostName, kStringCaseInsensitiveMatch));
4586 VerifyOrQuit(!sConflictCallback.mHasServiceType);
4587
4588 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4589 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4590
4591 Log("End of test");
4592
4593 testFreeInstance(sInstance);
4594 }
4595
4596 //---------------------------------------------------------------------------------------------------------------------
4597
TestServiceConflict(void)4598 void TestServiceConflict(void)
4599 {
4600 Core *mdns = InitTest();
4601 Core::Service service;
4602 const DnsMessage *dnsMsg;
4603 uint16_t heapAllocations;
4604 DnsNameString fullServiceName;
4605
4606 Log("-------------------------------------------------------------------------------------------");
4607 Log("TestServiceConflict");
4608
4609 service.mHostName = "myhost";
4610 service.mServiceInstance = "myservice";
4611 service.mServiceType = "_srv._udp";
4612 service.mSubTypeLabels = nullptr;
4613 service.mSubTypeLabelsLength = 0;
4614 service.mTxtData = kTxtData1;
4615 service.mTxtDataLength = sizeof(kTxtData1);
4616 service.mPort = 1234;
4617 service.mPriority = 1;
4618 service.mWeight = 2;
4619 service.mTtl = 1000;
4620
4621 fullServiceName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
4622
4623 AdvanceTime(1);
4624
4625 heapAllocations = sHeapAllocatedPtrs.GetLength();
4626 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
4627
4628 // Run the test twice, first run send response with record in Answer section,
4629 // section run in Additional Data section.
4630
4631 sConflictCallback.Reset();
4632 mdns->SetConflictCallback(HandleConflict);
4633
4634 for (uint8_t iter = 0; iter < 2; iter++)
4635 {
4636 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4637 Log("Register a `ServiceEntry`, wait for first probe");
4638
4639 sDnsMessages.Clear();
4640
4641 sRegCallbacks[0].Reset();
4642 SuccessOrQuit(mdns->RegisterService(service, 0, HandleCallback));
4643
4644 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4645 AdvanceTime(250);
4646
4647 VerifyOrQuit(!sDnsMessages.IsEmpty());
4648 dnsMsg = sDnsMessages.GetHead();
4649 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4650 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ true);
4651 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4652
4653 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4654 Log("Send a response claiming the name with record in %s section", (iter == 0) ? "answer" : "additional");
4655
4656 SendResponseWithEmptyKey(fullServiceName.AsCString(), (iter == 0) ? kInAnswerSection : kInAdditionalSection);
4657 AdvanceTime(1);
4658
4659 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4660 VerifyOrQuit(sRegCallbacks[0].mError == kErrorDuplicated);
4661
4662 VerifyOrQuit(!sConflictCallback.mWasCalled);
4663
4664 sDnsMessages.Clear();
4665
4666 SuccessOrQuit(mdns->UnregisterService(service));
4667
4668 AdvanceTime(15000);
4669 VerifyOrQuit(sDnsMessages.IsEmpty());
4670 }
4671
4672 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4673 Log("Register a `ServiceEntry` and respond to probe to trigger conflict");
4674
4675 sRegCallbacks[0].Reset();
4676 SuccessOrQuit(mdns->RegisterService(service, 0, HandleCallback));
4677
4678 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4679
4680 SendResponseWithEmptyKey(fullServiceName.AsCString(), kInAnswerSection);
4681 AdvanceTime(1);
4682
4683 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4684 VerifyOrQuit(sRegCallbacks[0].mError == kErrorDuplicated);
4685 VerifyOrQuit(!sConflictCallback.mWasCalled);
4686
4687 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4688 Log("Register the conflicted `ServiceEntry` again, and make sure no probes are sent");
4689
4690 sRegCallbacks[1].Reset();
4691 sConflictCallback.Reset();
4692 sDnsMessages.Clear();
4693
4694 SuccessOrQuit(mdns->RegisterService(service, 1, HandleCallback));
4695 AdvanceTime(5000);
4696
4697 VerifyOrQuit(sRegCallbacks[1].mWasCalled);
4698 VerifyOrQuit(sRegCallbacks[1].mError == kErrorDuplicated);
4699 VerifyOrQuit(!sConflictCallback.mWasCalled);
4700
4701 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4702 Log("Unregister the conflicted host and register it again immediately, make sure we see probes");
4703
4704 SuccessOrQuit(mdns->UnregisterService(service));
4705
4706 sConflictCallback.Reset();
4707 sRegCallbacks[0].Reset();
4708 SuccessOrQuit(mdns->RegisterService(service, 0, HandleSuccessCallback));
4709
4710 for (uint8_t probeCount = 0; probeCount < 3; probeCount++)
4711 {
4712 sDnsMessages.Clear();
4713
4714 VerifyOrQuit(!sRegCallbacks[0].mWasCalled);
4715 AdvanceTime(250);
4716
4717 VerifyOrQuit(!sDnsMessages.IsEmpty());
4718 dnsMsg = sDnsMessages.GetHead();
4719 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 2, /* Addnl */ 0);
4720 dnsMsg->ValidateAsProbeFor(service, /* aUnicastRequest */ (probeCount == 0));
4721 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4722 }
4723
4724 for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++)
4725 {
4726 sDnsMessages.Clear();
4727
4728 AdvanceTime((anncCount == 0) ? 250 : (1U << (anncCount - 1)) * 1000);
4729 VerifyOrQuit(sRegCallbacks[0].mWasCalled);
4730
4731 VerifyOrQuit(!sDnsMessages.IsEmpty());
4732 dnsMsg = sDnsMessages.GetHead();
4733 dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 4, /* Auth */ 0, /* Addnl */ 1);
4734 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt | kCheckPtr | kCheckServicesPtr);
4735 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
4736 }
4737
4738 VerifyOrQuit(!sConflictCallback.mWasCalled);
4739
4740 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
4741 Log("Send a response for service name and validate that conflict is detected and callback is called");
4742
4743 SendResponseWithEmptyKey(fullServiceName.AsCString(), kInAnswerSection);
4744 AdvanceTime(1);
4745
4746 VerifyOrQuit(sConflictCallback.mWasCalled);
4747 VerifyOrQuit(
4748 StringMatch(sConflictCallback.mName.AsCString(), service.mServiceInstance, kStringCaseInsensitiveMatch));
4749 VerifyOrQuit(sConflictCallback.mHasServiceType);
4750 VerifyOrQuit(
4751 StringMatch(sConflictCallback.mServiceType.AsCString(), service.mServiceType, kStringCaseInsensitiveMatch));
4752
4753 sDnsMessages.Clear();
4754 AdvanceTime(20000);
4755 VerifyOrQuit(sDnsMessages.IsEmpty());
4756
4757 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
4758 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
4759
4760 Log("End of test");
4761
4762 testFreeInstance(sInstance);
4763 }
4764
4765 //=====================================================================================================================
4766 // Browser/Resolver tests
4767
4768 struct BrowseCallback : public Allocatable<BrowseCallback>, public LinkedListEntry<BrowseCallback>
4769 {
4770 BrowseCallback *mNext;
4771 DnsName mServiceType;
4772 DnsName mSubTypeLabel;
4773 DnsName mServiceInstance;
4774 uint32_t mTtl;
4775 bool mIsSubType;
4776 };
4777
4778 struct SrvCallback : public Allocatable<SrvCallback>, public LinkedListEntry<SrvCallback>
4779 {
4780 SrvCallback *mNext;
4781 DnsName mServiceInstance;
4782 DnsName mServiceType;
4783 DnsName mHostName;
4784 uint16_t mPort;
4785 uint16_t mPriority;
4786 uint16_t mWeight;
4787 uint32_t mTtl;
4788 };
4789
4790 struct TxtCallback : public Allocatable<TxtCallback>, public LinkedListEntry<TxtCallback>
4791 {
4792 static constexpr uint16_t kMaxTxtDataLength = 100;
4793
Matchesot::Dns::Multicast::TxtCallback4794 template <uint16_t kSize> bool Matches(const uint8_t (&aData)[kSize]) const
4795 {
4796 return (mTxtDataLength == kSize) && (memcmp(mTxtData, aData, kSize) == 0);
4797 }
4798
4799 TxtCallback *mNext;
4800 DnsName mServiceInstance;
4801 DnsName mServiceType;
4802 uint8_t mTxtData[kMaxTxtDataLength];
4803 uint16_t mTxtDataLength;
4804 uint32_t mTtl;
4805 };
4806
4807 struct AddrCallback : public Allocatable<AddrCallback>, public LinkedListEntry<AddrCallback>
4808 {
4809 static constexpr uint16_t kMaxNumAddrs = 16;
4810
Containsot::Dns::Multicast::AddrCallback4811 bool Contains(const AddrAndTtl &aAddrAndTtl) const
4812 {
4813 bool contains = false;
4814
4815 for (uint16_t index = 0; index < mNumAddrs; index++)
4816 {
4817 if (mAddrAndTtls[index] == aAddrAndTtl)
4818 {
4819 contains = true;
4820 break;
4821 }
4822 }
4823
4824 return contains;
4825 }
4826
Matchesot::Dns::Multicast::AddrCallback4827 bool Matches(const AddrAndTtl *aAddrAndTtls, uint16_t aNumAddrs) const
4828 {
4829 bool matches = true;
4830
4831 VerifyOrExit(aNumAddrs == mNumAddrs, matches = false);
4832
4833 for (uint16_t index = 0; index < mNumAddrs; index++)
4834 {
4835 if (!Contains(aAddrAndTtls[index]))
4836 {
4837 ExitNow(matches = false);
4838 }
4839 }
4840
4841 exit:
4842 return matches;
4843 }
4844
4845 AddrCallback *mNext;
4846 DnsName mHostName;
4847 AddrAndTtl mAddrAndTtls[kMaxNumAddrs];
4848 uint16_t mNumAddrs;
4849 };
4850
4851 OwningList<BrowseCallback> sBrowseCallbacks;
4852 OwningList<SrvCallback> sSrvCallbacks;
4853 OwningList<TxtCallback> sTxtCallbacks;
4854 OwningList<AddrCallback> sAddrCallbacks;
4855
HandleBrowseResult(otInstance * aInstance,const otMdnsBrowseResult * aResult)4856 void HandleBrowseResult(otInstance *aInstance, const otMdnsBrowseResult *aResult)
4857 {
4858 BrowseCallback *entry;
4859
4860 VerifyOrQuit(aInstance == sInstance);
4861 VerifyOrQuit(aResult != nullptr);
4862 VerifyOrQuit(aResult->mServiceType != nullptr);
4863 VerifyOrQuit(aResult->mServiceInstance != nullptr);
4864 VerifyOrQuit(aResult->mInfraIfIndex == kInfraIfIndex);
4865
4866 Log("Browse callback: %s (subtype:%s) -> %s ttl:%lu", aResult->mServiceType,
4867 aResult->mSubTypeLabel == nullptr ? "(null)" : aResult->mSubTypeLabel, aResult->mServiceInstance,
4868 ToUlong(aResult->mTtl));
4869
4870 entry = BrowseCallback::Allocate();
4871 VerifyOrQuit(entry != nullptr);
4872
4873 entry->mServiceType.CopyFrom(aResult->mServiceType);
4874 entry->mSubTypeLabel.CopyFrom(aResult->mSubTypeLabel);
4875 entry->mServiceInstance.CopyFrom(aResult->mServiceInstance);
4876 entry->mTtl = aResult->mTtl;
4877 entry->mIsSubType = (aResult->mSubTypeLabel != nullptr);
4878
4879 sBrowseCallbacks.PushAfterTail(*entry);
4880 }
4881
HandleBrowseResultAlternate(otInstance * aInstance,const otMdnsBrowseResult * aResult)4882 void HandleBrowseResultAlternate(otInstance *aInstance, const otMdnsBrowseResult *aResult)
4883 {
4884 Log("Alternate browse callback is called");
4885 HandleBrowseResult(aInstance, aResult);
4886 }
4887
HandleSrvResult(otInstance * aInstance,const otMdnsSrvResult * aResult)4888 void HandleSrvResult(otInstance *aInstance, const otMdnsSrvResult *aResult)
4889 {
4890 SrvCallback *entry;
4891
4892 VerifyOrQuit(aInstance == sInstance);
4893 VerifyOrQuit(aResult != nullptr);
4894 VerifyOrQuit(aResult->mServiceInstance != nullptr);
4895 VerifyOrQuit(aResult->mServiceType != nullptr);
4896 VerifyOrQuit(aResult->mInfraIfIndex == kInfraIfIndex);
4897
4898 if (aResult->mTtl != 0)
4899 {
4900 VerifyOrQuit(aResult->mHostName != nullptr);
4901
4902 Log("SRV callback: %s %s, host:%s port:%u, prio:%u, weight:%u, ttl:%lu", aResult->mServiceInstance,
4903 aResult->mServiceType, aResult->mHostName, aResult->mPort, aResult->mPriority, aResult->mWeight,
4904 ToUlong(aResult->mTtl));
4905 }
4906 else
4907 {
4908 Log("SRV callback: %s %s, ttl:%lu", aResult->mServiceInstance, aResult->mServiceType, ToUlong(aResult->mTtl));
4909 }
4910
4911 entry = SrvCallback::Allocate();
4912 VerifyOrQuit(entry != nullptr);
4913
4914 entry->mServiceInstance.CopyFrom(aResult->mServiceInstance);
4915 entry->mServiceType.CopyFrom(aResult->mServiceType);
4916 entry->mHostName.CopyFrom(aResult->mHostName);
4917 entry->mPort = aResult->mPort;
4918 entry->mPriority = aResult->mPriority;
4919 entry->mWeight = aResult->mWeight;
4920 entry->mTtl = aResult->mTtl;
4921
4922 sSrvCallbacks.PushAfterTail(*entry);
4923 }
4924
HandleSrvResultAlternate(otInstance * aInstance,const otMdnsSrvResult * aResult)4925 void HandleSrvResultAlternate(otInstance *aInstance, const otMdnsSrvResult *aResult)
4926 {
4927 Log("Alternate SRV callback is called");
4928 HandleSrvResult(aInstance, aResult);
4929 }
4930
HandleTxtResult(otInstance * aInstance,const otMdnsTxtResult * aResult)4931 void HandleTxtResult(otInstance *aInstance, const otMdnsTxtResult *aResult)
4932 {
4933 TxtCallback *entry;
4934
4935 VerifyOrQuit(aInstance == sInstance);
4936 VerifyOrQuit(aResult != nullptr);
4937 VerifyOrQuit(aResult->mServiceInstance != nullptr);
4938 VerifyOrQuit(aResult->mServiceType != nullptr);
4939 VerifyOrQuit(aResult->mInfraIfIndex == kInfraIfIndex);
4940
4941 VerifyOrQuit(aResult->mTxtDataLength <= TxtCallback::kMaxTxtDataLength);
4942
4943 if (aResult->mTtl != 0)
4944 {
4945 VerifyOrQuit(aResult->mTxtData != nullptr);
4946
4947 Log("TXT callback: %s %s, len:%u, ttl:%lu", aResult->mServiceInstance, aResult->mServiceType,
4948 aResult->mTxtDataLength, ToUlong(aResult->mTtl));
4949 }
4950 else
4951 {
4952 Log("TXT callback: %s %s, ttl:%lu", aResult->mServiceInstance, aResult->mServiceType, ToUlong(aResult->mTtl));
4953 }
4954
4955 entry = TxtCallback::Allocate();
4956 VerifyOrQuit(entry != nullptr);
4957
4958 entry->mServiceInstance.CopyFrom(aResult->mServiceInstance);
4959 entry->mServiceType.CopyFrom(aResult->mServiceType);
4960 entry->mTxtDataLength = aResult->mTxtDataLength;
4961 memcpy(entry->mTxtData, aResult->mTxtData, aResult->mTxtDataLength);
4962 entry->mTtl = aResult->mTtl;
4963
4964 sTxtCallbacks.PushAfterTail(*entry);
4965 }
4966
HandleTxtResultAlternate(otInstance * aInstance,const otMdnsTxtResult * aResult)4967 void HandleTxtResultAlternate(otInstance *aInstance, const otMdnsTxtResult *aResult)
4968 {
4969 Log("Alternate TXT callback is called");
4970 HandleTxtResult(aInstance, aResult);
4971 }
4972
HandleAddrResult(otInstance * aInstance,const otMdnsAddressResult * aResult)4973 void HandleAddrResult(otInstance *aInstance, const otMdnsAddressResult *aResult)
4974 {
4975 AddrCallback *entry;
4976
4977 VerifyOrQuit(aInstance == sInstance);
4978 VerifyOrQuit(aResult != nullptr);
4979 VerifyOrQuit(aResult->mHostName != nullptr);
4980 VerifyOrQuit(aResult->mInfraIfIndex == kInfraIfIndex);
4981
4982 VerifyOrQuit(aResult->mAddressesLength <= AddrCallback::kMaxNumAddrs);
4983
4984 entry = AddrCallback::Allocate();
4985 VerifyOrQuit(entry != nullptr);
4986
4987 entry->mHostName.CopyFrom(aResult->mHostName);
4988 entry->mNumAddrs = aResult->mAddressesLength;
4989
4990 Log("Addr callback: %s, num:%u", aResult->mHostName, aResult->mAddressesLength);
4991
4992 for (uint16_t index = 0; index < aResult->mAddressesLength; index++)
4993 {
4994 entry->mAddrAndTtls[index].mAddress = AsCoreType(&aResult->mAddresses[index].mAddress);
4995 entry->mAddrAndTtls[index].mTtl = aResult->mAddresses[index].mTtl;
4996
4997 Log(" - %s, ttl:%lu", entry->mAddrAndTtls[index].mAddress.ToString().AsCString(),
4998 ToUlong(entry->mAddrAndTtls[index].mTtl));
4999 }
5000
5001 sAddrCallbacks.PushAfterTail(*entry);
5002 }
5003
HandleAddrResultAlternate(otInstance * aInstance,const otMdnsAddressResult * aResult)5004 void HandleAddrResultAlternate(otInstance *aInstance, const otMdnsAddressResult *aResult)
5005 {
5006 Log("Alternate addr callback is called");
5007 HandleAddrResult(aInstance, aResult);
5008 }
5009
5010 //---------------------------------------------------------------------------------------------------------------------
5011
TestBrowser(void)5012 void TestBrowser(void)
5013 {
5014 Core *mdns = InitTest();
5015 Core::Browser browser;
5016 Core::Browser browser2;
5017 const DnsMessage *dnsMsg;
5018 const BrowseCallback *browseCallback;
5019 uint16_t heapAllocations;
5020
5021 Log("-------------------------------------------------------------------------------------------");
5022 Log("TestBrowser");
5023
5024 AdvanceTime(1);
5025
5026 heapAllocations = sHeapAllocatedPtrs.GetLength();
5027 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
5028
5029 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5030 Log("Start a browser. Validate initial queries.");
5031
5032 ClearAllBytes(browser);
5033
5034 browser.mServiceType = "_srv._udp";
5035 browser.mSubTypeLabel = nullptr;
5036 browser.mInfraIfIndex = kInfraIfIndex;
5037 browser.mCallback = HandleBrowseResult;
5038
5039 sDnsMessages.Clear();
5040 SuccessOrQuit(mdns->StartBrowser(browser));
5041
5042 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
5043 {
5044 sDnsMessages.Clear();
5045
5046 AdvanceTime((queryCount == 0) ? 125 : (1U << (queryCount - 1)) * 1000);
5047
5048 VerifyOrQuit(!sDnsMessages.IsEmpty());
5049 dnsMsg = sDnsMessages.GetHead();
5050 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5051 dnsMsg->ValidateAsQueryFor(browser);
5052 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5053 }
5054
5055 sDnsMessages.Clear();
5056
5057 AdvanceTime(20000);
5058 VerifyOrQuit(sDnsMessages.IsEmpty());
5059
5060 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5061 Log("Send a response. Validate callback result.");
5062
5063 sBrowseCallbacks.Clear();
5064
5065 SendPtrResponse("_srv._udp.local.", "mysrv._srv._udp.local.", 120, kInAnswerSection);
5066
5067 AdvanceTime(1);
5068
5069 VerifyOrQuit(!sBrowseCallbacks.IsEmpty());
5070 browseCallback = sBrowseCallbacks.GetHead();
5071 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5072 VerifyOrQuit(!browseCallback->mIsSubType);
5073 VerifyOrQuit(browseCallback->mServiceInstance.Matches("mysrv"));
5074 VerifyOrQuit(browseCallback->mTtl == 120);
5075 VerifyOrQuit(browseCallback->GetNext() == nullptr);
5076
5077 VerifyOrQuit(sDnsMessages.IsEmpty());
5078
5079 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5080 Log("Send another response. Validate callback result.");
5081
5082 AdvanceTime(10000);
5083
5084 sBrowseCallbacks.Clear();
5085
5086 SendPtrResponse("_srv._udp.local.", "awesome._srv._udp.local.", 500, kInAnswerSection);
5087
5088 AdvanceTime(1);
5089
5090 VerifyOrQuit(!sBrowseCallbacks.IsEmpty());
5091 browseCallback = sBrowseCallbacks.GetHead();
5092 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5093 VerifyOrQuit(!browseCallback->mIsSubType);
5094 VerifyOrQuit(browseCallback->mServiceInstance.Matches("awesome"));
5095 VerifyOrQuit(browseCallback->mTtl == 500);
5096 VerifyOrQuit(browseCallback->GetNext() == nullptr);
5097
5098 VerifyOrQuit(sDnsMessages.IsEmpty());
5099
5100 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5101 Log("Start another browser for the same service and different callback. Validate results.");
5102
5103 AdvanceTime(5000);
5104
5105 browser2.mServiceType = "_srv._udp";
5106 browser2.mSubTypeLabel = nullptr;
5107 browser2.mInfraIfIndex = kInfraIfIndex;
5108 browser2.mCallback = HandleBrowseResultAlternate;
5109
5110 sBrowseCallbacks.Clear();
5111
5112 SuccessOrQuit(mdns->StartBrowser(browser2));
5113
5114 browseCallback = sBrowseCallbacks.GetHead();
5115
5116 for (uint8_t iter = 0; iter < 2; iter++)
5117 {
5118 VerifyOrQuit(browseCallback != nullptr);
5119
5120 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5121 VerifyOrQuit(!browseCallback->mIsSubType);
5122
5123 if (browseCallback->mServiceInstance.Matches("awesome"))
5124 {
5125 VerifyOrQuit(browseCallback->mTtl == 500);
5126 }
5127 else if (browseCallback->mServiceInstance.Matches("mysrv"))
5128 {
5129 VerifyOrQuit(browseCallback->mTtl == 120);
5130 }
5131 else
5132 {
5133 VerifyOrQuit(false);
5134 }
5135
5136 browseCallback = browseCallback->GetNext();
5137 }
5138
5139 VerifyOrQuit(browseCallback == nullptr);
5140
5141 AdvanceTime(5000);
5142
5143 VerifyOrQuit(sDnsMessages.IsEmpty());
5144
5145 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5146 Log("Start same browser again and check the returned error.");
5147
5148 sBrowseCallbacks.Clear();
5149
5150 VerifyOrQuit(mdns->StartBrowser(browser2) == kErrorAlready);
5151
5152 AdvanceTime(5000);
5153
5154 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5155
5156 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5157 Log("Send a goodbye response. Validate result callback for both browsers.");
5158
5159 SendPtrResponse("_srv._udp.local.", "awesome._srv._udp.local.", 0, kInAnswerSection);
5160
5161 AdvanceTime(1);
5162
5163 browseCallback = sBrowseCallbacks.GetHead();
5164
5165 for (uint8_t iter = 0; iter < 2; iter++)
5166 {
5167 VerifyOrQuit(browseCallback != nullptr);
5168
5169 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5170 VerifyOrQuit(!browseCallback->mIsSubType);
5171 VerifyOrQuit(browseCallback->mServiceInstance.Matches("awesome"));
5172 VerifyOrQuit(browseCallback->mTtl == 0);
5173
5174 browseCallback = browseCallback->GetNext();
5175 }
5176
5177 VerifyOrQuit(browseCallback == nullptr);
5178
5179 VerifyOrQuit(sDnsMessages.IsEmpty());
5180
5181 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5182 Log("Send a response with no changes, validate that no callback is invoked.");
5183
5184 sBrowseCallbacks.Clear();
5185
5186 SendPtrResponse("_srv._udp.local.", "mysrv._srv._udp.local.", 120, kInAnswerSection);
5187
5188 AdvanceTime(1);
5189
5190 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5191 VerifyOrQuit(sDnsMessages.IsEmpty());
5192
5193 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5194 Log("Stop the second browser.");
5195
5196 sBrowseCallbacks.Clear();
5197
5198 SuccessOrQuit(mdns->StopBrowser(browser2));
5199
5200 AdvanceTime(5000);
5201
5202 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5203 VerifyOrQuit(sDnsMessages.IsEmpty());
5204
5205 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5206 Log("Check query is sent at 80 percentage of TTL and then respond to it.");
5207
5208 // First query should be sent at 80-82% of TTL of 120 second (96.0-98.4 sec).
5209 // We wait for 100 second. Note that 5 seconds already passed in the
5210 // previous step.
5211
5212 AdvanceTime(91 * 1000 - 1);
5213
5214 VerifyOrQuit(sDnsMessages.IsEmpty());
5215
5216 AdvanceTime(4 * 1000 + 1);
5217
5218 VerifyOrQuit(!sDnsMessages.IsEmpty());
5219 dnsMsg = sDnsMessages.GetHead();
5220 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5221 dnsMsg->ValidateAsQueryFor(browser);
5222 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5223
5224 sDnsMessages.Clear();
5225 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5226
5227 AdvanceTime(10);
5228
5229 SendPtrResponse("_srv._udp.local.", "mysrv._srv._udp.local.", 120, kInAnswerSection);
5230
5231 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5232 Log("Check queries are sent at 80, 85, 90, 95 percentages of TTL.");
5233
5234 for (uint8_t queryCount = 0; queryCount < kNumRefreshQueries; queryCount++)
5235 {
5236 if (queryCount == 0)
5237 {
5238 // First query is expected in 80-82% of TTL, so
5239 // 80% of 120 = 96.0, 82% of 120 = 98.4
5240
5241 AdvanceTime(96 * 1000 - 1);
5242 }
5243 else
5244 {
5245 // Next query should happen within 3%-5% of TTL
5246 // from previous query. We wait 3% of TTL here.
5247 AdvanceTime(3600 - 1);
5248 }
5249
5250 VerifyOrQuit(sDnsMessages.IsEmpty());
5251
5252 // Wait for 2% of TTL of 120 which is 2.4 sec.
5253
5254 AdvanceTime(2400 + 1);
5255
5256 VerifyOrQuit(!sDnsMessages.IsEmpty());
5257 dnsMsg = sDnsMessages.GetHead();
5258 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5259 dnsMsg->ValidateAsQueryFor(browser);
5260 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5261
5262 sDnsMessages.Clear();
5263 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5264 }
5265
5266 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5267 Log("Check TTL timeout and callback result.");
5268
5269 AdvanceTime(6 * 1000);
5270
5271 VerifyOrQuit(!sBrowseCallbacks.IsEmpty());
5272
5273 browseCallback = sBrowseCallbacks.GetHead();
5274 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5275 VerifyOrQuit(!browseCallback->mIsSubType);
5276 VerifyOrQuit(browseCallback->mServiceInstance.Matches("mysrv"));
5277 VerifyOrQuit(browseCallback->mTtl == 0);
5278 VerifyOrQuit(browseCallback->GetNext() == nullptr);
5279
5280 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5281
5282 sBrowseCallbacks.Clear();
5283 sDnsMessages.Clear();
5284
5285 AdvanceTime(200 * 1000);
5286
5287 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5288 VerifyOrQuit(sDnsMessages.IsEmpty());
5289
5290 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5291 Log("Send a new response and make sure result callback is invoked");
5292
5293 SendPtrResponse("_srv._udp.local.", "great._srv._udp.local.", 200, kInAdditionalSection);
5294
5295 AdvanceTime(1);
5296
5297 browseCallback = sBrowseCallbacks.GetHead();
5298
5299 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5300 VerifyOrQuit(!browseCallback->mIsSubType);
5301 VerifyOrQuit(browseCallback->mServiceInstance.Matches("great"));
5302 VerifyOrQuit(browseCallback->mTtl == 200);
5303 VerifyOrQuit(browseCallback->GetNext() == nullptr);
5304
5305 sBrowseCallbacks.Clear();
5306
5307 AdvanceTime(150 * 1000);
5308
5309 VerifyOrQuit(sDnsMessages.IsEmpty());
5310 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5311
5312 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5313 Log("Stop the browser. There is no active browser for this service. Ensure no queries are sent");
5314
5315 sBrowseCallbacks.Clear();
5316
5317 SuccessOrQuit(mdns->StopBrowser(browser));
5318
5319 AdvanceTime(100 * 1000);
5320
5321 VerifyOrQuit(sBrowseCallbacks.IsEmpty());
5322 VerifyOrQuit(sDnsMessages.IsEmpty());
5323
5324 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5325 Log("Start browser again. Validate that initial queries are sent again");
5326
5327 SuccessOrQuit(mdns->StartBrowser(browser));
5328
5329 AdvanceTime(125);
5330
5331 VerifyOrQuit(!sDnsMessages.IsEmpty());
5332 dnsMsg = sDnsMessages.GetHead();
5333 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5334 dnsMsg->ValidateAsQueryFor(browser);
5335 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5336
5337 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5338 Log("Send a response after the first initial query");
5339
5340 sDnsMessages.Clear();
5341
5342 SendPtrResponse("_srv._udp.local.", "mysrv._srv._udp.local.", 120, kInAnswerSection);
5343
5344 AdvanceTime(1);
5345
5346 browseCallback = sBrowseCallbacks.GetHead();
5347
5348 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
5349 VerifyOrQuit(!browseCallback->mIsSubType);
5350 VerifyOrQuit(browseCallback->mServiceInstance.Matches("mysrv"));
5351 VerifyOrQuit(browseCallback->mTtl == 120);
5352 VerifyOrQuit(browseCallback->GetNext() == nullptr);
5353
5354 sBrowseCallbacks.Clear();
5355
5356 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5357 Log("Validate initial esquires are still sent and include known-answer");
5358
5359 for (uint8_t queryCount = 1; queryCount < kNumInitalQueries; queryCount++)
5360 {
5361 sDnsMessages.Clear();
5362
5363 AdvanceTime((1U << (queryCount - 1)) * 1000);
5364
5365 VerifyOrQuit(!sDnsMessages.IsEmpty());
5366 dnsMsg = sDnsMessages.GetHead();
5367 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 0);
5368 dnsMsg->ValidateAsQueryFor(browser);
5369 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5370 }
5371
5372 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5373
5374 sDnsMessages.Clear();
5375 AdvanceTime(50 * 1000);
5376 VerifyOrQuit(sDnsMessages.IsEmpty());
5377
5378 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
5379 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
5380
5381 Log("End of test");
5382
5383 testFreeInstance(sInstance);
5384 }
5385
TestSrvResolver(void)5386 void TestSrvResolver(void)
5387 {
5388 Core *mdns = InitTest();
5389 Core::SrvResolver resolver;
5390 Core::SrvResolver resolver2;
5391 const DnsMessage *dnsMsg;
5392 const SrvCallback *srvCallback;
5393 uint16_t heapAllocations;
5394
5395 Log("-------------------------------------------------------------------------------------------");
5396 Log("TestSrvResolver");
5397
5398 AdvanceTime(1);
5399
5400 heapAllocations = sHeapAllocatedPtrs.GetLength();
5401 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
5402
5403 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5404 Log("Start a SRV resolver. Validate initial queries.");
5405
5406 ClearAllBytes(resolver);
5407
5408 resolver.mServiceInstance = "mysrv";
5409 resolver.mServiceType = "_srv._udp";
5410 resolver.mInfraIfIndex = kInfraIfIndex;
5411 resolver.mCallback = HandleSrvResult;
5412
5413 sDnsMessages.Clear();
5414 SuccessOrQuit(mdns->StartSrvResolver(resolver));
5415
5416 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
5417 {
5418 sDnsMessages.Clear();
5419
5420 AdvanceTime((queryCount == 0) ? 125 : (1U << (queryCount - 1)) * 1000);
5421
5422 VerifyOrQuit(!sDnsMessages.IsEmpty());
5423 dnsMsg = sDnsMessages.GetHead();
5424 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5425 dnsMsg->ValidateAsQueryFor(resolver);
5426 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5427 }
5428
5429 sDnsMessages.Clear();
5430
5431 AdvanceTime(20 * 1000);
5432 VerifyOrQuit(sDnsMessages.IsEmpty());
5433
5434 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5435 Log("Send a response. Validate callback result.");
5436
5437 sSrvCallbacks.Clear();
5438
5439 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 0, 1, 120, kInAnswerSection);
5440
5441 AdvanceTime(1);
5442
5443 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5444 srvCallback = sSrvCallbacks.GetHead();
5445 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5446 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5447 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5448 VerifyOrQuit(srvCallback->mPort == 1234);
5449 VerifyOrQuit(srvCallback->mPriority == 0);
5450 VerifyOrQuit(srvCallback->mWeight == 1);
5451 VerifyOrQuit(srvCallback->mTtl == 120);
5452 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5453
5454 VerifyOrQuit(sDnsMessages.IsEmpty());
5455
5456 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5457 Log("Send an updated response changing host name. Validate callback result.");
5458
5459 AdvanceTime(1000);
5460
5461 sSrvCallbacks.Clear();
5462
5463 SendSrvResponse("mysrv._srv._udp.local.", "myhost2.local.", 1234, 0, 1, 120, kInAnswerSection);
5464
5465 AdvanceTime(1);
5466
5467 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5468 srvCallback = sSrvCallbacks.GetHead();
5469 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5470 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5471 VerifyOrQuit(srvCallback->mHostName.Matches("myhost2"));
5472 VerifyOrQuit(srvCallback->mPort == 1234);
5473 VerifyOrQuit(srvCallback->mPriority == 0);
5474 VerifyOrQuit(srvCallback->mWeight == 1);
5475 VerifyOrQuit(srvCallback->mTtl == 120);
5476 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5477
5478 VerifyOrQuit(sDnsMessages.IsEmpty());
5479
5480 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5481 Log("Send an updated response changing port. Validate callback result.");
5482
5483 AdvanceTime(1000);
5484
5485 sSrvCallbacks.Clear();
5486
5487 SendSrvResponse("mysrv._srv._udp.local.", "myhost2.local.", 4567, 0, 1, 120, kInAnswerSection);
5488
5489 AdvanceTime(1);
5490
5491 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5492 srvCallback = sSrvCallbacks.GetHead();
5493 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5494 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5495 VerifyOrQuit(srvCallback->mHostName.Matches("myhost2"));
5496 VerifyOrQuit(srvCallback->mPort == 4567);
5497 VerifyOrQuit(srvCallback->mPriority == 0);
5498 VerifyOrQuit(srvCallback->mWeight == 1);
5499 VerifyOrQuit(srvCallback->mTtl == 120);
5500 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5501
5502 VerifyOrQuit(sDnsMessages.IsEmpty());
5503
5504 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5505 Log("Send an updated response changing TTL. Validate callback result.");
5506
5507 AdvanceTime(1000);
5508
5509 sSrvCallbacks.Clear();
5510
5511 SendSrvResponse("mysrv._srv._udp.local.", "myhost2.local.", 4567, 0, 1, 0, kInAnswerSection);
5512
5513 AdvanceTime(1);
5514
5515 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5516 srvCallback = sSrvCallbacks.GetHead();
5517 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5518 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5519 VerifyOrQuit(srvCallback->mHostName.Matches(""));
5520 VerifyOrQuit(srvCallback->mPort == 4567);
5521 VerifyOrQuit(srvCallback->mPriority == 0);
5522 VerifyOrQuit(srvCallback->mWeight == 1);
5523 VerifyOrQuit(srvCallback->mTtl == 0);
5524 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5525
5526 VerifyOrQuit(sDnsMessages.IsEmpty());
5527
5528 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5529 Log("Send an updated response changing a bunch of things. Validate callback result.");
5530
5531 AdvanceTime(1000);
5532
5533 sSrvCallbacks.Clear();
5534
5535 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 2, 3, 120, kInAnswerSection);
5536
5537 AdvanceTime(1);
5538
5539 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5540 srvCallback = sSrvCallbacks.GetHead();
5541 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5542 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5543 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5544 VerifyOrQuit(srvCallback->mPort == 1234);
5545 VerifyOrQuit(srvCallback->mPriority == 2);
5546 VerifyOrQuit(srvCallback->mWeight == 3);
5547 VerifyOrQuit(srvCallback->mTtl == 120);
5548 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5549
5550 VerifyOrQuit(sDnsMessages.IsEmpty());
5551
5552 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5553 Log("Send a response with no changes. Validate callback is not invoked.");
5554
5555 AdvanceTime(1000);
5556
5557 sSrvCallbacks.Clear();
5558
5559 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 2, 3, 120, kInAnswerSection);
5560
5561 AdvanceTime(1);
5562
5563 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5564 VerifyOrQuit(sDnsMessages.IsEmpty());
5565
5566 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5567 Log("Start another resolver for the same service and different callback. Validate results.");
5568
5569 ClearAllBytes(resolver2);
5570
5571 resolver2.mServiceInstance = "mysrv";
5572 resolver2.mServiceType = "_srv._udp";
5573 resolver2.mInfraIfIndex = kInfraIfIndex;
5574 resolver2.mCallback = HandleSrvResultAlternate;
5575
5576 sSrvCallbacks.Clear();
5577
5578 SuccessOrQuit(mdns->StartSrvResolver(resolver2));
5579
5580 AdvanceTime(1);
5581
5582 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5583 srvCallback = sSrvCallbacks.GetHead();
5584 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5585 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5586 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5587 VerifyOrQuit(srvCallback->mPort == 1234);
5588 VerifyOrQuit(srvCallback->mPriority == 2);
5589 VerifyOrQuit(srvCallback->mWeight == 3);
5590 VerifyOrQuit(srvCallback->mTtl == 120);
5591 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5592
5593 VerifyOrQuit(sDnsMessages.IsEmpty());
5594
5595 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5596 Log("Start same resolver again and check the returned error.");
5597
5598 sSrvCallbacks.Clear();
5599
5600 VerifyOrQuit(mdns->StartSrvResolver(resolver2) == kErrorAlready);
5601
5602 AdvanceTime(5000);
5603
5604 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5605
5606 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5607 Log("Check query is sent at 80 percentage of TTL and then respond to it.");
5608
5609 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 2, 3, 120, kInAnswerSection);
5610
5611 // First query should be sent at 80-82% of TTL of 120 second (96.0-98.4 sec).
5612 // We wait for 100 second. Note that 5 seconds already passed in the
5613 // previous step.
5614
5615 AdvanceTime(96 * 1000 - 1);
5616
5617 VerifyOrQuit(sDnsMessages.IsEmpty());
5618
5619 AdvanceTime(4 * 1000 + 1);
5620
5621 VerifyOrQuit(!sDnsMessages.IsEmpty());
5622 dnsMsg = sDnsMessages.GetHead();
5623 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5624 dnsMsg->ValidateAsQueryFor(resolver);
5625 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5626
5627 sDnsMessages.Clear();
5628 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5629
5630 AdvanceTime(10);
5631
5632 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 2, 3, 120, kInAnswerSection);
5633
5634 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5635 Log("Check queries are sent at 80, 85, 90, 95 percentages of TTL.");
5636
5637 for (uint8_t queryCount = 0; queryCount < kNumRefreshQueries; queryCount++)
5638 {
5639 if (queryCount == 0)
5640 {
5641 // First query is expected in 80-82% of TTL, so
5642 // 80% of 120 = 96.0, 82% of 120 = 98.4
5643
5644 AdvanceTime(96 * 1000 - 1);
5645 }
5646 else
5647 {
5648 // Next query should happen within 3%-5% of TTL
5649 // from previous query. We wait 3% of TTL here.
5650 AdvanceTime(3600 - 1);
5651 }
5652
5653 VerifyOrQuit(sDnsMessages.IsEmpty());
5654
5655 // Wait for 2% of TTL of 120 which is 2.4 sec.
5656
5657 AdvanceTime(2400 + 1);
5658
5659 VerifyOrQuit(!sDnsMessages.IsEmpty());
5660 dnsMsg = sDnsMessages.GetHead();
5661 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5662 dnsMsg->ValidateAsQueryFor(resolver);
5663 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5664
5665 sDnsMessages.Clear();
5666 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5667 }
5668
5669 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5670 Log("Check TTL timeout and callback result.");
5671
5672 AdvanceTime(6 * 1000);
5673
5674 srvCallback = sSrvCallbacks.GetHead();
5675
5676 for (uint8_t iter = 0; iter < 2; iter++)
5677 {
5678 VerifyOrQuit(srvCallback != nullptr);
5679 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5680 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5681 VerifyOrQuit(srvCallback->mTtl == 0);
5682 srvCallback = srvCallback->GetNext();
5683 }
5684
5685 VerifyOrQuit(srvCallback == nullptr);
5686
5687 VerifyOrQuit(sDnsMessages.IsEmpty());
5688
5689 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5690
5691 sSrvCallbacks.Clear();
5692 sDnsMessages.Clear();
5693
5694 AdvanceTime(200 * 1000);
5695
5696 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5697 VerifyOrQuit(sDnsMessages.IsEmpty());
5698
5699 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5700 Log("Stop the second resolver");
5701
5702 sSrvCallbacks.Clear();
5703
5704 SuccessOrQuit(mdns->StopSrvResolver(resolver2));
5705
5706 AdvanceTime(100 * 1000);
5707
5708 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5709 VerifyOrQuit(sDnsMessages.IsEmpty());
5710
5711 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5712 Log("Send a new response and make sure result callback is invoked");
5713
5714 SendSrvResponse("mysrv._srv._udp.local.", "myhost.local.", 1234, 2, 3, 120, kInAnswerSection);
5715
5716 AdvanceTime(1);
5717
5718 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5719 srvCallback = sSrvCallbacks.GetHead();
5720 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5721 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5722 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5723 VerifyOrQuit(srvCallback->mPort == 1234);
5724 VerifyOrQuit(srvCallback->mPriority == 2);
5725 VerifyOrQuit(srvCallback->mWeight == 3);
5726 VerifyOrQuit(srvCallback->mTtl == 120);
5727 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5728
5729 VerifyOrQuit(sDnsMessages.IsEmpty());
5730
5731 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5732 Log("Stop the resolver. There is no active resolver. Ensure no queries are sent");
5733
5734 sSrvCallbacks.Clear();
5735
5736 SuccessOrQuit(mdns->StopSrvResolver(resolver));
5737
5738 AdvanceTime(20 * 1000);
5739
5740 VerifyOrQuit(sSrvCallbacks.IsEmpty());
5741 VerifyOrQuit(sDnsMessages.IsEmpty());
5742
5743 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5744 Log("Restart the resolver with more than half of TTL remaining.");
5745 Log("Ensure cached entry is reported in the result callback and no queries are sent.");
5746
5747 SuccessOrQuit(mdns->StartSrvResolver(resolver));
5748
5749 AdvanceTime(1);
5750
5751 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5752 srvCallback = sSrvCallbacks.GetHead();
5753 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5754 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5755 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5756 VerifyOrQuit(srvCallback->mPort == 1234);
5757 VerifyOrQuit(srvCallback->mPriority == 2);
5758 VerifyOrQuit(srvCallback->mWeight == 3);
5759 VerifyOrQuit(srvCallback->mTtl == 120);
5760 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5761
5762 VerifyOrQuit(sDnsMessages.IsEmpty());
5763
5764 AdvanceTime(20 * 1000);
5765
5766 VerifyOrQuit(sDnsMessages.IsEmpty());
5767
5768 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5769 Log("Stop and start the resolver again after less than half TTL remaining.");
5770 Log("Ensure cached entry is still reported in the result callback but queries should be sent");
5771
5772 sSrvCallbacks.Clear();
5773
5774 SuccessOrQuit(mdns->StopSrvResolver(resolver));
5775
5776 AdvanceTime(25 * 1000);
5777
5778 SuccessOrQuit(mdns->StartSrvResolver(resolver));
5779
5780 AdvanceTime(1);
5781
5782 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
5783 srvCallback = sSrvCallbacks.GetHead();
5784 VerifyOrQuit(srvCallback->mServiceInstance.Matches("mysrv"));
5785 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
5786 VerifyOrQuit(srvCallback->mHostName.Matches("myhost"));
5787 VerifyOrQuit(srvCallback->mPort == 1234);
5788 VerifyOrQuit(srvCallback->mPriority == 2);
5789 VerifyOrQuit(srvCallback->mWeight == 3);
5790 VerifyOrQuit(srvCallback->mTtl == 120);
5791 VerifyOrQuit(srvCallback->GetNext() == nullptr);
5792
5793 sSrvCallbacks.Clear();
5794
5795 AdvanceTime(15 * 1000);
5796
5797 dnsMsg = sDnsMessages.GetHead();
5798
5799 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
5800 {
5801 VerifyOrQuit(dnsMsg != nullptr);
5802 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5803 dnsMsg->ValidateAsQueryFor(resolver);
5804 dnsMsg = dnsMsg->GetNext();
5805 }
5806
5807 VerifyOrQuit(dnsMsg == nullptr);
5808
5809 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5810
5811 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
5812 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
5813
5814 Log("End of test");
5815
5816 testFreeInstance(sInstance);
5817 }
5818
TestTxtResolver(void)5819 void TestTxtResolver(void)
5820 {
5821 Core *mdns = InitTest();
5822 Core::TxtResolver resolver;
5823 Core::TxtResolver resolver2;
5824 const DnsMessage *dnsMsg;
5825 const TxtCallback *txtCallback;
5826 uint16_t heapAllocations;
5827
5828 Log("-------------------------------------------------------------------------------------------");
5829 Log("TestTxtResolver");
5830
5831 AdvanceTime(1);
5832
5833 heapAllocations = sHeapAllocatedPtrs.GetLength();
5834 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
5835
5836 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5837 Log("Start a TXT resolver. Validate initial queries.");
5838
5839 ClearAllBytes(resolver);
5840
5841 resolver.mServiceInstance = "mysrv";
5842 resolver.mServiceType = "_srv._udp";
5843 resolver.mInfraIfIndex = kInfraIfIndex;
5844 resolver.mCallback = HandleTxtResult;
5845
5846 sDnsMessages.Clear();
5847 SuccessOrQuit(mdns->StartTxtResolver(resolver));
5848
5849 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
5850 {
5851 sDnsMessages.Clear();
5852
5853 AdvanceTime((queryCount == 0) ? 125 : (1U << (queryCount - 1)) * 1000);
5854
5855 VerifyOrQuit(!sDnsMessages.IsEmpty());
5856 dnsMsg = sDnsMessages.GetHead();
5857 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
5858 dnsMsg->ValidateAsQueryFor(resolver);
5859 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
5860 }
5861
5862 sDnsMessages.Clear();
5863
5864 AdvanceTime(20 * 1000);
5865 VerifyOrQuit(sDnsMessages.IsEmpty());
5866
5867 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5868 Log("Send a response. Validate callback result.");
5869
5870 sTxtCallbacks.Clear();
5871
5872 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
5873
5874 AdvanceTime(1);
5875
5876 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5877 txtCallback = sTxtCallbacks.GetHead();
5878 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5879 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5880 VerifyOrQuit(txtCallback->Matches(kTxtData1));
5881 VerifyOrQuit(txtCallback->mTtl == 120);
5882 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5883
5884 VerifyOrQuit(sDnsMessages.IsEmpty());
5885
5886 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5887 Log("Send an updated response changing TXT data. Validate callback result.");
5888
5889 AdvanceTime(1000);
5890
5891 sTxtCallbacks.Clear();
5892
5893 SendTxtResponse("mysrv._srv._udp.local.", kTxtData2, sizeof(kTxtData2), 120, kInAnswerSection);
5894
5895 AdvanceTime(1);
5896
5897 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5898 txtCallback = sTxtCallbacks.GetHead();
5899 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5900 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5901 VerifyOrQuit(txtCallback->Matches(kTxtData2));
5902 VerifyOrQuit(txtCallback->mTtl == 120);
5903 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5904
5905 VerifyOrQuit(sDnsMessages.IsEmpty());
5906
5907 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5908 Log("Send an updated response changing TXT data to empty. Validate callback result.");
5909
5910 AdvanceTime(1000);
5911
5912 sTxtCallbacks.Clear();
5913
5914 SendTxtResponse("mysrv._srv._udp.local.", kEmptyTxtData, sizeof(kEmptyTxtData), 120, kInAnswerSection);
5915
5916 AdvanceTime(1);
5917
5918 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5919 txtCallback = sTxtCallbacks.GetHead();
5920 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5921 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5922 VerifyOrQuit(txtCallback->Matches(kEmptyTxtData));
5923 VerifyOrQuit(txtCallback->mTtl == 120);
5924 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5925
5926 VerifyOrQuit(sDnsMessages.IsEmpty());
5927
5928 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5929 Log("Send an updated response changing TTL. Validate callback result.");
5930
5931 AdvanceTime(1000);
5932
5933 sTxtCallbacks.Clear();
5934
5935 SendTxtResponse("mysrv._srv._udp.local.", kEmptyTxtData, sizeof(kEmptyTxtData), 500, kInAnswerSection);
5936
5937 AdvanceTime(1);
5938
5939 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5940 txtCallback = sTxtCallbacks.GetHead();
5941 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5942 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5943 VerifyOrQuit(txtCallback->Matches(kEmptyTxtData));
5944 VerifyOrQuit(txtCallback->mTtl == 500);
5945 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5946
5947 VerifyOrQuit(sDnsMessages.IsEmpty());
5948
5949 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5950 Log("Send an updated response with zero TTL. Validate callback result.");
5951
5952 AdvanceTime(1000);
5953
5954 sTxtCallbacks.Clear();
5955
5956 SendTxtResponse("mysrv._srv._udp.local.", kEmptyTxtData, sizeof(kEmptyTxtData), 0, kInAnswerSection);
5957
5958 AdvanceTime(1);
5959
5960 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5961 txtCallback = sTxtCallbacks.GetHead();
5962 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5963 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5964 VerifyOrQuit(txtCallback->mTtl == 0);
5965 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5966
5967 VerifyOrQuit(sDnsMessages.IsEmpty());
5968
5969 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5970 Log("Send an updated response. Validate callback result.");
5971
5972 sTxtCallbacks.Clear();
5973 AdvanceTime(100 * 1000);
5974
5975 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
5976
5977 AdvanceTime(1);
5978
5979 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
5980 txtCallback = sTxtCallbacks.GetHead();
5981 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
5982 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
5983 VerifyOrQuit(txtCallback->Matches(kTxtData1));
5984 VerifyOrQuit(txtCallback->mTtl == 120);
5985 VerifyOrQuit(txtCallback->GetNext() == nullptr);
5986
5987 VerifyOrQuit(sDnsMessages.IsEmpty());
5988
5989 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
5990 Log("Send a response with no changes. Validate callback is not invoked.");
5991
5992 AdvanceTime(1000);
5993
5994 sTxtCallbacks.Clear();
5995
5996 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
5997
5998 AdvanceTime(100);
5999
6000 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6001 VerifyOrQuit(sDnsMessages.IsEmpty());
6002
6003 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6004 Log("Start another resolver for the same service and different callback. Validate results.");
6005
6006 resolver2.mServiceInstance = "mysrv";
6007 resolver2.mServiceType = "_srv._udp";
6008 resolver2.mInfraIfIndex = kInfraIfIndex;
6009 resolver2.mCallback = HandleTxtResultAlternate;
6010
6011 sTxtCallbacks.Clear();
6012
6013 SuccessOrQuit(mdns->StartTxtResolver(resolver2));
6014
6015 AdvanceTime(1);
6016
6017 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
6018 txtCallback = sTxtCallbacks.GetHead();
6019 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
6020 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6021 VerifyOrQuit(txtCallback->Matches(kTxtData1));
6022 VerifyOrQuit(txtCallback->mTtl == 120);
6023 VerifyOrQuit(txtCallback->GetNext() == nullptr);
6024
6025 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6026 Log("Start same resolver again and check the returned error.");
6027
6028 sTxtCallbacks.Clear();
6029
6030 VerifyOrQuit(mdns->StartTxtResolver(resolver2) == kErrorAlready);
6031
6032 AdvanceTime(5000);
6033
6034 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6035
6036 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6037 Log("Check query is sent at 80 percentage of TTL and then respond to it.");
6038
6039 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
6040
6041 // First query should be sent at 80-82% of TTL of 120 second (96.0-98.4 sec).
6042 // We wait for 100 second. Note that 5 seconds already passed in the
6043 // previous step.
6044
6045 AdvanceTime(96 * 1000 - 1);
6046
6047 VerifyOrQuit(sDnsMessages.IsEmpty());
6048
6049 AdvanceTime(4 * 1000 + 1);
6050
6051 VerifyOrQuit(!sDnsMessages.IsEmpty());
6052 dnsMsg = sDnsMessages.GetHead();
6053 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6054 dnsMsg->ValidateAsQueryFor(resolver);
6055 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
6056
6057 sDnsMessages.Clear();
6058 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6059
6060 AdvanceTime(10);
6061
6062 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
6063
6064 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6065 Log("Check queries are sent at 80, 85, 90, 95 percentages of TTL.");
6066
6067 for (uint8_t queryCount = 0; queryCount < kNumRefreshQueries; queryCount++)
6068 {
6069 if (queryCount == 0)
6070 {
6071 // First query is expected in 80-82% of TTL, so
6072 // 80% of 120 = 96.0, 82% of 120 = 98.4
6073
6074 AdvanceTime(96 * 1000 - 1);
6075 }
6076 else
6077 {
6078 // Next query should happen within 3%-5% of TTL
6079 // from previous query. We wait 3% of TTL here.
6080 AdvanceTime(3600 - 1);
6081 }
6082
6083 VerifyOrQuit(sDnsMessages.IsEmpty());
6084
6085 // Wait for 2% of TTL of 120 which is 2.4 sec.
6086
6087 AdvanceTime(2400 + 1);
6088
6089 VerifyOrQuit(!sDnsMessages.IsEmpty());
6090 dnsMsg = sDnsMessages.GetHead();
6091 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6092 dnsMsg->ValidateAsQueryFor(resolver);
6093 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
6094
6095 sDnsMessages.Clear();
6096 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6097 }
6098
6099 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6100 Log("Check TTL timeout and callback result.");
6101
6102 AdvanceTime(6 * 1000);
6103
6104 txtCallback = sTxtCallbacks.GetHead();
6105
6106 for (uint8_t iter = 0; iter < 2; iter++)
6107 {
6108 VerifyOrQuit(txtCallback != nullptr);
6109 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
6110 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6111 VerifyOrQuit(txtCallback->mTtl == 0);
6112 txtCallback = txtCallback->GetNext();
6113 }
6114
6115 VerifyOrQuit(txtCallback == nullptr);
6116
6117 VerifyOrQuit(sDnsMessages.IsEmpty());
6118
6119 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6120
6121 sTxtCallbacks.Clear();
6122 sDnsMessages.Clear();
6123
6124 AdvanceTime(200 * 1000);
6125
6126 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6127 VerifyOrQuit(sDnsMessages.IsEmpty());
6128
6129 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6130 Log("Stop the second resolver");
6131
6132 sTxtCallbacks.Clear();
6133
6134 SuccessOrQuit(mdns->StopTxtResolver(resolver2));
6135
6136 AdvanceTime(100 * 1000);
6137
6138 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6139 VerifyOrQuit(sDnsMessages.IsEmpty());
6140
6141 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6142 Log("Send a new response and make sure result callback is invoked");
6143
6144 SendTxtResponse("mysrv._srv._udp.local.", kTxtData1, sizeof(kTxtData1), 120, kInAnswerSection);
6145
6146 AdvanceTime(1);
6147
6148 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
6149 txtCallback = sTxtCallbacks.GetHead();
6150 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
6151 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6152 VerifyOrQuit(txtCallback->Matches(kTxtData1));
6153 VerifyOrQuit(txtCallback->mTtl == 120);
6154 VerifyOrQuit(txtCallback->GetNext() == nullptr);
6155
6156 VerifyOrQuit(sDnsMessages.IsEmpty());
6157
6158 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6159 Log("Stop the resolver. There is no active resolver. Ensure no queries are sent");
6160
6161 sTxtCallbacks.Clear();
6162
6163 SuccessOrQuit(mdns->StopTxtResolver(resolver));
6164
6165 AdvanceTime(20 * 1000);
6166
6167 VerifyOrQuit(sTxtCallbacks.IsEmpty());
6168 VerifyOrQuit(sDnsMessages.IsEmpty());
6169
6170 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6171 Log("Restart the resolver with more than half of TTL remaining.");
6172 Log("Ensure cached entry is reported in the result callback and no queries are sent.");
6173
6174 SuccessOrQuit(mdns->StartTxtResolver(resolver));
6175
6176 AdvanceTime(1);
6177
6178 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
6179 txtCallback = sTxtCallbacks.GetHead();
6180 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
6181 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6182 VerifyOrQuit(txtCallback->Matches(kTxtData1));
6183 VerifyOrQuit(txtCallback->mTtl == 120);
6184 VerifyOrQuit(txtCallback->GetNext() == nullptr);
6185
6186 VerifyOrQuit(sDnsMessages.IsEmpty());
6187
6188 AdvanceTime(20 * 1000);
6189
6190 VerifyOrQuit(sDnsMessages.IsEmpty());
6191
6192 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6193 Log("Stop and start the resolver again after less than half TTL remaining.");
6194 Log("Ensure cached entry is still reported in the result callback but queries should be sent");
6195
6196 sTxtCallbacks.Clear();
6197
6198 SuccessOrQuit(mdns->StopTxtResolver(resolver));
6199
6200 AdvanceTime(25 * 1000);
6201
6202 SuccessOrQuit(mdns->StartTxtResolver(resolver));
6203
6204 AdvanceTime(1);
6205
6206 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
6207 txtCallback = sTxtCallbacks.GetHead();
6208 VerifyOrQuit(txtCallback->mServiceInstance.Matches("mysrv"));
6209 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6210 VerifyOrQuit(txtCallback->Matches(kTxtData1));
6211 VerifyOrQuit(txtCallback->mTtl == 120);
6212 VerifyOrQuit(txtCallback->GetNext() == nullptr);
6213
6214 sTxtCallbacks.Clear();
6215
6216 AdvanceTime(15 * 1000);
6217
6218 dnsMsg = sDnsMessages.GetHead();
6219
6220 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
6221 {
6222 VerifyOrQuit(dnsMsg != nullptr);
6223 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6224 dnsMsg->ValidateAsQueryFor(resolver);
6225 dnsMsg = dnsMsg->GetNext();
6226 }
6227
6228 VerifyOrQuit(dnsMsg == nullptr);
6229
6230 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6231
6232 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
6233 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
6234
6235 Log("End of test");
6236
6237 testFreeInstance(sInstance);
6238 }
6239
TestIp6AddrResolver(void)6240 void TestIp6AddrResolver(void)
6241 {
6242 Core *mdns = InitTest();
6243 Core::AddressResolver resolver;
6244 Core::AddressResolver resolver2;
6245 AddrAndTtl addrs[5];
6246 const DnsMessage *dnsMsg;
6247 const AddrCallback *addrCallback;
6248 uint16_t heapAllocations;
6249
6250 Log("-------------------------------------------------------------------------------------------");
6251 Log("TestIp6AddrResolver");
6252
6253 AdvanceTime(1);
6254
6255 heapAllocations = sHeapAllocatedPtrs.GetLength();
6256 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
6257
6258 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6259 Log("Start an IPv6 address resolver. Validate initial queries.");
6260
6261 ClearAllBytes(resolver);
6262
6263 resolver.mHostName = "myhost";
6264 resolver.mInfraIfIndex = kInfraIfIndex;
6265 resolver.mCallback = HandleAddrResult;
6266
6267 sDnsMessages.Clear();
6268 SuccessOrQuit(mdns->StartIp6AddressResolver(resolver));
6269
6270 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
6271 {
6272 sDnsMessages.Clear();
6273
6274 AdvanceTime((queryCount == 0) ? 125 : (1U << (queryCount - 1)) * 1000);
6275
6276 VerifyOrQuit(!sDnsMessages.IsEmpty());
6277 dnsMsg = sDnsMessages.GetHead();
6278 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6279 dnsMsg->ValidateAsQueryFor(resolver);
6280 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
6281 }
6282
6283 sDnsMessages.Clear();
6284
6285 AdvanceTime(20 * 1000);
6286 VerifyOrQuit(sDnsMessages.IsEmpty());
6287
6288 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6289 Log("Send a response. Validate callback result.");
6290
6291 sAddrCallbacks.Clear();
6292
6293 SuccessOrQuit(addrs[0].mAddress.FromString("fd00::1"));
6294 addrs[0].mTtl = 120;
6295
6296 SendHostAddrResponse("myhost.local.", addrs, 1, /* aCachFlush */ true, kInAnswerSection);
6297
6298 AdvanceTime(1);
6299
6300 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6301 addrCallback = sAddrCallbacks.GetHead();
6302 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6303 VerifyOrQuit(addrCallback->Matches(addrs, 1));
6304 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6305
6306 VerifyOrQuit(sDnsMessages.IsEmpty());
6307
6308 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6309 Log("Send an updated response adding a new address. Validate callback result.");
6310
6311 SuccessOrQuit(addrs[1].mAddress.FromString("fd00::2"));
6312 addrs[1].mTtl = 120;
6313
6314 AdvanceTime(1000);
6315
6316 sAddrCallbacks.Clear();
6317
6318 SendHostAddrResponse("myhost.local.", addrs, 2, /* aCachFlush */ true, kInAnswerSection);
6319
6320 AdvanceTime(1);
6321
6322 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6323 addrCallback = sAddrCallbacks.GetHead();
6324 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6325 VerifyOrQuit(addrCallback->Matches(addrs, 2));
6326 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6327
6328 VerifyOrQuit(sDnsMessages.IsEmpty());
6329
6330 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6331 Log("Send an updated response adding and removing addresses. Validate callback result.");
6332
6333 SuccessOrQuit(addrs[0].mAddress.FromString("fd00::2"));
6334 SuccessOrQuit(addrs[1].mAddress.FromString("fd00::aa"));
6335 SuccessOrQuit(addrs[2].mAddress.FromString("fe80::bb"));
6336 addrs[0].mTtl = 120;
6337 addrs[1].mTtl = 120;
6338 addrs[2].mTtl = 120;
6339
6340 AdvanceTime(1000);
6341
6342 sAddrCallbacks.Clear();
6343
6344 SendHostAddrResponse("myhost.local.", addrs, 3, /* aCachFlush */ true, kInAnswerSection);
6345
6346 AdvanceTime(1);
6347
6348 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6349 addrCallback = sAddrCallbacks.GetHead();
6350 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6351 VerifyOrQuit(addrCallback->Matches(addrs, 3));
6352 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6353
6354 VerifyOrQuit(sDnsMessages.IsEmpty());
6355
6356 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6357 Log("Send a response without cache flush adding an address. Validate callback result.");
6358
6359 SuccessOrQuit(addrs[3].mAddress.FromString("fd00::3"));
6360 addrs[3].mTtl = 500;
6361
6362 AdvanceTime(1000);
6363
6364 sAddrCallbacks.Clear();
6365
6366 SendHostAddrResponse("myhost.local.", &addrs[3], 1, /* aCachFlush */ false, kInAnswerSection);
6367
6368 AdvanceTime(1);
6369
6370 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6371 addrCallback = sAddrCallbacks.GetHead();
6372 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6373 VerifyOrQuit(addrCallback->Matches(addrs, 4));
6374 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6375
6376 VerifyOrQuit(sDnsMessages.IsEmpty());
6377
6378 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6379 Log("Send a response without cache flush with existing addresses. Validate that callback is not called.");
6380
6381 AdvanceTime(1000);
6382
6383 sAddrCallbacks.Clear();
6384
6385 SendHostAddrResponse("myhost.local.", &addrs[2], 2, /* aCachFlush */ false, kInAnswerSection);
6386
6387 AdvanceTime(1);
6388
6389 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6390 VerifyOrQuit(sDnsMessages.IsEmpty());
6391
6392 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6393 Log("Send a response without no changes to the list. Validate that callback is not called");
6394
6395 AdvanceTime(1000);
6396
6397 sAddrCallbacks.Clear();
6398
6399 SendHostAddrResponse("myhost.local.", addrs, 4, /* aCachFlush */ true, kInAdditionalSection);
6400
6401 AdvanceTime(1);
6402
6403 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6404 VerifyOrQuit(sDnsMessages.IsEmpty());
6405
6406 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6407 Log("Send a response without cache flush updating TTL of existing address. Validate callback result.");
6408
6409 addrs[3].mTtl = 200;
6410
6411 AdvanceTime(1000);
6412
6413 sAddrCallbacks.Clear();
6414
6415 SendHostAddrResponse("myhost.local.", &addrs[3], 1, /* aCachFlush */ false, kInAnswerSection);
6416
6417 AdvanceTime(1);
6418
6419 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6420 addrCallback = sAddrCallbacks.GetHead();
6421 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6422 VerifyOrQuit(addrCallback->Matches(addrs, 4));
6423 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6424
6425 VerifyOrQuit(sDnsMessages.IsEmpty());
6426
6427 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6428 Log("Send a response without cache flush removing an address (zero TTL). Validate callback result.");
6429
6430 addrs[3].mTtl = 0;
6431
6432 AdvanceTime(1000);
6433
6434 sAddrCallbacks.Clear();
6435
6436 SendHostAddrResponse("myhost.local.", &addrs[3], 1, /* aCachFlush */ false, kInAnswerSection);
6437
6438 AdvanceTime(1);
6439
6440 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6441 addrCallback = sAddrCallbacks.GetHead();
6442 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6443 VerifyOrQuit(addrCallback->Matches(addrs, 3));
6444 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6445
6446 VerifyOrQuit(sDnsMessages.IsEmpty());
6447
6448 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6449 Log("Send a response with cache flush removing all addresses. Validate callback result.");
6450
6451 addrs[0].mTtl = 0;
6452
6453 AdvanceTime(1000);
6454
6455 sAddrCallbacks.Clear();
6456
6457 SendHostAddrResponse("myhost.local.", addrs, 1, /* aCachFlush */ true, kInAnswerSection);
6458
6459 AdvanceTime(1);
6460
6461 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6462 addrCallback = sAddrCallbacks.GetHead();
6463 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6464 VerifyOrQuit(addrCallback->Matches(addrs, 0));
6465 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6466
6467 VerifyOrQuit(sDnsMessages.IsEmpty());
6468
6469 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6470 Log("Send a response with addresses with different TTL. Validate callback result");
6471
6472 SuccessOrQuit(addrs[0].mAddress.FromString("fd00::00"));
6473 SuccessOrQuit(addrs[1].mAddress.FromString("fd00::11"));
6474 SuccessOrQuit(addrs[2].mAddress.FromString("fe80::22"));
6475 SuccessOrQuit(addrs[3].mAddress.FromString("fe80::33"));
6476 addrs[0].mTtl = 120;
6477 addrs[1].mTtl = 800;
6478 addrs[2].mTtl = 2000;
6479 addrs[3].mTtl = 8000;
6480
6481 AdvanceTime(5 * 1000);
6482
6483 sAddrCallbacks.Clear();
6484
6485 SendHostAddrResponse("myhost.local.", addrs, 4, /* aCachFlush */ true, kInAnswerSection);
6486
6487 AdvanceTime(1);
6488
6489 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6490 addrCallback = sAddrCallbacks.GetHead();
6491 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6492 VerifyOrQuit(addrCallback->Matches(addrs, 4));
6493 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6494
6495 VerifyOrQuit(sDnsMessages.IsEmpty());
6496
6497 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6498 Log("Start another resolver for the same host and different callback. Validate results.");
6499
6500 resolver2.mHostName = "myhost";
6501 resolver2.mInfraIfIndex = kInfraIfIndex;
6502 resolver2.mCallback = HandleAddrResultAlternate;
6503
6504 sAddrCallbacks.Clear();
6505
6506 SuccessOrQuit(mdns->StartIp6AddressResolver(resolver2));
6507
6508 AdvanceTime(1);
6509
6510 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6511 addrCallback = sAddrCallbacks.GetHead();
6512 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6513 VerifyOrQuit(addrCallback->Matches(addrs, 4));
6514 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6515
6516 VerifyOrQuit(sDnsMessages.IsEmpty());
6517
6518 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6519 Log("Start same resolver again and check the returned error.");
6520
6521 sAddrCallbacks.Clear();
6522
6523 VerifyOrQuit(mdns->StartIp6AddressResolver(resolver2) == kErrorAlready);
6524
6525 AdvanceTime(5000);
6526
6527 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6528 sDnsMessages.Clear();
6529
6530 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6531 Log("Check query is sent at 80 percentage of TTL and then respond to it.");
6532
6533 SendHostAddrResponse("myhost.local.", addrs, 4, /* aCachFlush */ true, kInAnswerSection);
6534
6535 // First query should be sent at 80-82% of TTL of 120 second (96.0-98.4 sec).
6536 // We wait for 100 second. Note that 5 seconds already passed in the
6537 // previous step.
6538
6539 AdvanceTime(96 * 1000 - 1);
6540
6541 VerifyOrQuit(sDnsMessages.IsEmpty());
6542
6543 AdvanceTime(4 * 1000 + 1);
6544
6545 VerifyOrQuit(!sDnsMessages.IsEmpty());
6546 dnsMsg = sDnsMessages.GetHead();
6547 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6548 dnsMsg->ValidateAsQueryFor(resolver);
6549 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
6550
6551 sDnsMessages.Clear();
6552 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6553
6554 AdvanceTime(10);
6555
6556 SendHostAddrResponse("myhost.local.", addrs, 4, /* aCachFlush */ true, kInAnswerSection);
6557
6558 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6559 Log("Check queries are sent at 80, 85, 90, 95 percentages of TTL.");
6560
6561 for (uint8_t queryCount = 0; queryCount < kNumRefreshQueries; queryCount++)
6562 {
6563 if (queryCount == 0)
6564 {
6565 // First query is expected in 80-82% of TTL, so
6566 // 80% of 120 = 96.0, 82% of 120 = 98.4
6567
6568 AdvanceTime(96 * 1000 - 1);
6569 }
6570 else
6571 {
6572 // Next query should happen within 3%-5% of TTL
6573 // from previous query. We wait 3% of TTL here.
6574 AdvanceTime(3600 - 1);
6575 }
6576
6577 VerifyOrQuit(sDnsMessages.IsEmpty());
6578
6579 // Wait for 2% of TTL of 120 which is 2.4 sec.
6580
6581 AdvanceTime(2400 + 1);
6582
6583 VerifyOrQuit(!sDnsMessages.IsEmpty());
6584 dnsMsg = sDnsMessages.GetHead();
6585 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6586 dnsMsg->ValidateAsQueryFor(resolver);
6587 VerifyOrQuit(dnsMsg->GetNext() == nullptr);
6588
6589 sDnsMessages.Clear();
6590 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6591 }
6592
6593 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6594 Log("Check TTL timeout of first address (TTL 120) and callback result.");
6595
6596 AdvanceTime(6 * 1000);
6597
6598 addrCallback = sAddrCallbacks.GetHead();
6599
6600 for (uint8_t iter = 0; iter < 2; iter++)
6601 {
6602 VerifyOrQuit(addrCallback != nullptr);
6603 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6604 VerifyOrQuit(addrCallback->Matches(&addrs[1], 3));
6605 addrCallback = addrCallback->GetNext();
6606 }
6607
6608 VerifyOrQuit(addrCallback == nullptr);
6609
6610 VerifyOrQuit(sDnsMessages.IsEmpty());
6611
6612 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6613 Log("Check TTL timeout of next address (TTL 800) and callback result.");
6614
6615 sAddrCallbacks.Clear();
6616
6617 AdvanceTime((800 - 120) * 1000);
6618
6619 addrCallback = sAddrCallbacks.GetHead();
6620
6621 for (uint8_t iter = 0; iter < 2; iter++)
6622 {
6623 VerifyOrQuit(addrCallback != nullptr);
6624 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6625 VerifyOrQuit(addrCallback->Matches(&addrs[2], 2));
6626 addrCallback = addrCallback->GetNext();
6627 }
6628
6629 VerifyOrQuit(addrCallback == nullptr);
6630
6631 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6632
6633 sAddrCallbacks.Clear();
6634 sDnsMessages.Clear();
6635
6636 AdvanceTime(200 * 1000);
6637
6638 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6639 VerifyOrQuit(sDnsMessages.IsEmpty());
6640
6641 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6642 Log("Stop the second resolver");
6643
6644 sAddrCallbacks.Clear();
6645
6646 SuccessOrQuit(mdns->StopIp6AddressResolver(resolver2));
6647
6648 AdvanceTime(100 * 1000);
6649
6650 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6651 VerifyOrQuit(sDnsMessages.IsEmpty());
6652
6653 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6654 Log("Send a new response and make sure result callback is invoked");
6655
6656 sAddrCallbacks.Clear();
6657
6658 SendHostAddrResponse("myhost.local.", addrs, 1, /* aCachFlush */ true, kInAnswerSection);
6659
6660 AdvanceTime(1);
6661
6662 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6663 addrCallback = sAddrCallbacks.GetHead();
6664 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6665 VerifyOrQuit(addrCallback->Matches(addrs, 1));
6666 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6667
6668 VerifyOrQuit(sDnsMessages.IsEmpty());
6669
6670 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6671 Log("Stop the resolver. There is no active resolver. Ensure no queries are sent");
6672
6673 sAddrCallbacks.Clear();
6674
6675 SuccessOrQuit(mdns->StopIp6AddressResolver(resolver));
6676
6677 AdvanceTime(20 * 1000);
6678
6679 VerifyOrQuit(sAddrCallbacks.IsEmpty());
6680 VerifyOrQuit(sDnsMessages.IsEmpty());
6681
6682 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6683 Log("Restart the resolver with more than half of TTL remaining.");
6684 Log("Ensure cached entry is reported in the result callback and no queries are sent.");
6685
6686 SuccessOrQuit(mdns->StartIp6AddressResolver(resolver));
6687
6688 AdvanceTime(1);
6689
6690 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6691 addrCallback = sAddrCallbacks.GetHead();
6692 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6693 VerifyOrQuit(addrCallback->Matches(addrs, 1));
6694 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6695
6696 VerifyOrQuit(sDnsMessages.IsEmpty());
6697
6698 AdvanceTime(20 * 1000);
6699
6700 VerifyOrQuit(sDnsMessages.IsEmpty());
6701
6702 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6703 Log("Stop and start the resolver again after less than half TTL remaining.");
6704 Log("Ensure cached entry is still reported in the result callback but queries should be sent");
6705
6706 sAddrCallbacks.Clear();
6707
6708 SuccessOrQuit(mdns->StopIp6AddressResolver(resolver));
6709
6710 AdvanceTime(25 * 1000);
6711
6712 SuccessOrQuit(mdns->StartIp6AddressResolver(resolver));
6713
6714 AdvanceTime(1);
6715
6716 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6717 addrCallback = sAddrCallbacks.GetHead();
6718 VerifyOrQuit(addrCallback->mHostName.Matches("myhost"));
6719 VerifyOrQuit(addrCallback->Matches(addrs, 1));
6720 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6721
6722 sAddrCallbacks.Clear();
6723
6724 AdvanceTime(15 * 1000);
6725
6726 dnsMsg = sDnsMessages.GetHead();
6727
6728 for (uint8_t queryCount = 0; queryCount < kNumInitalQueries; queryCount++)
6729 {
6730 VerifyOrQuit(dnsMsg != nullptr);
6731 dnsMsg->ValidateHeader(kMulticastQuery, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 0);
6732 dnsMsg->ValidateAsQueryFor(resolver);
6733 dnsMsg = dnsMsg->GetNext();
6734 }
6735
6736 VerifyOrQuit(dnsMsg == nullptr);
6737
6738 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6739
6740 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
6741 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
6742
6743 Log("End of test");
6744
6745 testFreeInstance(sInstance);
6746 }
6747
TestPassiveCache(void)6748 void TestPassiveCache(void)
6749 {
6750 static const char *const kSubTypes[] = {"_sub1", "_xyzw"};
6751
6752 Core *mdns = InitTest();
6753 Core::Browser browser;
6754 Core::SrvResolver srvResolver;
6755 Core::TxtResolver txtResolver;
6756 Core::AddressResolver addrResolver;
6757 Core::Host host1;
6758 Core::Host host2;
6759 Core::Service service1;
6760 Core::Service service2;
6761 Core::Service service3;
6762 Ip6::Address host1Addresses[3];
6763 Ip6::Address host2Addresses[2];
6764 AddrAndTtl host1AddrTtls[3];
6765 AddrAndTtl host2AddrTtls[2];
6766 const DnsMessage *dnsMsg;
6767 BrowseCallback *browseCallback;
6768 SrvCallback *srvCallback;
6769 TxtCallback *txtCallback;
6770 AddrCallback *addrCallback;
6771 uint16_t heapAllocations;
6772
6773 Log("-------------------------------------------------------------------------------------------");
6774 Log("TestPassiveCache");
6775
6776 AdvanceTime(1);
6777
6778 heapAllocations = sHeapAllocatedPtrs.GetLength();
6779 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
6780
6781 SuccessOrQuit(host1Addresses[0].FromString("fd00::1:aaaa"));
6782 SuccessOrQuit(host1Addresses[1].FromString("fd00::1:bbbb"));
6783 SuccessOrQuit(host1Addresses[2].FromString("fd00::1:cccc"));
6784 host1.mHostName = "host1";
6785 host1.mAddresses = host1Addresses;
6786 host1.mAddressesLength = 3;
6787 host1.mTtl = 1500;
6788
6789 host1AddrTtls[0].mAddress = host1Addresses[0];
6790 host1AddrTtls[1].mAddress = host1Addresses[1];
6791 host1AddrTtls[2].mAddress = host1Addresses[2];
6792 host1AddrTtls[0].mTtl = host1.mTtl;
6793 host1AddrTtls[1].mTtl = host1.mTtl;
6794 host1AddrTtls[2].mTtl = host1.mTtl;
6795
6796 SuccessOrQuit(host2Addresses[0].FromString("fd00::2:eeee"));
6797 SuccessOrQuit(host2Addresses[1].FromString("fd00::2:ffff"));
6798 host2.mHostName = "host2";
6799 host2.mAddresses = host2Addresses;
6800 host2.mAddressesLength = 2;
6801 host2.mTtl = 1500;
6802
6803 host2AddrTtls[0].mAddress = host2Addresses[0];
6804 host2AddrTtls[1].mAddress = host2Addresses[1];
6805 host2AddrTtls[0].mTtl = host2.mTtl;
6806 host2AddrTtls[1].mTtl = host2.mTtl;
6807
6808 service1.mHostName = host1.mHostName;
6809 service1.mServiceInstance = "srv1";
6810 service1.mServiceType = "_srv._udp";
6811 service1.mSubTypeLabels = kSubTypes;
6812 service1.mSubTypeLabelsLength = 2;
6813 service1.mTxtData = kTxtData1;
6814 service1.mTxtDataLength = sizeof(kTxtData1);
6815 service1.mPort = 1111;
6816 service1.mPriority = 0;
6817 service1.mWeight = 0;
6818 service1.mTtl = 1500;
6819
6820 service2.mHostName = host1.mHostName;
6821 service2.mServiceInstance = "srv2";
6822 service2.mServiceType = "_tst._tcp";
6823 service2.mSubTypeLabels = nullptr;
6824 service2.mSubTypeLabelsLength = 0;
6825 service2.mTxtData = nullptr;
6826 service2.mTxtDataLength = 0;
6827 service2.mPort = 2222;
6828 service2.mPriority = 2;
6829 service2.mWeight = 2;
6830 service2.mTtl = 1500;
6831
6832 service3.mHostName = host2.mHostName;
6833 service3.mServiceInstance = "srv3";
6834 service3.mServiceType = "_srv._udp";
6835 service3.mSubTypeLabels = kSubTypes;
6836 service3.mSubTypeLabelsLength = 1;
6837 service3.mTxtData = kTxtData2;
6838 service3.mTxtDataLength = sizeof(kTxtData2);
6839 service3.mPort = 3333;
6840 service3.mPriority = 3;
6841 service3.mWeight = 3;
6842 service3.mTtl = 1500;
6843
6844 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6845 Log("Register 2 hosts and 3 services");
6846
6847 SuccessOrQuit(mdns->RegisterHost(host1, 0, HandleSuccessCallback));
6848 SuccessOrQuit(mdns->RegisterHost(host2, 1, HandleSuccessCallback));
6849 SuccessOrQuit(mdns->RegisterService(service1, 2, HandleSuccessCallback));
6850 SuccessOrQuit(mdns->RegisterService(service2, 3, HandleSuccessCallback));
6851 SuccessOrQuit(mdns->RegisterService(service3, 4, HandleSuccessCallback));
6852
6853 AdvanceTime(10 * 1000);
6854
6855 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6856 Log("Start a browser for `_srv._udp`, validate callback result");
6857
6858 browser.mServiceType = "_srv._udp";
6859 browser.mSubTypeLabel = nullptr;
6860 browser.mInfraIfIndex = kInfraIfIndex;
6861 browser.mCallback = HandleBrowseResult;
6862
6863 sBrowseCallbacks.Clear();
6864
6865 SuccessOrQuit(mdns->StartBrowser(browser));
6866
6867 AdvanceTime(350);
6868
6869 browseCallback = sBrowseCallbacks.GetHead();
6870
6871 for (uint8_t iter = 0; iter < 2; iter++)
6872 {
6873 VerifyOrQuit(browseCallback != nullptr);
6874
6875 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
6876 VerifyOrQuit(!browseCallback->mIsSubType);
6877 VerifyOrQuit(browseCallback->mServiceInstance.Matches("srv1") ||
6878 browseCallback->mServiceInstance.Matches("srv3"));
6879 VerifyOrQuit(browseCallback->mTtl == 1500);
6880
6881 browseCallback = browseCallback->GetNext();
6882 }
6883
6884 VerifyOrQuit(browseCallback == nullptr);
6885
6886 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6887 Log("Start SRV and TXT resolvers for the srv1 and for its host name.");
6888 Log("Ensure all results are immediately provided from cache.");
6889
6890 srvResolver.mServiceInstance = "srv1";
6891 srvResolver.mServiceType = "_srv._udp";
6892 srvResolver.mInfraIfIndex = kInfraIfIndex;
6893 srvResolver.mCallback = HandleSrvResult;
6894
6895 txtResolver.mServiceInstance = "srv1";
6896 txtResolver.mServiceType = "_srv._udp";
6897 txtResolver.mInfraIfIndex = kInfraIfIndex;
6898 txtResolver.mCallback = HandleTxtResult;
6899
6900 addrResolver.mHostName = "host1";
6901 addrResolver.mInfraIfIndex = kInfraIfIndex;
6902 addrResolver.mCallback = HandleAddrResult;
6903
6904 sSrvCallbacks.Clear();
6905 sTxtCallbacks.Clear();
6906 sAddrCallbacks.Clear();
6907 sDnsMessages.Clear();
6908
6909 SuccessOrQuit(mdns->StartSrvResolver(srvResolver));
6910 SuccessOrQuit(mdns->StartTxtResolver(txtResolver));
6911 SuccessOrQuit(mdns->StartIp6AddressResolver(addrResolver));
6912
6913 AdvanceTime(1);
6914
6915 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
6916 srvCallback = sSrvCallbacks.GetHead();
6917 VerifyOrQuit(srvCallback->mServiceInstance.Matches("srv1"));
6918 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
6919 VerifyOrQuit(srvCallback->mHostName.Matches("host1"));
6920 VerifyOrQuit(srvCallback->mPort == 1111);
6921 VerifyOrQuit(srvCallback->mPriority == 0);
6922 VerifyOrQuit(srvCallback->mWeight == 0);
6923 VerifyOrQuit(srvCallback->mTtl == 1500);
6924 VerifyOrQuit(srvCallback->GetNext() == nullptr);
6925
6926 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
6927 txtCallback = sTxtCallbacks.GetHead();
6928 VerifyOrQuit(txtCallback->mServiceInstance.Matches("srv1"));
6929 VerifyOrQuit(txtCallback->mServiceType.Matches("_srv._udp"));
6930 VerifyOrQuit(txtCallback->Matches(kTxtData1));
6931 VerifyOrQuit(txtCallback->mTtl == 1500);
6932 VerifyOrQuit(txtCallback->GetNext() == nullptr);
6933
6934 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
6935 addrCallback = sAddrCallbacks.GetHead();
6936 VerifyOrQuit(addrCallback->mHostName.Matches("host1"));
6937 VerifyOrQuit(addrCallback->Matches(host1AddrTtls, 3));
6938 VerifyOrQuit(addrCallback->GetNext() == nullptr);
6939
6940 AdvanceTime(400);
6941
6942 VerifyOrQuit(sDnsMessages.IsEmpty());
6943
6944 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6945 Log("Start a browser for sub-type service, validate callback result");
6946
6947 browser.mServiceType = "_srv._udp";
6948 browser.mSubTypeLabel = "_xyzw";
6949 browser.mInfraIfIndex = kInfraIfIndex;
6950 browser.mCallback = HandleBrowseResult;
6951
6952 sBrowseCallbacks.Clear();
6953
6954 SuccessOrQuit(mdns->StartBrowser(browser));
6955
6956 AdvanceTime(350);
6957
6958 browseCallback = sBrowseCallbacks.GetHead();
6959 VerifyOrQuit(browseCallback != nullptr);
6960
6961 VerifyOrQuit(browseCallback->mServiceType.Matches("_srv._udp"));
6962 VerifyOrQuit(browseCallback->mIsSubType);
6963 VerifyOrQuit(browseCallback->mSubTypeLabel.Matches("_xyzw"));
6964 VerifyOrQuit(browseCallback->mServiceInstance.Matches("srv1"));
6965 VerifyOrQuit(browseCallback->mTtl == 1500);
6966 VerifyOrQuit(browseCallback->GetNext() == nullptr);
6967
6968 AdvanceTime(5 * 1000);
6969
6970 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
6971 Log("Start SRV and TXT resolvers for `srv2._tst._tcp` service and validate callback result");
6972
6973 srvResolver.mServiceInstance = "srv2";
6974 srvResolver.mServiceType = "_tst._tcp";
6975 srvResolver.mInfraIfIndex = kInfraIfIndex;
6976 srvResolver.mCallback = HandleSrvResult;
6977
6978 txtResolver.mServiceInstance = "srv2";
6979 txtResolver.mServiceType = "_tst._tcp";
6980 txtResolver.mInfraIfIndex = kInfraIfIndex;
6981 txtResolver.mCallback = HandleTxtResult;
6982
6983 sSrvCallbacks.Clear();
6984 sTxtCallbacks.Clear();
6985
6986 SuccessOrQuit(mdns->StartSrvResolver(srvResolver));
6987 SuccessOrQuit(mdns->StartTxtResolver(txtResolver));
6988
6989 AdvanceTime(350);
6990
6991 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
6992 srvCallback = sSrvCallbacks.GetHead();
6993 VerifyOrQuit(srvCallback->mServiceInstance.Matches("srv2"));
6994 VerifyOrQuit(srvCallback->mServiceType.Matches("_tst._tcp"));
6995 VerifyOrQuit(srvCallback->mHostName.Matches("host1"));
6996 VerifyOrQuit(srvCallback->mPort == 2222);
6997 VerifyOrQuit(srvCallback->mPriority == 2);
6998 VerifyOrQuit(srvCallback->mWeight == 2);
6999 VerifyOrQuit(srvCallback->mTtl == 1500);
7000 VerifyOrQuit(srvCallback->GetNext() == nullptr);
7001
7002 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
7003 txtCallback = sTxtCallbacks.GetHead();
7004 VerifyOrQuit(txtCallback->mServiceInstance.Matches("srv2"));
7005 VerifyOrQuit(txtCallback->mServiceType.Matches("_tst._tcp"));
7006 VerifyOrQuit(txtCallback->Matches(kEmptyTxtData));
7007 VerifyOrQuit(txtCallback->mTtl == 1500);
7008 VerifyOrQuit(txtCallback->GetNext() == nullptr);
7009
7010 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7011 Log("Unregister `srv2._tst._tcp` and validate callback results");
7012
7013 sSrvCallbacks.Clear();
7014 sTxtCallbacks.Clear();
7015
7016 SuccessOrQuit(mdns->UnregisterService(service2));
7017
7018 AdvanceTime(350);
7019
7020 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
7021 srvCallback = sSrvCallbacks.GetHead();
7022 VerifyOrQuit(srvCallback->mServiceInstance.Matches("srv2"));
7023 VerifyOrQuit(srvCallback->mServiceType.Matches("_tst._tcp"));
7024 VerifyOrQuit(srvCallback->mTtl == 0);
7025 VerifyOrQuit(srvCallback->GetNext() == nullptr);
7026
7027 VerifyOrQuit(!sTxtCallbacks.IsEmpty());
7028 txtCallback = sTxtCallbacks.GetHead();
7029 VerifyOrQuit(txtCallback->mServiceInstance.Matches("srv2"));
7030 VerifyOrQuit(txtCallback->mServiceType.Matches("_tst._tcp"));
7031 VerifyOrQuit(txtCallback->mTtl == 0);
7032 VerifyOrQuit(txtCallback->GetNext() == nullptr);
7033
7034 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7035 Log("Start an SRV resolver for `srv3._srv._udp` service and validate callback result");
7036
7037 srvResolver.mServiceInstance = "srv3";
7038 srvResolver.mServiceType = "_srv._udp";
7039 srvResolver.mInfraIfIndex = kInfraIfIndex;
7040 srvResolver.mCallback = HandleSrvResult;
7041
7042 sSrvCallbacks.Clear();
7043
7044 SuccessOrQuit(mdns->StartSrvResolver(srvResolver));
7045
7046 AdvanceTime(350);
7047
7048 VerifyOrQuit(!sSrvCallbacks.IsEmpty());
7049 srvCallback = sSrvCallbacks.GetHead();
7050 VerifyOrQuit(srvCallback->mServiceInstance.Matches("srv3"));
7051 VerifyOrQuit(srvCallback->mServiceType.Matches("_srv._udp"));
7052 VerifyOrQuit(srvCallback->mHostName.Matches("host2"));
7053 VerifyOrQuit(srvCallback->mPort == 3333);
7054 VerifyOrQuit(srvCallback->mPriority == 3);
7055 VerifyOrQuit(srvCallback->mWeight == 3);
7056 VerifyOrQuit(srvCallback->mTtl == 1500);
7057 VerifyOrQuit(srvCallback->GetNext() == nullptr);
7058
7059 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7060 Log("Start an address resolver for host2 and validate result is immediately reported from cache");
7061
7062 addrResolver.mHostName = "host2";
7063 addrResolver.mInfraIfIndex = kInfraIfIndex;
7064 addrResolver.mCallback = HandleAddrResult;
7065
7066 sAddrCallbacks.Clear();
7067 SuccessOrQuit(mdns->StartIp6AddressResolver(addrResolver));
7068
7069 AdvanceTime(1);
7070
7071 VerifyOrQuit(!sAddrCallbacks.IsEmpty());
7072 addrCallback = sAddrCallbacks.GetHead();
7073 VerifyOrQuit(addrCallback->mHostName.Matches("host2"));
7074 VerifyOrQuit(addrCallback->Matches(host2AddrTtls, 2));
7075 VerifyOrQuit(addrCallback->GetNext() == nullptr);
7076
7077 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7078
7079 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
7080 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
7081
7082 Log("End of test");
7083
7084 testFreeInstance(sInstance);
7085 }
7086
TestLegacyUnicastResponse(void)7087 void TestLegacyUnicastResponse(void)
7088 {
7089 Core *mdns = InitTest();
7090 Core::Host host;
7091 Core::Service service;
7092 const DnsMessage *dnsMsg;
7093 uint16_t heapAllocations;
7094 DnsNameString fullServiceName;
7095 DnsNameString fullServiceType;
7096 DnsNameString hostFullName;
7097 Ip6::Address hostAddresses[2];
7098
7099 Log("-------------------------------------------------------------------------------------------");
7100 Log("TestLegacyUnicastResponse");
7101
7102 AdvanceTime(1);
7103
7104 heapAllocations = sHeapAllocatedPtrs.GetLength();
7105 SuccessOrQuit(mdns->SetEnabled(true, kInfraIfIndex));
7106
7107 SuccessOrQuit(hostAddresses[0].FromString("fd00::1:aaaa"));
7108 SuccessOrQuit(hostAddresses[1].FromString("fd00::1:bbbb"));
7109 host.mHostName = "host";
7110 host.mAddresses = hostAddresses;
7111 host.mAddressesLength = 2;
7112 host.mTtl = 1500;
7113 hostFullName.Append("%s.local.", host.mHostName);
7114
7115 service.mHostName = host.mHostName;
7116 service.mServiceInstance = "myservice";
7117 service.mServiceType = "_srv._udp";
7118 service.mSubTypeLabels = nullptr;
7119 service.mSubTypeLabelsLength = 0;
7120 service.mTxtData = kTxtData1;
7121 service.mTxtDataLength = sizeof(kTxtData1);
7122 service.mPort = 1234;
7123 service.mPriority = 1;
7124 service.mWeight = 2;
7125 service.mTtl = 1000;
7126
7127 fullServiceName.Append("%s.%s.local.", service.mServiceInstance, service.mServiceType);
7128 fullServiceType.Append("%s.local.", service.mServiceType);
7129
7130 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7131
7132 sDnsMessages.Clear();
7133
7134 for (RegCallback ®Callbck : sRegCallbacks)
7135 {
7136 regCallbck.Reset();
7137 }
7138
7139 SuccessOrQuit(mdns->RegisterHost(host, 0, HandleSuccessCallback));
7140 SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback));
7141
7142 AdvanceTime(10 * 1000);
7143
7144 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7145 Log("Send a query with two questions (SRV for service1 and AAAA for host). Validate that no response is sent");
7146
7147 AdvanceTime(2000);
7148
7149 sDnsMessages.Clear();
7150 SendQueryForTwo(fullServiceName.AsCString(), ResourceRecord::kTypeSrv, hostFullName.AsCString(),
7151 ResourceRecord::kTypeAaaa, /* aIsLegacyUnicast */ true);
7152
7153 AdvanceTime(200);
7154
7155 dnsMsg = sDnsMessages.GetHead();
7156 VerifyOrQuit(dnsMsg == nullptr);
7157
7158 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7159 Log("Send a query for SRV record and validate the response");
7160
7161 AdvanceTime(2000);
7162
7163 sDnsMessages.Clear();
7164 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeSrv, ResourceRecord::kClassInternet,
7165 /* aTruncated */ false,
7166 /* aLegacyUnicastQuery */ true);
7167
7168 AdvanceTime(1000);
7169
7170 dnsMsg = sDnsMessages.GetHead();
7171 VerifyOrQuit(dnsMsg != nullptr);
7172 dnsMsg->ValidateHeader(kLegacyUnicastResponse, /* Q */ 1, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 3);
7173 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv);
7174 dnsMsg->Validate(host, kInAdditionalSection);
7175
7176 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7177 Log("Send a query for TXT record and validate the response");
7178
7179 AdvanceTime(2000);
7180
7181 sDnsMessages.Clear();
7182 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeTxt, ResourceRecord::kClassInternet,
7183 /* aTruncated */ false,
7184 /* aLegacyUnicastQuery */ true);
7185
7186 AdvanceTime(1000);
7187
7188 dnsMsg = sDnsMessages.GetHead();
7189 VerifyOrQuit(dnsMsg != nullptr);
7190 dnsMsg->ValidateHeader(kLegacyUnicastResponse, /* Q */ 1, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1);
7191 dnsMsg->Validate(service, kInAnswerSection, kCheckTxt);
7192
7193 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7194 Log("Send a query for ANY record and validate the response");
7195
7196 AdvanceTime(2000);
7197
7198 sDnsMessages.Clear();
7199 SendQuery(fullServiceName.AsCString(), ResourceRecord::kTypeAny, ResourceRecord::kClassInternet,
7200 /* aTruncated */ false,
7201 /* aLegacyUnicastQuery */ true);
7202
7203 AdvanceTime(1000);
7204
7205 dnsMsg = sDnsMessages.GetHead();
7206 VerifyOrQuit(dnsMsg != nullptr);
7207 dnsMsg->ValidateHeader(kLegacyUnicastResponse, /* Q */ 1, /* Ans */ 2, /* Auth */ 0, /* Addnl */ 3);
7208 dnsMsg->Validate(service, kInAnswerSection, kCheckSrv | kCheckTxt);
7209 dnsMsg->Validate(host, kInAdditionalSection);
7210
7211 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7212 Log("Send a query for PTR record for service type and validate the response");
7213
7214 AdvanceTime(2000);
7215
7216 sDnsMessages.Clear();
7217 SendQuery(fullServiceType.AsCString(), ResourceRecord::kTypePtr, ResourceRecord::kClassInternet,
7218 /* aTruncated */ false,
7219 /* aLegacyUnicastQuery */ true);
7220
7221 AdvanceTime(1000);
7222
7223 dnsMsg = sDnsMessages.GetHead();
7224 VerifyOrQuit(dnsMsg != nullptr);
7225 dnsMsg->ValidateHeader(kLegacyUnicastResponse, /* Q */ 1, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 4);
7226 dnsMsg->Validate(service, kInAnswerSection, kCheckPtr);
7227 dnsMsg->Validate(service, kInAdditionalSection, kCheckSrv | kCheckTxt);
7228 dnsMsg->Validate(host, kInAdditionalSection);
7229
7230 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7231 Log("Send a query for non-existing record and validate the response with NSEC");
7232
7233 AdvanceTime(2000);
7234
7235 sDnsMessages.Clear();
7236 SendQuery(hostFullName.AsCString(), ResourceRecord::kTypeA, ResourceRecord::kClassInternet, /* aTruncated */ false,
7237 /* aLegacyUnicastQuery */ true);
7238
7239 AdvanceTime(1000);
7240
7241 dnsMsg = sDnsMessages.GetHead();
7242 VerifyOrQuit(dnsMsg != nullptr);
7243 dnsMsg->ValidateHeader(kLegacyUnicastResponse, /* Q */ 1, /* Ans */ 0, /* Auth */ 0, /* Addnl */ 1);
7244 VerifyOrQuit(dnsMsg->mAdditionalRecords.ContainsNsec(hostFullName, ResourceRecord::kTypeAaaa));
7245
7246 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
7247
7248 sDnsMessages.Clear();
7249
7250 SuccessOrQuit(mdns->UnregisterHost(host));
7251
7252 AdvanceTime(15000);
7253
7254 SuccessOrQuit(mdns->SetEnabled(false, kInfraIfIndex));
7255 VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
7256
7257 Log("End of test");
7258
7259 testFreeInstance(sInstance);
7260 }
7261
7262 } // namespace Multicast
7263 } // namespace Dns
7264 } // namespace ot
7265
7266 #endif // OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
7267
main(void)7268 int main(void)
7269 {
7270 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
7271 ot::Dns::Multicast::TestHostReg();
7272 ot::Dns::Multicast::TestKeyReg();
7273 ot::Dns::Multicast::TestServiceReg();
7274 ot::Dns::Multicast::TestUnregisterBeforeProbeFinished();
7275 ot::Dns::Multicast::TestServiceSubTypeReg();
7276 ot::Dns::Multicast::TestHostOrServiceAndKeyReg();
7277 ot::Dns::Multicast::TestQuery();
7278 ot::Dns::Multicast::TestMultiPacket();
7279 ot::Dns::Multicast::TestResponseAggregation();
7280 ot::Dns::Multicast::TestQuestionUnicastDisallowed();
7281 ot::Dns::Multicast::TestTxMessageSizeLimit();
7282 ot::Dns::Multicast::TestHostConflict();
7283 ot::Dns::Multicast::TestServiceConflict();
7284
7285 ot::Dns::Multicast::TestBrowser();
7286 ot::Dns::Multicast::TestSrvResolver();
7287 ot::Dns::Multicast::TestTxtResolver();
7288 ot::Dns::Multicast::TestIp6AddrResolver();
7289 ot::Dns::Multicast::TestPassiveCache();
7290 ot::Dns::Multicast::TestLegacyUnicastResponse();
7291
7292 printf("All tests passed\n");
7293 #else
7294 printf("mDNS feature is not enabled\n");
7295 #endif
7296
7297 return 0;
7298 }
7299