@@ -290,6 +290,21 @@ void Server::Response::Send(const Ip6::MessageInfo &aMessageInfo)
290290 return ;
291291}
292292
293+ bool Server::Questions::IsFor (uint16_t aRrType) const
294+ {
295+ // Check if any of questions is for `aRrType`.
296+
297+ return (mFirstRrType == aRrType) || (mSecondRrType == aRrType);
298+ }
299+
300+ Server::Section Server::Questions::SectionFor (uint16_t aRrType) const
301+ {
302+ // Determine section to append `aRrType` record based on the
303+ // query questions.
304+
305+ return (IsFor (aRrType) || IsFor (kRrTypeAny )) ? kAnswerSection : kAdditionalDataSection ;
306+ }
307+
293308Server::ResponseCode Server::Request::ParseQuestions (uint8_t aTestMode, bool &aShouldRespond)
294309{
295310 // Parse header and questions from a `Request` query message and
@@ -349,7 +364,7 @@ Server::ResponseCode Server::Response::AddQuestionsFrom(const Request &aRequest)
349364 // service instance names with dot characters in the instance
350365 // label, are appended correctly.
351366
352- SuccessOrExit (Name (*aRequest.mMessage , sizeof (Header) ).AppendTo (*mMessage ));
367+ SuccessOrExit (Name (*aRequest.mMessage , kQueryNameOffset ).AppendTo (*mMessage ));
353368
354369 // Check the name to include the correct domain name and determine
355370 // the domain name offset (for DNS name compression).
@@ -398,26 +413,17 @@ Error Server::Response::ParseQueryName(void)
398413 offset = sizeof (Header);
399414 SuccessOrExit (error = Name::ReadName (*mMessage , offset, name));
400415
401- if (mQuestions .IsFor (kRrTypePtr ))
402- {
403- // `mOffsets.mServiceName` may be updated as we read labels and if we
404- // determine that the query name is a sub-type service.
405- mOffsets .mServiceName = sizeof (Header);
406- }
407- else if (mQuestions .IsFor (kRrTypeSrv ) || mQuestions .IsFor (kRrTypeTxt ))
408- {
409- mOffsets .mInstanceName = sizeof (Header);
410- }
411- else
412- {
413- mOffsets .mHostName = sizeof (Header);
414- }
416+ // `mOffsets.mServiceName` may be updated as we read labels and if we
417+ // determine that the query name is a sub-type service.
418+ mOffsets .mServiceName = kQueryNameOffset ;
419+ mOffsets .mInstanceName = kQueryNameOffset ;
420+ mOffsets .mHostName = kQueryNameOffset ;
415421
416422 // Read the query name labels one by one to check if the name is
417423 // service sub-type and also check that it is sub-domain of the
418424 // default domain name and determine its offset
419425
420- offset = sizeof (Header) ;
426+ offset = kQueryNameOffset ;
421427
422428 while (true )
423429 {
@@ -427,7 +433,8 @@ Error Server::Response::ParseQueryName(void)
427433
428434 SuccessOrExit (error = Name::ReadLabel (*mMessage , offset, label, labelLength));
429435
430- if (mQuestions .IsFor (kRrTypePtr ) && StringMatch (label, kSubLabel , kStringCaseInsensitiveMatch ))
436+ if ((mQuestions .IsFor (kRrTypePtr ) || mQuestions .IsFor (kRrTypeAny )) &&
437+ StringMatch (label, kSubLabel , kStringCaseInsensitiveMatch ))
431438 {
432439 mOffsets .mServiceName = offset;
433440 }
@@ -451,7 +458,7 @@ void Server::Response::ReadQueryName(Name::Buffer &aName) const { Server::ReadQu
451458
452459bool Server::Response::QueryNameMatches (const char *aName) const { return Server::QueryNameMatches (*mMessage , aName); }
453460
454- Error Server::Response::AppendQueryName (void ) { return Name::AppendPointerLabel (sizeof (Header) , *mMessage ); }
461+ Error Server::Response::AppendQueryName (void ) { return Name::AppendPointerLabel (kQueryNameOffset , *mMessage ); }
455462
456463#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
457464Error Server::Response::AppendPtrRecord (const Srp::Server::Service &aService)
@@ -514,6 +521,7 @@ Error Server::Response::AppendSrvRecord(const char *aHostName,
514521 SrvRecord srvRecord;
515522 uint16_t recordOffset;
516523 Name::Buffer hostLabels;
524+ uint16_t nameOffset;
517525
518526 SuccessOrExit (error = Name::ExtractLabels (aHostName, kDefaultDomainName , hostLabels));
519527
@@ -523,7 +531,8 @@ Error Server::Response::AppendSrvRecord(const char *aHostName,
523531 srvRecord.SetWeight (aWeight);
524532 srvRecord.SetPort (aPort);
525533
526- SuccessOrExit (error = Name::AppendPointerLabel (mOffsets .mInstanceName , *mMessage ));
534+ nameOffset = mQuestions .IsFor (kRrTypeAny ) ? kQueryNameOffset : mOffsets .mInstanceName ;
535+ SuccessOrExit (error = Name::AppendPointerLabel (nameOffset, *mMessage ));
527536
528537 recordOffset = mMessage ->GetLength ();
529538 SuccessOrExit (error = mMessage ->Append (srvRecord));
@@ -601,14 +610,16 @@ Error Server::Response::AppendAaaaRecord(const Ip6::Address &aAddress, uint32_t
601610{
602611 Error error = kErrorNone ;
603612 AaaaRecord aaaaRecord;
613+ uint16_t nameOffset;
604614
605615 VerifyOrExit (!aAddress.IsIp4Mapped ());
606616
607617 aaaaRecord.Init ();
608618 aaaaRecord.SetTtl (aTtl);
609619 aaaaRecord.SetAddress (aAddress);
610620
611- SuccessOrExit (error = Name::AppendPointerLabel (mOffsets .mHostName , *mMessage ));
621+ nameOffset = mQuestions .IsFor (kRrTypeAny ) ? kQueryNameOffset : mOffsets .mHostName ;
622+ SuccessOrExit (error = Name::AppendPointerLabel (nameOffset, *mMessage ));
612623 SuccessOrExit (error = mMessage ->Append (aaaaRecord));
613624 IncResourceRecordCount ();
614625
@@ -621,14 +632,16 @@ Error Server::Response::AppendARecord(const Ip6::Address &aAddress, uint32_t aTt
621632 Error error = kErrorNone ;
622633 ARecord aRecord;
623634 Ip4::Address ip4Address;
635+ uint16_t nameOffset;
624636
625637 SuccessOrExit (ip4Address.ExtractFromIp4MappedIp6Address (aAddress));
626638
627639 aRecord.Init ();
628640 aRecord.SetTtl (aTtl);
629641 aRecord.SetAddress (ip4Address);
630642
631- SuccessOrExit (error = Name::AppendPointerLabel (mOffsets .mHostName , *mMessage ));
643+ nameOffset = mQuestions .IsFor (kRrTypeAny ) ? kQueryNameOffset : mOffsets .mHostName ;
644+ SuccessOrExit (error = Name::AppendPointerLabel (nameOffset, *mMessage ));
632645 SuccessOrExit (error = mMessage ->Append (aRecord));
633646 IncResourceRecordCount ();
634647
@@ -653,6 +666,7 @@ Error Server::Response::AppendTxtRecord(const void *aTxtData, uint16_t aTxtLengt
653666{
654667 Error error = kErrorNone ;
655668 TxtRecord txtRecord;
669+ uint16_t nameOffset;
656670 uint8_t emptyTxt = 0 ;
657671
658672 if (aTxtLength == 0 )
@@ -665,7 +679,8 @@ Error Server::Response::AppendTxtRecord(const void *aTxtData, uint16_t aTxtLengt
665679 txtRecord.SetTtl (aTtl);
666680 txtRecord.SetLength (aTxtLength);
667681
668- SuccessOrExit (error = Name::AppendPointerLabel (mOffsets .mInstanceName , *mMessage ));
682+ nameOffset = mQuestions .IsFor (kRrTypeAny ) ? kQueryNameOffset : mOffsets .mInstanceName ;
683+ SuccessOrExit (error = Name::AppendPointerLabel (nameOffset, *mMessage ));
669684 SuccessOrExit (error = mMessage ->Append (txtRecord));
670685 SuccessOrExit (error = mMessage ->AppendBytes (aTxtData, aTxtLength));
671686
@@ -705,7 +720,7 @@ Error Server::Response::AppendGenericRecord(uint16_t aRrType, const RecordData &
705720 record.Init (aRrType);
706721 record.SetTtl (aTtl);
707722
708- SuccessOrExit (error = Name::AppendPointerLabel (mOffsets . mHostName , *mMessage ));
723+ SuccessOrExit (error = Name::AppendPointerLabel (kQueryNameOffset , *mMessage ));
709724
710725 recordOffset = mMessage ->GetLength ();
711726 SuccessOrExit (error = mMessage ->Append (record));
@@ -735,6 +750,7 @@ template <typename ServiceType> Error Server::Response::AppendServiceRecords(con
735750
736751 if (mSection == kAdditionalDataSection )
737752 {
753+ VerifyOrExit (!mQuestions .IsFor (kRrTypeAny ));
738754 VerifyOrExit (!(Get<Server>().mTestMode & kTestModeEmptyAdditionalSection ));
739755 }
740756
@@ -788,7 +804,6 @@ Error Server::Response::ResolveBySrp(void)
788804{
789805 Error error = kErrorNone ;
790806 const Srp::Server::Service *matchedService = nullptr ;
791- bool found = false ;
792807
793808 mSection = kAnswerSection ;
794809
@@ -801,18 +816,7 @@ Error Server::Response::ResolveBySrp(void)
801816
802817 if (QueryNameMatches (host.GetFullName ()))
803818 {
804- if (mQuestions .IsFor (kRrTypeAaaa ) || mQuestions .IsFor (kRrTypeA ))
805- {
806- mSection = mQuestions .SectionFor (kRrTypeAaaa );
807- SuccessOrExit (error = AppendHostAddresses (host));
808- }
809-
810- if (mQuestions .IsFor (kRrTypeKey ))
811- {
812- mSection = kAnswerSection ;
813- SuccessOrExit (error = AppendKeyRecord (host));
814- }
815-
819+ error = ResolveUsingSrpHost (host);
816820 ExitNow ();
817821 }
818822
@@ -823,52 +827,74 @@ Error Server::Response::ResolveBySrp(void)
823827 continue ;
824828 }
825829
826- if (mQuestions . IsFor ( kRrTypePtr ))
830+ if (QueryNameMatches (service. GetInstanceName () ))
827831 {
828- if (QueryNameMatchesService (service))
829- {
830- SuccessOrExit (error = AppendPtrRecord (service));
831- matchedService = &service;
832- }
832+ error = ResolveUsingSrpService (service);
833+ ExitNow ();
833834 }
834- else if (QueryNameMatches (service.GetInstanceName ()))
835+
836+ if ((mQuestions .IsFor (kRrTypePtr ) || mQuestions .IsFor (kRrTypeAny )) && QueryNameMatchesService (service))
835837 {
838+ SuccessOrExit (error = AppendPtrRecord (service));
836839 matchedService = &service;
837- found = true ;
838- break ;
839840 }
840841 }
841-
842- if (found)
843- {
844- break ;
845- }
846842 }
847843
848844 VerifyOrExit (matchedService != nullptr , error = kErrorNotFound );
849845
850- if (mQuestions .IsFor (kRrTypePtr ))
846+ // We append SRV/TXT/AAAA records in additional section for a PTR
847+ // query when there is only a single matched service. This is the
848+ // recommended behavior to keep the size of the response small.
849+
850+ if (mQuestions .IsFor (kRrTypePtr ) && (mHeader .GetAnswerCount () == 1 ))
851851 {
852- // Skip adding additional records, when answering a
853- // PTR query with more than one answer. This is the
854- // recommended behavior to keep the size of the
855- // response small.
852+ error = AppendServiceRecords (*matchedService);
853+ }
854+
855+ exit:
856+ return error;
857+ }
858+
859+ Error Server::Response::ResolveUsingSrpHost (const Srp::Server::Host &aHost)
860+ {
861+ // The query name is already checked to match the `aHost` name.
862+
863+ Error error = kErrorNone ;
856864
857- VerifyOrExit (mHeader .GetAnswerCount () == 1 );
865+ if (mQuestions .IsFor (kRrTypeAaaa ) || mQuestions .IsFor (kRrTypeA ) || mQuestions .IsFor (kRrTypeAny ))
866+ {
867+ mSection = mQuestions .SectionFor (kRrTypeAaaa );
868+ SuccessOrExit (error = AppendHostAddresses (aHost));
858869 }
859- else
870+
871+ if (mQuestions .IsFor (kRrTypeKey ) || mQuestions .IsFor (kRrTypeAny ))
860872 {
861- if (mQuestions .IsFor (kRrTypeKey ))
862- {
863- mSection = kAnswerSection ;
864- error = AppendKeyRecord (matchedService->GetHost ());
865- ExitNow ();
866- }
873+ mSection = kAnswerSection ;
874+ SuccessOrExit (error = AppendKeyRecord (aHost));
875+ }
876+
877+ exit:
878+ return error;
879+ }
867880
868- VerifyOrExit (mQuestions .IsFor (kRrTypeSrv ) || mQuestions .IsFor (kRrTypeTxt ));
881+ Error Server::Response::ResolveUsingSrpService (const Srp::Server::Service &aService)
882+ {
883+ // The query name is already checked to match the
884+ // `aService` instance name.
885+
886+ Error error = kErrorNone ;
887+
888+ if (mQuestions .IsFor (kRrTypeKey ) || mQuestions .IsFor (kRrTypeAny ))
889+ {
890+ mSection = kAnswerSection ;
891+ SuccessOrExit (error = AppendKeyRecord (aService.GetHost ()));
869892 }
870893
871- error = AppendServiceRecords (*matchedService);
894+ if (mQuestions .IsFor (kRrTypeSrv ) || mQuestions .IsFor (kRrTypeTxt ) || mQuestions .IsFor (kRrTypeAny ))
895+ {
896+ SuccessOrExit (error = AppendServiceRecords (aService));
897+ }
872898
873899exit:
874900 return error;
@@ -1573,6 +1599,7 @@ void Server::DiscoveryProxy::ReadNameFor(ProxyAction aAction,
15731599 case kNoAction :
15741600 break ;
15751601 case kBrowsing :
1602+ case kQueryingRecord :
15761603 ReadQueryName (aQuery, aName);
15771604 break ;
15781605 case kResolvingSrv :
@@ -1581,7 +1608,6 @@ void Server::DiscoveryProxy::ReadNameFor(ProxyAction aAction,
15811608 break ;
15821609 case kResolvingIp6Address :
15831610 case kResolvingIp4Address :
1584- case kQueryingRecord :
15851611 ReadQueryHostName (aQuery, aInfo, aName);
15861612 break ;
15871613 }
@@ -1819,7 +1845,7 @@ void Server::DiscoveryProxy::StartOrStopRecordQuerier(Command aCom
18191845 Dnssd::RecordQuerier querier;
18201846 Name::LabelBuffer firstLabel;
18211847 Name::Buffer nextLabels;
1822- uint16_t offset = aInfo. mOffsets . mHostName ;
1848+ uint16_t offset = sizeof (Header) ;
18231849 uint8_t labelLength = sizeof (firstLabel);
18241850
18251851 IgnoreError (Dns::Name::ReadLabel (aQuery, offset, firstLabel, labelLength));
@@ -1847,25 +1873,37 @@ bool Server::DiscoveryProxy::QueryMatches(const ProxyQuery &aQuery,
18471873 const ProxyQueryInfo &aInfo,
18481874 ProxyAction aAction,
18491875 const Name::Buffer &aName,
1850- uint16_t aQuerierRrType) const
1876+ uint16_t aQuerierRrType,
1877+ RrTypeMatchMode aRrTypeMatchMode) const
18511878{
18521879 // Check whether `aQuery` is performing `aAction` and
1853- // its name matches `aName`. The `aQuerierRrType` is only
1854- // used when the action is `kQueryingRecord` to indicate
1855- // which record is being queried.
1880+ // its name matches `aName`. The `aQuerierRrType` and
1881+ // `aRrTypeMatchMode` are only used when the action is
1882+ // `kQueryingRecord` to indicate queried record type and
1883+ // how to determine a match.
18561884
18571885 bool matches = false ;
18581886
18591887 VerifyOrExit (aInfo.mAction == aAction);
18601888
18611889 if (aAction == kQueryingRecord )
18621890 {
1863- VerifyOrExit (aInfo.mQuestions .IsFor (aQuerierRrType));
1891+ switch (aRrTypeMatchMode)
1892+ {
1893+ case kRequireExactMatch :
1894+ VerifyOrExit (aInfo.mQuestions .IsFor (aQuerierRrType));
1895+ break ;
1896+
1897+ case kPermitAnyOrExactMatch :
1898+ VerifyOrExit (aInfo.mQuestions .IsFor (aQuerierRrType) || aInfo.mQuestions .IsFor (kRrTypeAny ));
1899+ break ;
1900+ }
18641901 }
18651902
18661903 switch (aAction)
18671904 {
18681905 case kBrowsing :
1906+ case kQueryingRecord :
18691907 VerifyOrExit (QueryNameMatches (aQuery, aName));
18701908 break ;
18711909 case kResolvingSrv :
@@ -1874,7 +1912,6 @@ bool Server::DiscoveryProxy::QueryMatches(const ProxyQuery &aQuery,
18741912 break ;
18751913 case kResolvingIp6Address :
18761914 case kResolvingIp4Address :
1877- case kQueryingRecord :
18781915 VerifyOrExit (QueryHostNameMatches (aQuery, aInfo, aName));
18791916 break ;
18801917 case kNoAction :
@@ -1902,7 +1939,7 @@ bool Server::DiscoveryProxy::HasActive(ProxyAction aAction, const Name::Buffer &
19021939
19031940 info.ReadFrom (query);
19041941
1905- if (QueryMatches (query, info, aAction, aName, aQuerierRrType))
1942+ if (QueryMatches (query, info, aAction, aName, aQuerierRrType, kRequireExactMatch ))
19061943 {
19071944 has = true ;
19081945 break ;
@@ -2105,7 +2142,7 @@ void Server::DiscoveryProxy::HandleResult(ProxyAction aAction,
21052142
21062143 info.ReadFrom (query);
21072144
2108- if (!QueryMatches (query, info, aAction, aName, querierRrType))
2145+ if (!QueryMatches (query, info, aAction, aName, querierRrType, kPermitAnyOrExactMatch ))
21092146 {
21102147 continue ;
21112148 }
0 commit comments