diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp index 35c6cb793..5b75f4f06 100644 --- a/src/core/net/dnssd_server.cpp +++ b/src/core/net/dnssd_server.cpp @@ -335,6 +335,9 @@ Server::ResponseCode Server::Request::ParseQuestions(uint8_t aTestMode, bool &aS case ResourceRecord::kTypeAaaa: mType = kAaaaQuery; break; + case ResourceRecord::kTypeA: + mType = kAQuery; + break; default: ExitNow(rcode = Header::kResponseNotImplemented); } @@ -447,6 +450,7 @@ Error Server::Response::ParseQueryName(void) break; case kAaaaQuery: + case kAQuery: mOffsets.mHostName = sizeof(Header); break; } @@ -579,27 +583,42 @@ Error Server::Response::AppendHostAddresses(const Srp::Server::Host &aHost) addrs = aHost.GetAddresses(addrsLength); ttl = TimeMilli::MsecToSec(aHost.GetExpireTime() - TimerMilli::GetNow()); - return AppendHostAddresses(addrs, addrsLength, ttl); + return AppendHostAddresses(kIp6AddrType, addrs, addrsLength, ttl); } #endif -Error Server::Response::AppendHostAddresses(const HostInfo &aHostInfo) +Error Server::Response::AppendHostAddresses(AddrType aAddrType, const HostInfo &aHostInfo) { - return AppendHostAddresses(AsCoreTypePtr(aHostInfo.mAddresses), aHostInfo.mAddressNum, aHostInfo.mTtl); + return AppendHostAddresses(aAddrType, AsCoreTypePtr(aHostInfo.mAddresses), aHostInfo.mAddressNum, aHostInfo.mTtl); } Error Server::Response::AppendHostAddresses(const ServiceInstanceInfo &aInstanceInfo) { - return AppendHostAddresses(AsCoreTypePtr(aInstanceInfo.mAddresses), aInstanceInfo.mAddressNum, aInstanceInfo.mTtl); + return AppendHostAddresses(kIp6AddrType, AsCoreTypePtr(aInstanceInfo.mAddresses), aInstanceInfo.mAddressNum, + aInstanceInfo.mTtl); } -Error Server::Response::AppendHostAddresses(const Ip6::Address *aAddrs, uint16_t aAddrsLength, uint32_t aTtl) +Error Server::Response::AppendHostAddresses(AddrType aAddrType, + const Ip6::Address *aAddrs, + uint16_t aAddrsLength, + uint32_t aTtl) { Error error = kErrorNone; for (uint16_t index = 0; index < aAddrsLength; index++) { - SuccessOrExit(error = AppendAaaaRecord(aAddrs[index], aTtl)); + const Ip6::Address &address = aAddrs[index]; + + switch (aAddrType) + { + case kIp6AddrType: + SuccessOrExit(error = AppendAaaaRecord(address, aTtl)); + break; + + case kIp4AddrType: + SuccessOrExit(error = AppendARecord(address, aTtl)); + break; + } } exit: @@ -608,9 +627,11 @@ exit: Error Server::Response::AppendAaaaRecord(const Ip6::Address &aAddress, uint32_t aTtl) { - Error error; + Error error = kErrorNone; AaaaRecord aaaaRecord; + VerifyOrExit(!aAddress.IsIp4Mapped()); + aaaaRecord.Init(); aaaaRecord.SetTtl(aTtl); aaaaRecord.SetAddress(aAddress); @@ -623,6 +644,26 @@ exit: return error; } +Error Server::Response::AppendARecord(const Ip6::Address &aAddress, uint32_t aTtl) +{ + Error error = kErrorNone; + ARecord aRecord; + Ip4::Address ip4Address; + + SuccessOrExit(ip4Address.ExtractFromIp4MappedIp6Address(aAddress)); + + aRecord.Init(); + aRecord.SetTtl(aTtl); + aRecord.SetAddress(ip4Address); + + SuccessOrExit(error = Name::AppendPointerLabel(mOffsets.mHostName, *mMessage)); + SuccessOrExit(error = mMessage->Append(aRecord)); + IncResourceRecordCount(); + +exit: + return error; +} + #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE Error Server::Response::AppendTxtRecord(const Srp::Server::Service &aService) { @@ -704,6 +745,7 @@ const char *Server::Response::QueryTypeToString(QueryType aType) "TXT", // (2) kTxtQuery "SRV & TXT", // (3) kSrvTxtQuery "AAAA", // (4) kAaaaQuery + "A", // (5) kAQuery }; static_assert(0 == kPtrQuery, "kPtrQuery value is incorrect"); @@ -711,6 +753,7 @@ const char *Server::Response::QueryTypeToString(QueryType aType) static_assert(2 == kTxtQuery, "kTxtQuery value is incorrect"); static_assert(3 == kSrvTxtQuery, "kSrvTxtQuery value is incorrect"); static_assert(4 == kAaaaQuery, "kAaaaQuery value is incorrect"); + static_assert(5 == kAQuery, "kAQuery value is incorrect"); return kTypeNames[aType]; } @@ -737,11 +780,12 @@ Error Server::Response::ResolveBySrp(void) continue; } - if (mType == kAaaaQuery) + if ((mType == kAaaaQuery) || (mType == kAQuery)) { if (QueryNameMatches(host.GetFullName())) { - error = AppendHostAddresses(host); + mSection = (mType == kAaaaQuery) ? kAnswerSection : kAdditionalDataSection; + error = AppendHostAddresses(host); ExitNow(); } @@ -1191,9 +1235,14 @@ exit: void Server::Response::Answer(const HostInfo &aHostInfo, const Ip6::MessageInfo &aMessageInfo) { + // Caller already ensures that `mType` is either `kAaaaQuery` or + // `kAQuery`. + + AddrType addrType = (mType == kAaaaQuery) ? kIp6AddrType : kIp4AddrType; + mSection = kAnswerSection; - if (AppendHostAddresses(aHostInfo) != kErrorNone) + if (AppendHostAddresses(addrType, aHostInfo) != kErrorNone) { SetResponseCode(Header::kResponseServerFailure); } @@ -1238,6 +1287,7 @@ void Server::HandleDiscoveredServiceInstance(const char *aServiceFullName, const break; case kAaaaQuery: + case kAQuery: break; } @@ -1261,12 +1311,22 @@ void Server::HandleDiscoveredHost(const char *aHostFullName, const HostInfo &aHo info.ReadFrom(query); - if ((info.mType == kAaaaQuery) && QueryNameMatches(query, aHostFullName)) + switch (info.mType) { - Response response(GetInstance()); + case kAaaaQuery: + case kAQuery: + if (QueryNameMatches(query, aHostFullName)) + { + Response response(GetInstance()); - RemoveQueryAndPrepareResponse(query, info, response); - response.Answer(aHostInfo, info.mMessageInfo); + RemoveQueryAndPrepareResponse(query, info, response); + response.Answer(aHostInfo, info.mMessageInfo); + } + + break; + + default: + break; } } } @@ -1301,6 +1361,7 @@ Server::DnsQueryType Server::GetQueryTypeAndName(const otDnssdQuery *aQuery, Dns break; case kAaaaQuery: + case kAQuery: type = kDnsQueryResolveHost; break; } @@ -1483,6 +1544,9 @@ void Server::DiscoveryProxy::Resolve(ProxyQuery &aQuery, ProxyQueryInfo &aInfo) case kAaaaQuery: action = kResolvingIp6Address; break; + case kAQuery: + action = kResolvingIp4Address; + break; } Perform(action, aQuery, aInfo); @@ -1538,6 +1602,7 @@ void Server::DiscoveryProxy::ReadNameFor(ProxyAction aAction, ReadQueryInstanceName(aQuery, aInfo, aName); break; case kResolvingIp6Address: + case kResolvingIp4Address: ReadQueryHostName(aQuery, aInfo, aName); break; } @@ -1597,6 +1662,9 @@ void Server::DiscoveryProxy::UpdateProxy(Command aCommand, case kResolvingIp6Address: StartOrStopIp6Resolver(aCommand, aName); break; + case kResolvingIp4Address: + StartOrStopIp4Resolver(aCommand, aName); + break; } } @@ -1734,6 +1802,30 @@ void Server::DiscoveryProxy::StartOrStopIp6Resolver(Command aCommand, Name::Buff } } +void Server::DiscoveryProxy::StartOrStopIp4Resolver(Command aCommand, Name::Buffer &aHostName) +{ + // Start or stop an IPv4 address resolver for a given host name. + + Dnssd::AddressResolver resolver; + + IgnoreError(StripDomainName(aHostName)); + + resolver.mHostName = aHostName; + resolver.mInfraIfIndex = Get().GetIfIndex(); + resolver.mCallback = HandleIp4AddressResult; + + switch (aCommand) + { + case kStart: + Get().StartIp4AddressResolver(resolver); + break; + + case kStop: + Get().StopIp4AddressResolver(resolver); + break; + } +} + bool Server::DiscoveryProxy::QueryMatches(const ProxyQuery &aQuery, const ProxyQueryInfo &aInfo, ProxyAction aAction, @@ -1756,6 +1848,7 @@ bool Server::DiscoveryProxy::QueryMatches(const ProxyQuery &aQuery, VerifyOrExit(QueryInstanceNameMatches(aQuery, aInfo, aName)); break; case kResolvingIp6Address: + case kResolvingIp4Address: VerifyOrExit(QueryHostNameMatches(aQuery, aInfo, aName)); break; case kNoAction: @@ -1892,7 +1985,46 @@ void Server::DiscoveryProxy::HandleIp6AddressResult(const Dnssd::AddressResult & VerifyOrExit(hasValidAddress); ConstructFullName(aResult.mHostName, fullHostName); - HandleResult(kResolvingIp6Address, fullHostName, &Response::AppendHostAddresses, ProxyResult(aResult)); + HandleResult(kResolvingIp6Address, fullHostName, &Response::AppendHostIp6Addresses, ProxyResult(aResult)); + +exit: + return; +} + +void Server::DiscoveryProxy::HandleIp4AddressResult(otInstance *aInstance, const otPlatDnssdAddressResult *aResult) +{ + AsCoreType(aInstance).Get().mDiscoveryProxy.HandleIp4AddressResult(*aResult); +} + +void Server::DiscoveryProxy::HandleIp4AddressResult(const Dnssd::AddressResult &aResult) +{ + bool hasValidAddress = false; + Name::Buffer fullHostName; + + VerifyOrExit(mIsRunning); + VerifyOrExit(aResult.mInfraIfIndex == Get().GetIfIndex()); + + for (uint16_t index = 0; index < aResult.mAddressesLength; index++) + { + const Dnssd::AddressAndTtl &entry = aResult.mAddresses[index]; + const Ip6::Address &address = AsCoreType(&entry.mAddress); + + if (entry.mTtl == 0) + { + continue; + } + + if (address.IsIp4Mapped()) + { + hasValidAddress = true; + break; + } + } + + VerifyOrExit(hasValidAddress); + + ConstructFullName(aResult.mHostName, fullHostName); + HandleResult(kResolvingIp4Address, fullHostName, &Response::AppendHostIp4Addresses, ProxyResult(aResult)); exit: return; @@ -1944,6 +2076,7 @@ void Server::DiscoveryProxy::HandleResult(ProxyAction aAction, break; case kNoAction: case kResolvingIp6Address: + case kResolvingIp4Address: break; } @@ -2038,6 +2171,10 @@ bool Server::DiscoveryProxy::IsActionForAdditionalSection(ProxyAction aAction, Q VerifyOrExit(aQueryType == kAaaaQuery); break; + case kResolvingIp4Address: + VerifyOrExit(aQueryType == kAQuery); + break; + case kNoAction: case kBrowsing: ExitNow(); @@ -2079,7 +2216,7 @@ Error Server::Response::AppendTxtRecord(const ProxyResult &aResult) return AppendTxtRecord(txtResult->mTxtData, txtResult->mTxtDataLength, txtResult->mTtl); } -Error Server::Response::AppendHostAddresses(const ProxyResult &aResult) +Error Server::Response::AppendHostIp6Addresses(const ProxyResult &aResult) { Error error = kErrorNone; const Dnssd::AddressResult *addrResult = aResult.mAddressResult; @@ -2108,6 +2245,30 @@ exit: return error; } +Error Server::Response::AppendHostIp4Addresses(const ProxyResult &aResult) +{ + Error error = kErrorNone; + const Dnssd::AddressResult *addrResult = aResult.mAddressResult; + + mSection = (mType == kAQuery) ? kAnswerSection : kAdditionalDataSection; + + for (uint16_t index = 0; index < addrResult->mAddressesLength; index++) + { + const Dnssd::AddressAndTtl &entry = addrResult->mAddresses[index]; + const Ip6::Address &address = AsCoreType(&entry.mAddress); + + if (entry.mTtl == 0) + { + continue; + } + + SuccessOrExit(error = AppendARecord(address, entry.mTtl)); + } + +exit: + return error; +} + bool Server::IsProxyAddressValid(const Ip6::Address &aAddress) { return !aAddress.IsLinkLocalUnicast() && !aAddress.IsMulticast() && !aAddress.IsUnspecified() && diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp index f584e3b12..4174ac5ae 100644 --- a/src/core/net/dnssd_server.hpp +++ b/src/core/net/dnssd_server.hpp @@ -326,6 +326,7 @@ private: kTxtQuery, kSrvTxtQuery, kAaaaQuery, + kAQuery, }; enum Section : uint8_t @@ -334,6 +335,12 @@ private: kAdditionalDataSection, }; + enum AddrType : uint8_t + { + kIp6AddrType, + kIp4AddrType, + }; + #if OPENTHREAD_CONFIG_DNSSD_DISCOVERY_PROXY_ENABLE enum ProxyAction : uint8_t { @@ -342,6 +349,7 @@ private: kResolvingSrv, kResolvingTxt, kResolvingIp6Address, + kResolvingIp4Address }; #endif @@ -384,33 +392,35 @@ private: { public: explicit Response(Instance &aInstance); - Error AllocateAndInitFrom(const Request &aRequest); - void InitFrom(ProxyQuery &aQuery, const ProxyQueryInfo &aInfo); - void SetResponseCode(ResponseCode aResponseCode) { mHeader.SetResponseCode(aResponseCode); } ResponseCode AddQuestionsFrom(const Request &aRequest); - Error ParseQueryName(void); - void ReadQueryName(Name::Buffer &aName) const; - bool QueryNameMatches(const char *aName) const; - Error AppendQueryName(void); - Error AppendPtrRecord(const char *aInstanceLabel, uint32_t aTtl); - Error AppendSrvRecord(const ServiceInstanceInfo &aInstanceInfo); - Error AppendSrvRecord(const char *aHostName, - uint32_t aTtl, - uint16_t aPriority, - uint16_t aWeight, - uint16_t aPort); - Error AppendTxtRecord(const ServiceInstanceInfo &aInstanceInfo); - Error AppendTxtRecord(const void *aTxtData, uint16_t aTxtLength, uint32_t aTtl); - Error AppendHostAddresses(const HostInfo &aHostInfo); - Error AppendHostAddresses(const ServiceInstanceInfo &aInstanceInfo); - Error AppendHostAddresses(const Ip6::Address *aAddrs, uint16_t aAddrsLength, uint32_t aTtl); - Error AppendAaaaRecord(const Ip6::Address &aAddress, uint32_t aTtl); - void UpdateRecordLength(ResourceRecord &aRecord, uint16_t aOffset); - void IncResourceRecordCount(void); - void Send(const Ip6::MessageInfo &aMessageInfo); - void Answer(const HostInfo &aHostInfo, const Ip6::MessageInfo &aMessageInfo); - void Answer(const ServiceInstanceInfo &aInstanceInfo, const Ip6::MessageInfo &aMessageInfo); - Error ExtractServiceInstanceLabel(const char *aInstanceName, Name::LabelBuffer &aLabel); + + Error AllocateAndInitFrom(const Request &aRequest); + void InitFrom(ProxyQuery &aQuery, const ProxyQueryInfo &aInfo); + void SetResponseCode(ResponseCode aResponseCode) { mHeader.SetResponseCode(aResponseCode); } + Error ParseQueryName(void); + void ReadQueryName(Name::Buffer &aName) const; + bool QueryNameMatches(const char *aName) const; + Error AppendQueryName(void); + Error AppendPtrRecord(const char *aInstanceLabel, uint32_t aTtl); + Error AppendSrvRecord(const ServiceInstanceInfo &aInstanceInfo); + Error AppendSrvRecord(const char *aHostName, + uint32_t aTtl, + uint16_t aPriority, + uint16_t aWeight, + uint16_t aPort); + Error AppendTxtRecord(const ServiceInstanceInfo &aInstanceInfo); + Error AppendTxtRecord(const void *aTxtData, uint16_t aTxtLength, uint32_t aTtl); + Error AppendHostAddresses(AddrType aAddrType, const HostInfo &aHostInfo); + Error AppendHostAddresses(const ServiceInstanceInfo &aInstanceInfo); + Error AppendHostAddresses(AddrType aAddrType, const Ip6::Address *aAddrs, uint16_t aAddrsLength, uint32_t aTtl); + Error AppendAaaaRecord(const Ip6::Address &aAddress, uint32_t aTtl); + Error AppendARecord(const Ip6::Address &aAddress, uint32_t aTtl); + void UpdateRecordLength(ResourceRecord &aRecord, uint16_t aOffset); + void IncResourceRecordCount(void); + void Send(const Ip6::MessageInfo &aMessageInfo); + void Answer(const HostInfo &aHostInfo, const Ip6::MessageInfo &aMessageInfo); + void Answer(const ServiceInstanceInfo &aInstanceInfo, const Ip6::MessageInfo &aMessageInfo); + Error ExtractServiceInstanceLabel(const char *aInstanceName, Name::LabelBuffer &aLabel); #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE Error ResolveBySrp(void); bool QueryNameMatchesService(const Srp::Server::Service &aService) const; @@ -422,8 +432,8 @@ private: Error AppendPtrRecord(const ProxyResult &aResult); Error AppendSrvRecord(const ProxyResult &aResult); Error AppendTxtRecord(const ProxyResult &aResult); - - Error AppendHostAddresses(const ProxyResult &aResult); + Error AppendHostIp6Addresses(const ProxyResult &aResult); + Error AppendHostIp4Addresses(const ProxyResult &aResult); #endif #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) @@ -493,16 +503,19 @@ private: void StartOrStopSrvResolver(Command aCommand, const ProxyQuery &aQuery, const ProxyQueryInfo &aInfo); void StartOrStopTxtResolver(Command aCommand, const ProxyQuery &aQuery, const ProxyQueryInfo &aInfo); void StartOrStopIp6Resolver(Command aCommand, Name::Buffer &aHostName); + void StartOrStopIp4Resolver(Command aCommand, Name::Buffer &aHostName); static void HandleBrowseResult(otInstance *aInstance, const otPlatDnssdBrowseResult *aResult); static void HandleSrvResult(otInstance *aInstance, const otPlatDnssdSrvResult *aResult); static void HandleTxtResult(otInstance *aInstance, const otPlatDnssdTxtResult *aResult); static void HandleIp6AddressResult(otInstance *aInstance, const otPlatDnssdAddressResult *aResult); + static void HandleIp4AddressResult(otInstance *aInstance, const otPlatDnssdAddressResult *aResult); void HandleBrowseResult(const Dnssd::BrowseResult &aResult); void HandleSrvResult(const Dnssd::SrvResult &aResult); void HandleTxtResult(const Dnssd::TxtResult &aResult); void HandleIp6AddressResult(const Dnssd::AddressResult &aResult); + void HandleIp4AddressResult(const Dnssd::AddressResult &aResult); void HandleResult(ProxyAction aAction, const Name::Buffer &aName, ResponseAppender aAppender, diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_server.py b/tests/scripts/thread-cert/border_router/test_dnssd_server.py index 8bff2b2e6..6af3bd69a 100755 --- a/tests/scripts/thread-cert/border_router/test_dnssd_server.py +++ b/tests/scripts/thread-cert/border_router/test_dnssd_server.py @@ -196,7 +196,7 @@ class TestDnssdServerOnBr(thread_cert.TestCase): }) # check some invalid queries - for qtype in ['A', 'CNAME']: + for qtype in ['CNAME']: dig_result = digger.dns_dig(server_addr, host1_full_name, qtype) self._assert_dig_result_matches(dig_result, { 'status': 'NOTIMP', diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py index 71166ef7d..a80d017b4 100755 --- a/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py +++ b/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py @@ -278,7 +278,7 @@ class TestDnssdServerOnMultiBr(thread_cert.TestCase): self._verify_discovery_proxy_meshcop(br2_addr, br2.get_network_name(), host) # 4. Check some invalid queries - for qtype in ['A', 'CNAME']: + for qtype in ['CNAME']: dig_result = host.dns_dig(br2_addr, host1_full_name, qtype) self._assert_dig_result_matches(dig_result, { 'status': 'NOTIMP', diff --git a/tests/unit/test_dnssd_discovery_proxy.cpp b/tests/unit/test_dnssd_discovery_proxy.cpp index c2dfc0d04..09536821a 100644 --- a/tests/unit/test_dnssd_discovery_proxy.cpp +++ b/tests/unit/test_dnssd_discovery_proxy.cpp @@ -566,7 +566,7 @@ struct TxtResolverInfo : public Clearable otPlatDnssdTxtCallback mCallback; }; -struct Ip6AddrResolverInfo : public Clearable +struct IpAddrResolverInfo : public Clearable { bool HostNameMatches(const char *aName) const { return !strcmp(mHostName, aName); } @@ -592,16 +592,19 @@ struct InvokeOnStart : public Clearable const otPlatDnssdSrvResult *mSrvResult; const otPlatDnssdTxtResult *mTxtResult; const otPlatDnssdAddressResult *mIp6AddrResult; + const otPlatDnssdAddressResult *mIp4AddrResult; }; -static BrowserInfo sStartBrowserInfo; -static BrowserInfo sStopBrowserInfo; -static SrvResolverInfo sStartSrvResolverInfo; -static SrvResolverInfo sStopSrvResolverInfo; -static TxtResolverInfo sStartTxtResolverInfo; -static TxtResolverInfo sStopTxtResolverInfo; -static Ip6AddrResolverInfo sStartIp6AddrResolverInfo; -static Ip6AddrResolverInfo sStopIp6AddrResolverInfo; +static BrowserInfo sStartBrowserInfo; +static BrowserInfo sStopBrowserInfo; +static SrvResolverInfo sStartSrvResolverInfo; +static SrvResolverInfo sStopSrvResolverInfo; +static TxtResolverInfo sStartTxtResolverInfo; +static TxtResolverInfo sStopTxtResolverInfo; +static IpAddrResolverInfo sStartIp6AddrResolverInfo; +static IpAddrResolverInfo sStopIp6AddrResolverInfo; +static IpAddrResolverInfo sStartIp4AddrResolverInfo; +static IpAddrResolverInfo sStopIp4AddrResolverInfo; static InvokeOnStart sInvokeOnStart; @@ -615,6 +618,8 @@ void ResetPlatDnssdApiInfo(void) sStopTxtResolverInfo.Clear(); sStartIp6AddrResolverInfo.Clear(); sStopIp6AddrResolverInfo.Clear(); + sStartIp4AddrResolverInfo.Clear(); + sStopIp4AddrResolverInfo.Clear(); sInvokeOnStart.Clear(); } @@ -674,6 +679,21 @@ void InvokeIp6AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, c aCallback(sInstance, &aResult); } +void InvokeIp4AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, const otPlatDnssdAddressResult &aResult) +{ + Log("Invoking Ip4 resolver callback"); + Log(" hostName : %s", aResult.mHostName); + Log(" if-index : %u", aResult.mInfraIfIndex); + Log(" numAddresses : %u", aResult.mAddressesLength); + for (uint16_t index = 0; index < aResult.mAddressesLength; index++) + { + Log(" address[%u] : %s", index, AsCoreType(&aResult.mAddresses[index].mAddress).ToString().AsCString()); + Log(" ttl[%u] : %u", index, aResult.mAddresses[index].mTtl); + } + + aCallback(sInstance, &aResult); +} + otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); @@ -802,6 +822,40 @@ void otPlatDnssdStopIp6AddressResolver(otInstance *aInstance, const otPlatDnssdA } } +void otPlatDnssdStartIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver) +{ + VerifyOrQuit(aResolver != nullptr); + + Log("otPlatDnssdStartIp4AddressResolver(\"%s\")", aResolver->mHostName); + + VerifyOrQuit(aInstance == sInstance); + VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex); + + sStartIp4AddrResolverInfo.UpdateFrom(aResolver); + + if (sInvokeOnStart.mIp4AddrResult != nullptr) + { + InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult); + } +} + +void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver) +{ + VerifyOrQuit(aResolver != nullptr); + + Log("otPlatDnssdStopIp4AddressResolver(\"%s\")", aResolver->mHostName); + + VerifyOrQuit(aInstance == sInstance); + VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex); + + sStopIp4AddrResolverInfo.UpdateFrom(aResolver); + + if (sInvokeOnStart.mIp6AddrResult != nullptr) + { + InvokeIp4AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult); + } +} + //---------------------------------------------------------------------------------------------------------------------- void TestProxyBasic(void) @@ -810,15 +864,18 @@ void TestProxyBasic(void) const uint8_t kTxtData[] = {3, 'A', '=', '1', 0}; - Srp::Server *srpServer; - Srp::Client *srpClient; - Dns::Client *dnsClient; - Dns::ServiceDiscovery::Server *dnsServer; - Dnssd::BrowseResult browseResult; - Dnssd::SrvResult srvResult; - Dnssd::TxtResult txtResult; - Dnssd::AddressResult ip6AddrrResult; - Dnssd::AddressAndTtl addressAndTtl; + Srp::Server *srpServer; + Srp::Client *srpClient; + Dns::Client *dnsClient; + Dns::ServiceDiscovery::Server *dnsServer; + Dnssd::BrowseResult browseResult; + Dnssd::SrvResult srvResult; + Dnssd::TxtResult txtResult; + Dnssd::AddressResult ip6AddrrResult; + Dnssd::AddressResult ip4AddrrResult; + Dnssd::AddressAndTtl addressAndTtl; + NetworkData::ExternalRouteConfig routeConfig; + Ip6::Address address; Log("--------------------------------------------------------------------------------------------"); Log("TestProxyBasic"); @@ -853,6 +910,19 @@ void TestProxyBasic(void) AdvanceTime(2000); VerifyOrQuit(srpClient->IsRunning()); + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); + Log("Add a route prefix (with NAT64 flag) to network data"); + + routeConfig.Clear(); + SuccessOrQuit(AsCoreType(&routeConfig.mPrefix.mPrefix).FromString("64:ff9b::")); + routeConfig.mPrefix.mLength = 96; + routeConfig.mPreference = NetworkData::kRoutePreferenceMedium; + routeConfig.mNat64 = true; + routeConfig.mStable = true; + + SuccessOrQuit(otBorderRouterAddRoute(sInstance, &routeConfig)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); sBrowseInfo.Reset(); @@ -870,6 +940,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp")); @@ -896,6 +968,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp")); VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback); @@ -959,6 +1033,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp")); VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("hulk")); @@ -991,6 +1067,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("compound")); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback); @@ -1034,6 +1112,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp")); VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("iron.man")); @@ -1062,6 +1142,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0); @@ -1120,6 +1202,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0); @@ -1147,6 +1231,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("starktower")); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback); @@ -1185,6 +1271,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("earth")); @@ -1214,6 +1302,8 @@ void TestProxyBasic(void) VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("earth")); VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback); @@ -1228,6 +1318,84 @@ void TestProxyBasic(void) VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == AsCoreType(&addressAndTtl.mAddress)); VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl); + Log("--------------------------------------------------------------------------------------------"); + + ResetPlatDnssdApiInfo(); + sResolveAddressInfo.Reset(); + + Log("ResolveIp4Address()"); + SuccessOrQuit(dnsClient->ResolveIp4Address("shield.default.service.arpa.", AddressCallback, sInstance)); + AdvanceTime(10); + + // Check that an IPv4 address resolver is started + + VerifyOrQuit(sStartBrowserInfo.mCallCount == 0); + VerifyOrQuit(sStopBrowserInfo.mCallCount == 0); + VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0); + + VerifyOrQuit(sStartIp4AddrResolverInfo.HostNameMatches("shield")); + + VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0); + + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); + Log("Invoke IPv4 Address Resolver callback"); + + SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("::ffff:1.2.3.4")); + addressAndTtl.mTtl = kTtl; + ip4AddrrResult.mHostName = "shield"; + ip4AddrrResult.mInfraIfIndex = kInfraIfIndex; + ip4AddrrResult.mAddresses = &addressAndTtl; + ip4AddrrResult.mAddressesLength = 1; + + InvokeIp4AddrResolverCallback(sStartIp4AddrResolverInfo.mCallback, ip4AddrrResult); + + AdvanceTime(10); + + // Check that the IPv4 address resolver is stopped + + VerifyOrQuit(sStartBrowserInfo.mCallCount == 0); + VerifyOrQuit(sStopBrowserInfo.mCallCount == 0); + VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0); + VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 1); + + VerifyOrQuit(sStopIp4AddrResolverInfo.HostNameMatches("shield")); + VerifyOrQuit(sStopIp4AddrResolverInfo.mCallback == sStartIp4AddrResolverInfo.mCallback); + + // Check that response is sent to client and validate it + + VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1); + SuccessOrQuit(sResolveAddressInfo.mError); + + VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa.")); + VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1); + + // The 1.2.3.4 address with the NAT64 prefix + SuccessOrQuit(address.FromString("64:ff9b:0:0:0:0:102:304")); + VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address); + VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl); + + VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1); + SuccessOrQuit(sResolveAddressInfo.mError); + + VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa.")); + VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1); + VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl); + + VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address); + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); Log("Stop DNS-SD server");