[dnssd] support forwarding DNS queries to platform upstream (#8668)

This commit adds a set of APsI for forwarding a DNS query to the
upstream DNS server via platform API and a posix platform
implementation.

This feature is disabled by default, and this PR adds a `dns server
upstream {enable|disable}` command CLI for enabling and disabling this
feature.

Tests will be added after ot-br-posix adds related support.
This commit is contained in:
Song GUO
2023-02-21 21:15:03 -08:00
committed by GitHub
parent c311b85cc9
commit 852d076f00
28 changed files with 1038 additions and 16 deletions
+1
View File
@@ -103,6 +103,7 @@ ot_option(OT_DHCP6_SERVER OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE "DHCP6 server")
ot_option(OT_DIAGNOSTIC OPENTHREAD_CONFIG_DIAG_ENABLE "diagnostic")
ot_option(OT_DNS_CLIENT OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE "DNS client")
ot_option(OT_DNS_DSO OPENTHREAD_CONFIG_DNS_DSO_ENABLE "DNS Stateful Operations (DSO)")
ot_option(OT_DNS_QUERY_UPSTREAM OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE "Allow sending DNS queries to upstream")
ot_option(OT_DNSSD_SERVER OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE "DNS-SD server")
ot_option(OT_DUA OPENTHREAD_CONFIG_DUA_ENABLE "Domain Unicast Address (DUA)")
ot_option(OT_ECDSA OPENTHREAD_CONFIG_ECDSA_ENABLE "ECDSA")
+1
View File
@@ -35,6 +35,7 @@ This page lists the available common switches with description. Unless stated ot
| DEBUG_UART_LOG | not implemented | Enables the log output for the debug UART. Requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART to be enabled. |
| DNS_CLIENT | OT_DNS_CLIENT | Enables support for DNS client. Enable this switch on a device that sends a DNS query for AAAA (IPv6) record. |
| DNS_DSO | OT_DNS_DSO | Enables support for DNS Stateful Operations (DSO). |
| DNS_QUERY_UPSTREAM | OT_DNS_QUERY_UPSTREAM | Enables forwarding DNS queries to upstream DNS server. |
| DNSSD_SERVER | OT_DNSSD_SERVER | Enables support for DNS-SD server. DNS-SD server use service information from local SRP server to resolve DNS-SD query questions. |
| DUA | OT_DUA | Enables the Domain Unicast Address feature for Thread 1.2. |
| DYNAMIC_LOG_LEVEL | not implemented | Enables the dynamic log level feature. Enable this switch if OpenThread log level is required to be set at runtime. See [Logging guide](https://openthread.io/guides/build/logs) to learn more. |
+5
View File
@@ -52,6 +52,7 @@ DISABLE_DOC ?= 0
DISABLE_TOOLS ?= 0
DNS_CLIENT ?= 0
DNS_DSO ?= 0
DNS_QUERY_UPSTREAM ?= 0
DNSSD_SERVER ?= 0
DUA ?= 0
DYNAMIC_LOG_LEVEL ?= 0
@@ -212,6 +213,10 @@ ifeq ($(DNS_DSO),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNS_DSO_ENABLE=1
endif
ifeq ($(DNS_QUERY_UPSTREAM), 1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE=1
endif
ifeq ($(DNSSD_SERVER),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1
endif
+1
View File
@@ -102,6 +102,7 @@ ot_platform_headers = \
openthread/platform/crypto.h \
openthread/platform/debug_uart.h \
openthread/platform/diag.h \
openthread/platform/dns.h \
openthread/platform/dso_transport.h \
openthread/platform/entropy.h \
openthread/platform/flash.h \
+1
View File
@@ -86,6 +86,7 @@ source_set("openthread") {
"platform/crypto.h",
"platform/debug_uart.h",
"platform/diag.h",
"platform/dns.h",
"platform/dso_transport.h",
"platform/entropy.h",
"platform/flash.h",
+15
View File
@@ -245,6 +245,21 @@ otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*a
*/
const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance);
/**
* Enable or disable forwarding DNS queries to platform DNS upstream API.
*
* Available when `OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE` is enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnabled A boolean to enable/disable forwarding DNS queries to upstream.
*
* @sa otPlatDnsStartUpstreamQuery
* @sa otPlatDnsCancelUpstreamQuery
* @sa otPlatDnsUpstreamQueryDone
*
*/
void otDnssdUpstreamQuerySetEnabled(otInstance *aInstance, bool aEnabled);
/**
* @}
*
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (288)
#define OPENTHREAD_API_VERSION (289)
/**
* @addtogroup api-instance
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file defines the platform DNS interface.
*
*/
#ifndef OPENTHREAD_PLATFORM_DNS_H_
#define OPENTHREAD_PLATFORM_DNS_H_
#include <openthread/instance.h>
#include <openthread/message.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup plat-dns
*
* @brief
* This module includes the platform abstraction for sending recursive DNS query to upstream DNS servers.
*
* @{
*
*/
/**
* This opaque type represents an upstream DNS query transaction.
*
*/
typedef struct otPlatDnsUpstreamQuery otPlatDnsUpstreamQuery;
/**
* Starts an upstream query transaction.
*
* - In success case (and errors represented by DNS protocol messages), the platform is expected to call
* `otPlatDnsUpstreamQueryDone`.
* - The OpenThread core may cancel a (possibly timeout) query transaction by calling
* `otPlatDnsCancelUpstreamQuery`, the platform must not call `otPlatDnsUpstreamQueryDone` on a
* cancelled transaction.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aTxn A pointer to the opaque DNS query transaction object.
* @param[in] aQuery A message buffer of the DNS payload that should be sent to upstream DNS server.
*
*/
void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery);
/**
* Cancels a transaction of upstream query.
*
* The platform must call `otPlatDnsUpstreamQueryDone` to release the resources.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aTxn A pointer to the opaque DNS query transaction object.
*
*/
void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn);
/**
* The platform calls this function to finish DNS query.
*
* The transaction will be released, so the platform must not call on the same transaction twice. This function passes
* the ownership of `aResponse` to OpenThread stack.
*
* Platform can pass a nullptr to close a transaction without a response.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aTxn A pointer to the opaque DNS query transaction object.
* @param[in] aResponse A message buffer of the DNS response payload or `nullptr` to close a transaction without a
* response.
*
*/
extern void otPlatDnsUpstreamQueryDone(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, otMessage *aResponse);
/**
* @}
*
*/
#ifdef __cplusplus
}
#endif
#endif
+1
View File
@@ -108,6 +108,7 @@ OT_CLANG_TIDY_BUILD_OPTS=(
'-DOT_DIAGNOSTIC=ON'
'-DOT_DNS_CLIENT=ON'
'-DOT_DNS_DSO=ON'
'-DOT_DNS_QUERY_UPSTREAM=ON'
'-DOT_DNSSD_SERVER=ON'
'-DOT_DUA=ON'
'-DOT_MLR=ON'
+31
View File
@@ -3334,6 +3334,37 @@ template <> otError Interpreter::Process<Cmd("dns")>(Arg aArgs[])
}
#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
else if (aArgs[0] == "server")
{
if (aArgs[1].IsEmpty())
{
error = OT_ERROR_INVALID_ARGS;
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
/**
* @cli dns server upstream {enable|disable}
* @code
* Done
* @endcode
* @cparam dns server upstream @ca{enable|disable}
* @par api_copy
* #otDnssdUpstreamQuerySetEnabled
*/
else if (aArgs[1] == "upstream")
{
bool enable;
SuccessOrExit(error = ParseEnableOrDisable(aArgs[2], enable));
otDnssdUpstreamQuerySetEnabled(GetInstancePtr(), enable);
}
#endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
else
{
ExitNow(error = OT_ERROR_INVALID_COMMAND);
}
}
#endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
else
{
ExitNow(error = OT_ERROR_INVALID_COMMAND);
+1
View File
@@ -540,6 +540,7 @@ openthread_core_files = [
"net/dns_client.hpp",
"net/dns_dso.cpp",
"net/dns_dso.hpp",
"net/dns_platform.cpp",
"net/dns_types.cpp",
"net/dns_types.hpp",
"net/dnssd_server.cpp",
+1
View File
@@ -161,6 +161,7 @@ set(COMMON_SOURCES
net/dhcp6_server.cpp
net/dns_client.cpp
net/dns_dso.cpp
net/dns_platform.cpp
net/dns_types.cpp
net/dnssd_server.cpp
net/icmp6.cpp
+1
View File
@@ -251,6 +251,7 @@ SOURCES_COMMON = \
net/dhcp6_server.cpp \
net/dns_client.cpp \
net/dns_dso.cpp \
net/dns_platform.cpp \
net/dns_types.cpp \
net/dnssd_server.cpp \
net/icmp6.cpp \
+7
View File
@@ -86,4 +86,11 @@ const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance)
return &AsCoreType(aInstance).Get<Dns::ServiceDiscovery::Server>().GetCounters();
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
void otDnssdUpstreamQuerySetEnabled(otInstance *aInstance, bool aEnabled)
{
return AsCoreType(aInstance).Get<Dns::ServiceDiscovery::Server>().SetUpstreamQueryEnabled(aEnabled);
}
#endif
#endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+11
View File
@@ -75,4 +75,15 @@
#define OPENTHREAD_CONFIG_DNSSD_QUERY_TIMEOUT 6000
#endif
/**
* @def OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
*
* Define to 1 to enable upstream forwarding support. The platform MUST implement `otPlatDnsStartUpstreamQuery` and
* `otPlatDnsCancelUpstreamQuery`.
*
*/
#ifndef OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
#define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 0
#endif
#endif // CONFIG_DNSSD_SERVER_H_
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements the DNS platform callbacks into OpenThread.
*/
#include "openthread-core-config.h"
#include <openthread/instance.h>
#include <openthread/platform/dns.h>
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/message.hpp"
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
using namespace ot;
void otPlatDnsUpstreamQueryDone(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, otMessage *aResponse)
{
return AsCoreType(aInstance).Get<Dns::ServiceDiscovery::Server>().OnUpstreamQueryDone(AsCoreType(aTxn),
AsCoreTypePtr(aResponse));
}
#endif
+5
View File
@@ -687,6 +687,11 @@ exit:
return match;
}
bool Name::IsSameDomain(const char *aDomain1, const char *aDomain2)
{
return IsSubDomainOf(aDomain1, aDomain2) && IsSubDomainOf(aDomain2, aDomain1);
}
Error ResourceRecord::ParseRecords(const Message &aMessage, uint16_t &aOffset, uint16_t aNumRecords)
{
Error error = kErrorNone;
+14
View File
@@ -990,6 +990,20 @@ public:
*/
static bool IsSubDomainOf(const char *aName, const char *aDomain);
/**
* This static method tests if the two DNS name are the same domain.
*
* Both @p aDomain1 and @p aDomain2 can end without dot ('.').
*
* @param[in] aDomain1 The dot-separated name.
* @param[in] aDomain2 The dot-separated domain.
*
* @retval TRUE If the two DNS names are the same domain.
* @retval FALSE If the two DNS names are not the same domain.
*
*/
static bool IsSameDomain(const char *aDomain1, const char *aDomain2);
private:
// The first 2 bits of the encoded label specifies label type.
//
+190 -10
View File
@@ -35,6 +35,8 @@
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
#include <openthread/platform/dns.h>
#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
@@ -52,10 +54,11 @@ namespace ServiceDiscovery {
RegisterLogModule("DnssdServer");
const char Server::kDnssdProtocolUdp[] = "_udp";
const char Server::kDnssdProtocolTcp[] = "_tcp";
const char Server::kDnssdSubTypeLabel[] = "._sub.";
const char Server::kDefaultDomainName[] = "default.service.arpa.";
const char Server::kDnssdProtocolUdp[] = "_udp";
const char Server::kDnssdProtocolTcp[] = "_tcp";
const char Server::kDnssdSubTypeLabel[] = "._sub.";
const char Server::kDefaultDomainName[] = "default.service.arpa.";
const char *Server::kBlockedDomains[] = {"ipv4only.arpa."};
Server::Server(Instance &aInstance)
: InstanceLocator(aInstance)
@@ -63,6 +66,9 @@ Server::Server(Instance &aInstance)
, mQueryCallbackContext(nullptr)
, mQuerySubscribe(nullptr)
, mQueryUnsubscribe(nullptr)
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
, mEnableUpstreamQuery(false)
#endif
, mTimer(aInstance)
{
mCounters.Clear();
@@ -103,6 +109,16 @@ void Server::Stop(void)
}
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
for (UpstreamQueryTransaction &txn : mUpstreamQueryTransactions)
{
if (txn.IsValid())
{
ResetUpstreamQueryTransaction(txn, kErrorFailed);
}
}
#endif
mTimer.Stop();
IgnoreError(mSocket.Close());
@@ -145,8 +161,22 @@ void Server::ProcessQuery(const Header &aRequestHeader, Message &aRequestMessage
Message *responseMessage = nullptr;
Header responseHeader;
NameCompressInfo compressInfo(kDefaultDomainName);
Header::Response response = Header::kResponseSuccess;
bool resolveByQueryCallbacks = false;
Header::Response response = Header::kResponseSuccess;
bool shouldSendResponse = true;
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
if (mEnableUpstreamQuery && ShouldForwardToUpstream(aRequestHeader, aRequestMessage))
{
error = ResolveByUpstream(aRequestMessage, aMessageInfo);
if (error == kErrorNone)
{
shouldSendResponse = false;
ExitNow();
}
response = Header::kResponseServerFailure;
LogWarn("Failed to forward DNS query to upstream: %s", ErrorToString(error));
}
#endif
responseMessage = mSocket.NewMessage(0);
VerifyOrExit(responseMessage != nullptr, error = kErrorNoBufs);
@@ -158,6 +188,14 @@ void Server::ProcessQuery(const Header &aRequestHeader, Message &aRequestMessage
responseHeader.Clear();
responseHeader.SetType(Header::kTypeResponse);
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
responseHeader.SetQueryType(aRequestHeader.GetQueryType());
if (aRequestHeader.IsRecursionDesiredFlagSet())
{
responseHeader.SetRecursionDesiredFlag();
}
// We may met errors when forwarding the query to the upstream
VerifyOrExit(response == Header::kResponseSuccess);
// Validate the query
VerifyOrExit(aRequestHeader.GetQueryType() == Header::kQueryTypeStandard,
@@ -172,13 +210,11 @@ void Server::ProcessQuery(const Header &aRequestHeader, Message &aRequestMessage
// Answer the questions
response = ResolveBySrp(responseHeader, *responseMessage, compressInfo);
#endif
// Resolve the question using query callbacks if SRP server failed to resolve the questions.
if (responseHeader.GetAnswerCount() == 0)
{
if (kErrorNone == ResolveByQueryCallbacks(responseHeader, *responseMessage, compressInfo, aMessageInfo))
{
resolveByQueryCallbacks = true;
shouldSendResponse = false;
}
}
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
@@ -189,7 +225,7 @@ void Server::ProcessQuery(const Header &aRequestHeader, Message &aRequestMessage
#endif
exit:
if (error == kErrorNone && !resolveByQueryCallbacks)
if (error == kErrorNone && shouldSendResponse)
{
SendResponse(responseHeader, response, *responseMessage, aMessageInfo, mSocket);
}
@@ -839,6 +875,87 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
bool Server::ShouldForwardToUpstream(const Header &aRequestHeader, const Message &aRequestMessage)
{
bool ret = true;
uint16_t readOffset;
char name[Name::kMaxNameSize];
VerifyOrExit(aRequestHeader.IsRecursionDesiredFlagSet(), ret = false);
readOffset = sizeof(Header);
for (uint16_t i = 0; i < aRequestHeader.GetQuestionCount(); i++)
{
VerifyOrExit(kErrorNone == Name::ReadName(aRequestMessage, readOffset, name, sizeof(name)), ret = false);
readOffset += sizeof(Question);
VerifyOrExit(!Name::IsSubDomainOf(name, kDefaultDomainName), ret = false);
for (const char *blockedDomain : kBlockedDomains)
{
VerifyOrExit(!Name::IsSameDomain(name, blockedDomain), ret = false);
}
}
exit:
return ret;
}
void Server::OnUpstreamQueryDone(UpstreamQueryTransaction &aQueryTransaction, Message *aResponseMessage)
{
Error error = kErrorNone;
VerifyOrExit(aQueryTransaction.IsValid(), error = kErrorInvalidArgs);
if (aResponseMessage != nullptr)
{
error = mSocket.SendTo(*aResponseMessage, aQueryTransaction.GetMessageInfo());
}
ResetUpstreamQueryTransaction(aQueryTransaction, error);
ResetTimer();
exit:
FreeMessageOnError(aResponseMessage, error);
}
Server::UpstreamQueryTransaction *Server::AllocateUpstreamQueryTransaction(const Ip6::MessageInfo &aMessageInfo)
{
UpstreamQueryTransaction *ret = nullptr;
for (UpstreamQueryTransaction &txn : mUpstreamQueryTransactions)
{
if (!txn.IsValid())
{
ret = &txn;
txn.Init(aMessageInfo);
break;
}
}
if (ret != nullptr)
{
LogInfo("Upstream query transaction %d initialized.", static_cast<int>(ret - mUpstreamQueryTransactions));
mTimer.FireAtIfEarlier(ret->GetExpireTime());
}
return ret;
}
Error Server::ResolveByUpstream(const Message &aRequestMessage, const Ip6::MessageInfo &aMessageInfo)
{
Error error = kErrorNone;
UpstreamQueryTransaction *txn = nullptr;
txn = AllocateUpstreamQueryTransaction(aMessageInfo);
VerifyOrExit(txn != nullptr, error = kErrorNoBufs);
otPlatDnsStartUpstreamQuery(&GetInstance(), txn, &aRequestMessage);
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
Server::QueryTransaction *Server::NewQuery(const Header &aResponseHeader,
Message &aResponseMessage,
const NameCompressInfo &aCompressInfo,
@@ -1143,6 +1260,21 @@ void Server::HandleTimer(void)
}
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
for (UpstreamQueryTransaction &query : mUpstreamQueryTransactions)
{
if (!query.IsValid())
{
continue;
}
if (query.GetExpireTime() <= now)
{
otPlatDnsCancelUpstreamQuery(&GetInstance(), &query);
}
}
#endif
ResetTimer();
}
@@ -1171,6 +1303,28 @@ void Server::ResetTimer(void)
}
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
for (UpstreamQueryTransaction &query : mUpstreamQueryTransactions)
{
TimeMilli expire;
if (!query.IsValid())
{
continue;
}
expire = query.GetExpireTime();
if (expire <= now)
{
nextExpire = now;
}
else if (expire < nextExpire)
{
nextExpire = expire;
}
}
#endif
if (nextExpire < now.GetDistantFuture())
{
mTimer.FireAt(nextExpire);
@@ -1246,6 +1400,32 @@ void Server::UpdateResponseCounters(Header::Response aResponseCode)
}
}
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
void Server::UpstreamQueryTransaction::Init(const Ip6::MessageInfo &aMessageInfo)
{
mMessageInfo = aMessageInfo;
mValid = true;
mExpireTime = TimerMilli::GetNow() + kQueryTimeout;
}
void Server::ResetUpstreamQueryTransaction(UpstreamQueryTransaction &aTxn, Error aError)
{
int index = static_cast<int>(&aTxn - mUpstreamQueryTransactions);
// Avoid the warnings when info / warn logging is disabled.
OT_UNUSED_VARIABLE(index);
if (aError == kErrorNone)
{
LogInfo("Upstream query transaction %d completed.", index);
}
else
{
LogWarn("Upstream query transaction %d closed: %s.", index, ErrorToString(aError));
}
aTxn.Reset();
}
#endif
} // namespace ServiceDiscovery
} // namespace Dns
} // namespace ot
+105 -5
View File
@@ -49,6 +49,10 @@
* This file includes definitions for the DNS-SD server.
*/
struct otPlatDnsUpstreamQuery
{
};
namespace ot {
namespace Srp {
@@ -75,6 +79,62 @@ public:
{
};
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
/**
* This class represents an upstream query transaction. The methods should only be used by
* `Dns::ServiceDiscovery::Server`.
*
*/
class UpstreamQueryTransaction : public otPlatDnsUpstreamQuery
{
public:
/**
* This method returns whether the transaction is valid.
*
* @retval TRUE The transaction is valid.
* @retval FALSE The transaction is not valid.
*
*/
bool IsValid(void) const { return mValid; }
/**
* This method returns the time when the transaction expires.
*
* @returns The expire time of the transaction.
*
*/
TimeMilli GetExpireTime(void) const { return mExpireTime; }
/**
* This method resets the transaction with a reason. The transaction will be invalid and can be reused for
* another upstream query after this call.
*
*/
void Reset(void) { mValid = false; }
/**
* This method initializes the transaction.
*
* @param[in] aMessageInfo The IP message info of the query.
*
*/
void Init(const Ip6::MessageInfo &aMessageInfo);
/**
* This method returns the message info of the query.
*
* @returns The message info of the query.
*
*/
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
private:
Ip6::MessageInfo mMessageInfo;
TimeMilli mExpireTime;
bool mValid;
};
#endif
/**
* This enumeration specifies a DNS-SD query type.
*
@@ -133,6 +193,28 @@ public:
*/
void HandleDiscoveredServiceInstance(const char *aServiceFullName, const otDnssdServiceInstanceInfo &aInstanceInfo);
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
/**
* This method notifies an answer of an upstream DNS query.
*
* The Transaction will be released.
*
* @param[in] aQueryTransaction A reference to upstream DNS query transaction.
* @param[in] aResponseMessage A pointer to response UDP message, should be allocated from Udp::NewMessage.
* Passing a nullptr means close the transaction without a response.
*
*/
void OnUpstreamQueryDone(UpstreamQueryTransaction &aQueryTransaction, Message *aResponseMessage);
/**
* This method enables or disables forwarding DNS queries to platform DNS upstream API.
*
* @param[in] aEnabled A boolean to enable/disable forwarding DNS queries to upstream.
*
*/
void SetUpstreamQueryEnabled(bool aEnabled) { mEnableUpstreamQuery = aEnabled; }
#endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
/**
* This method notifies a discovered host.
*
@@ -250,10 +332,11 @@ private:
uint16_t mHostNameOffset; // Offset of host name serialization into the response message.
};
static constexpr bool kBindUnspecifiedNetif = OPENTHREAD_CONFIG_DNSSD_SERVER_BIND_UNSPECIFIED_NETIF;
static constexpr uint8_t kProtocolLabelLength = 4;
static constexpr uint8_t kSubTypeLabelLength = 4;
static constexpr uint16_t kMaxConcurrentQueries = 32;
static constexpr bool kBindUnspecifiedNetif = OPENTHREAD_CONFIG_DNSSD_SERVER_BIND_UNSPECIFIED_NETIF;
static constexpr uint8_t kProtocolLabelLength = 4;
static constexpr uint8_t kSubTypeLabelLength = 4;
static constexpr uint16_t kMaxConcurrentQueries = 32;
static constexpr uint16_t kMaxConcurrentUpstreamQueries = 32;
// This structure represents the splitting information of a full name.
struct NameComponentsOffsetInfo
@@ -384,6 +467,13 @@ private:
const Srp::Server::Service *aService);
#endif
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
static bool ShouldForwardToUpstream(const Header &aRequestHeader, const Message &aRequestMessage);
UpstreamQueryTransaction *AllocateUpstreamQueryTransaction(const Ip6::MessageInfo &aMessageInfo);
void ResetUpstreamQueryTransaction(UpstreamQueryTransaction &aTxn, Error aError);
Error ResolveByUpstream(const Message &aRequestMessage, const Ip6::MessageInfo &aMessageInfo);
#endif
Error ResolveByQueryCallbacks(Header &aResponseHeader,
Message &aResponseMessage,
NameCompressInfo &aCompressInfo,
@@ -424,7 +514,14 @@ private:
void *mQueryCallbackContext;
otDnssdQuerySubscribeCallback mQuerySubscribe;
otDnssdQueryUnsubscribeCallback mQueryUnsubscribe;
ServerTimer mTimer;
static const char *kBlockedDomains[];
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
bool mEnableUpstreamQuery;
UpstreamQueryTransaction mUpstreamQueryTransactions[kMaxConcurrentUpstreamQueries];
#endif
ServerTimer mTimer;
Counters mCounters;
};
@@ -433,6 +530,9 @@ private:
} // namespace Dns
DefineMapEnum(otDnssdQueryType, Dns::ServiceDiscovery::Server::DnsQueryType);
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
DefineCoreType(otPlatDnsUpstreamQuery, Dns::ServiceDiscovery::Server::UpstreamQueryTransaction);
#endif
} // namespace ot
+1
View File
@@ -120,6 +120,7 @@ add_library(openthread-posix
power_updater.cpp
radio.cpp
radio_url.cpp
resolver.cpp
settings.cpp
spi_interface.cpp
system.cpp
+1
View File
@@ -62,6 +62,7 @@ libopenthread_posix_a_SOURCES = \
power.cpp \
power_updater.cpp \
radio.cpp \
resolver.cpp \
radio_url.cpp \
settings.cpp \
spi_interface.cpp \
+17
View File
@@ -152,6 +152,8 @@ extern int
#include "common/debug.hpp"
#include "net/ip6_address.hpp"
#include "resolver.hpp"
unsigned int gNetifIndex = 0;
char gNetifName[IFNAMSIZ];
otIp4Cidr gNat64Cidr;
@@ -209,6 +211,10 @@ static otIp6Prefix sAddedExternalRoutes[kMaxExternalRoutesNum];
static constexpr uint32_t kNat64RoutePriority = 100; ///< Priority for route to NAT64 CIDR, 100 means a high priority.
#endif
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
ot::Posix::Resolver gResolver;
#endif
#if defined(RTM_NEWMADDR) || defined(__NetBSD__)
// on some BSDs (mac OS, FreeBSD), we get RTM_NEWMADDR/RTM_DELMADDR messages, so we don't need to monitor using MLD
// on NetBSD, MLD monitoring simply doesn't work
@@ -1899,6 +1905,9 @@ void platformNetifSetUp(void)
#if OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
otIp6SetMulticastPromiscuousEnabled(aInstance, true);
#endif
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
gResolver.Init();
#endif
}
void platformNetifTearDown(void) {}
@@ -1957,6 +1966,10 @@ void platformNetifUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *a
FD_SET(sMLDMonitorFd, aErrorFdSet);
#endif
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
gResolver.UpdateFdSet(aReadFdSet, aErrorFdSet, aMaxFd);
#endif
if (sTunFd > *aMaxFd)
{
*aMaxFd = sTunFd;
@@ -2019,6 +2032,10 @@ void platformNetifProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, c
}
#endif
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
gResolver.Process(aReadFdSet, aErrorFdSet);
#endif
exit:
return;
}
+290
View File
@@ -0,0 +1,290 @@
/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "resolver.hpp"
#include "platform-posix.h"
#include <openthread/logging.h>
#include <openthread/message.h>
#include <openthread/udp.h>
#include <openthread/platform/dns.h>
#include "common/code_utils.hpp"
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <cassert>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <fstream>
#include <string>
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
namespace {
constexpr char kResolveConfLocation[] = "/etc/resolv.conf";
constexpr char kNameserverItem[] = "nameserver";
} // namespace
extern ot::Posix::Resolver gResolver;
namespace ot {
namespace Posix {
void Resolver::Init(void)
{
memset(mUpstreamTransaction, 0, sizeof(mUpstreamTransaction));
LoadDnsServerListFromConf();
}
void Resolver::LoadDnsServerListFromConf(void)
{
std::string line;
std::ifstream fp;
fp.open(kResolveConfLocation);
if (fp.bad())
{
otLogCritPlat("Cannot read %s for domain name servers, default to 127.0.0.1", kResolveConfLocation);
mUpstreamDnsServerCount = 1;
assert(inet_pton(AF_INET, "127.0.0.1", &mUpstreamDnsServerList[0]) == 1);
ExitNow();
}
while (std::getline(fp, line) && mUpstreamDnsServerCount < kMaxUpstreamServerCount)
{
if (line.find(kNameserverItem, 0) == 0)
{
in_addr_t addr;
if (inet_pton(AF_INET, &line.c_str()[sizeof(kNameserverItem)], &addr) == 1)
{
otLogCritPlat("Got nameserver #%d: %s", mUpstreamDnsServerCount,
&line.c_str()[sizeof(kNameserverItem)]);
mUpstreamDnsServerList[mUpstreamDnsServerCount] = addr;
mUpstreamDnsServerCount++;
}
}
}
exit:
return;
}
void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
{
char packet[kMaxDnsMessageSize];
otError error = OT_ERROR_NONE;
uint16_t length = otMessageGetLength(aQuery);
sockaddr_in serverAddr;
Transaction *txn;
VerifyOrExit(length <= kMaxDnsMessageSize, error = OT_ERROR_NO_BUFS);
VerifyOrExit(otMessageRead(aQuery, 0, &packet, sizeof(packet)) == length, error = OT_ERROR_NO_BUFS);
txn = AllocateTransaction(aTxn);
VerifyOrExit(txn != nullptr, error = OT_ERROR_NO_BUFS);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(53);
for (int i = 0; i < mUpstreamDnsServerCount; i++)
{
serverAddr.sin_addr.s_addr = mUpstreamDnsServerList[i];
VerifyOrExit(
sendto(txn->mUdpFd, packet, length, MSG_DONTWAIT, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) > 0,
error = OT_ERROR_NO_ROUTE);
}
otLogInfoPlat("Forwarded DNS query %p to %d server(s).", static_cast<void *>(aTxn), mUpstreamDnsServerCount);
exit:
if (error != OT_ERROR_NONE)
{
otLogCritPlat("Failed to forward DNS query %p to server: %d", static_cast<void *>(aTxn), error);
}
return;
}
void Resolver::Cancel(otPlatDnsUpstreamQuery *aTxn)
{
Transaction *txn = GetTransaction(aTxn);
if (txn != nullptr)
{
CloseTransaction(txn);
}
otPlatDnsUpstreamQueryDone(gInstance, aTxn, nullptr);
}
Resolver::Transaction *Resolver::AllocateTransaction(otPlatDnsUpstreamQuery *aThreadTxn)
{
int fdOrError = 0;
Transaction *ret = nullptr;
for (Transaction &txn : mUpstreamTransaction)
{
if (txn.mThreadTxn == nullptr)
{
fdOrError = socket(AF_INET, SOCK_DGRAM, 0);
if (fdOrError < 0)
{
otLogInfoPlat("Failed to create socket for upstream resolver: %d", fdOrError);
break;
}
ret = &txn;
ret->mUdpFd = fdOrError;
ret->mThreadTxn = aThreadTxn;
break;
}
}
return ret;
}
void Resolver::ForwardResponse(Transaction *aTxn)
{
char response[kMaxDnsMessageSize];
ssize_t readSize;
otMessage *message;
VerifyOrExit((readSize = read(aTxn->mUdpFd, response, sizeof(response))) > 0);
message = otUdpNewMessage(gInstance, nullptr);
SuccessOrExit(otMessageAppend(message, response, readSize));
otPlatDnsUpstreamQueryDone(gInstance, aTxn->mThreadTxn, message);
message = nullptr;
exit:
if (readSize < 0)
{
otLogInfoPlat("Failed to read response from upstream resolver socket: %d", errno);
}
if (message != nullptr)
{
otMessageFree(message);
}
}
Resolver::Transaction *Resolver::GetTransaction(int aFd)
{
Transaction *ret = nullptr;
for (Transaction &txn : mUpstreamTransaction)
{
if (txn.mThreadTxn != nullptr && txn.mUdpFd == aFd)
{
ret = &txn;
break;
}
}
return ret;
}
Resolver::Transaction *Resolver::GetTransaction(otPlatDnsUpstreamQuery *aThreadTxn)
{
Transaction *ret = nullptr;
for (Transaction &txn : mUpstreamTransaction)
{
if (txn.mThreadTxn == aThreadTxn)
{
ret = &txn;
break;
}
}
return ret;
}
void Resolver::CloseTransaction(Transaction *aTxn)
{
if (aTxn->mUdpFd >= 0)
{
close(aTxn->mUdpFd);
aTxn->mUdpFd = -1;
}
aTxn->mThreadTxn = nullptr;
}
void Resolver::UpdateFdSet(fd_set *aReadFdSet, fd_set *aErrorFdSet, int *aMaxFd)
{
for (Transaction &txn : mUpstreamTransaction)
{
if (txn.mThreadTxn != nullptr)
{
FD_SET(txn.mUdpFd, aReadFdSet);
FD_SET(txn.mUdpFd, aErrorFdSet);
if (txn.mUdpFd > *aMaxFd)
{
*aMaxFd = txn.mUdpFd;
}
}
}
}
void Resolver::Process(const fd_set *aReadFdSet, const fd_set *aErrorFdSet)
{
for (Transaction &txn : mUpstreamTransaction)
{
if (txn.mThreadTxn != nullptr)
{
// Note: On Linux, we can only get the error via read, so they should share the same logic.
if (FD_ISSET(txn.mUdpFd, aErrorFdSet) || FD_ISSET(txn.mUdpFd, aReadFdSet))
{
ForwardResponse(&txn);
CloseTransaction(&txn);
}
}
}
}
} // namespace Posix
} // namespace ot
void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
{
OT_UNUSED_VARIABLE(aInstance);
gResolver.Query(aTxn, aQuery);
}
void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn)
{
OT_UNUSED_VARIABLE(aInstance);
gResolver.Cancel(aTxn);
}
#endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
+119
View File
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POSIX_PLATFORM_RESOLVER_HPP_
#define POSIX_PLATFORM_RESOLVER_HPP_
#include <openthread/platform/dns.h>
#include <arpa/inet.h>
#include <sys/select.h>
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
namespace ot {
namespace Posix {
class Resolver
{
public:
constexpr static ssize_t kMaxDnsMessageSize = 512;
constexpr static ssize_t kMaxUpstreamTransactionCount = 16;
constexpr static ssize_t kMaxUpstreamServerCount = 3;
/**
* This method initialize the upstream DNS resolver.
*
*/
void Init(void);
/**
* Sends the query to the upstream.
*
* @param[in] aTxn A pointer to the OpenThread upstream DNS query transaction.
* @param[in] aQuery A pointer to a message for the payload of the DNS query.
*
*/
void Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery);
/**
* Cancels a upstream DNS query transaction.
*
* @param[in] aTxn A pointer to the OpenThread upstream DNS query transaction.
*
*/
void Cancel(otPlatDnsUpstreamQuery *aTxn);
/**
* Updates the file descriptor sets with file descriptors used by the radio driver.
*
* @param[in,out] aReadFdSet A reference to the read file descriptors.
* @param[in,out] aErrorFdSet A reference to the error file descriptors.
* @param[in,out] aMaxFd A reference to the max file descriptor.
* @param[in,out] aTimeout A reference to the timeout.
*
*/
void UpdateFdSet(fd_set *aReadFdSet, fd_set *aErrorFdSet, int *aMaxFd);
/**
* Handles the result of select.
*
* @param[in] aReadFdSet A reference to the read file descriptors.
* @param[in] aErrorFdSet A reference to the error file descriptors.
*
*/
void Process(const fd_set *aReadFdSet, const fd_set *aErrorFdSet);
private:
struct Transaction
{
otPlatDnsUpstreamQuery *mThreadTxn;
int mUdpFd;
};
Transaction *GetTransaction(int aFd);
Transaction *GetTransaction(otPlatDnsUpstreamQuery *aThreadTxn);
Transaction *AllocateTransaction(otPlatDnsUpstreamQuery *aThreadTxn);
void ForwardResponse(Transaction *aTxn);
void CloseTransaction(Transaction *aTxn);
void FinishTransaction(int aFd);
void LoadDnsServerListFromConf(void);
int mUpstreamDnsServerCount = 0;
in_addr_t mUpstreamDnsServerList[kMaxUpstreamServerCount];
Transaction mUpstreamTransaction[kMaxUpstreamTransactionCount];
};
} // namespace Posix
} // namespace ot
#endif // OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
#endif // POSIX_PLATFORM_RESOLVER_HPP_
+37
View File
@@ -67,6 +67,7 @@ void TestDnsName(void)
char name[Dns::Name::kMaxNameSize];
const char *subDomain;
const char *domain;
const char *domain2;
static const uint8_t kEncodedName1[] = {7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0};
static const uint8_t kEncodedName2[] = {3, 'f', 'o', 'o', 1, 'a', 2, 'b', 'b', 3, 'e', 'd', 'u', 0};
@@ -210,6 +211,42 @@ void TestDnsName(void)
domain = "Vice.arpa.";
VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
domain = "example.com.";
domain2 = "example.com.";
VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = "example.com";
VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = "ExAmPlE.cOm";
VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com";
domain2 = "ExAmPlE.cOm";
VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = "ExAmPlE.cOm.";
VerifyOrQuit(Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = "aExAmPlE.cOm.";
VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = "cOm.";
VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
domain = "example.";
domain2 = "example.com.";
VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
domain = "example.com.";
domain2 = ".example.com.";
VerifyOrQuit(!Dns::Name::IsSameDomain(domain, domain2));
printf("----------------------------------------------------------------\n");
printf("Append names, check encoded bytes, parse name and read labels:\n");
+14
View File
@@ -505,4 +505,18 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket,
}
#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aTxn);
OT_UNUSED_VARIABLE(aQuery);
}
void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn)
{
otPlatDnsUpstreamQueryDone(aInstance, aTxn, nullptr);
}
#endif
} // extern "C"
+1
View File
@@ -33,6 +33,7 @@
#include <openthread/config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/dns.h>
#include <openthread/platform/dso_transport.h>
#include <openthread/platform/entropy.h>
#include <openthread/platform/logging.h>