| /* |
| * Copyright (c) 2017-2021, 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 DNS_CLIENT_HPP_ |
| #define DNS_CLIENT_HPP_ |
| |
| #include "openthread-core-config.h" |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE |
| |
| #include <openthread/dns_client.h> |
| |
| #include "common/as_core_type.hpp" |
| #include "common/clearable.hpp" |
| #include "common/message.hpp" |
| #include "common/non_copyable.hpp" |
| #include "common/timer.hpp" |
| #include "net/dns_types.hpp" |
| #include "net/ip6.hpp" |
| #include "net/netif.hpp" |
| |
| /** |
| * @file |
| * This file includes definitions for the DNS client. |
| */ |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE |
| |
| #if !OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE |
| #error "DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE" |
| #endif |
| |
| #if !OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE |
| #error "DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE" |
| #endif |
| |
| #endif |
| |
| /** |
| * This struct represents an opaque (and empty) type for a response to an address resolution DNS query. |
| * |
| */ |
| struct otDnsAddressResponse |
| { |
| }; |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| /** |
| * This struct represents an opaque (and empty) type for a response to browse (service instance enumeration) DNS query. |
| * |
| */ |
| struct otDnsBrowseResponse |
| { |
| }; |
| |
| /** |
| * This struct represents an opaque (and empty) type for a response to service inst resolution DNS query. |
| * |
| */ |
| struct otDnsServiceResponse |
| { |
| }; |
| |
| #endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| namespace ot { |
| |
| namespace Srp { |
| class Client; |
| } |
| |
| namespace Dns { |
| |
| /** |
| * This class implements DNS client. |
| * |
| */ |
| class Client : public InstanceLocator, private NonCopyable |
| { |
| friend class ot::Srp::Client; |
| |
| typedef Message Query; // `Message` is used to save `Query` related info. |
| |
| public: |
| /** |
| * This type represents a DNS query configuration (e.g., server address, response wait timeout, etc). |
| * |
| */ |
| class QueryConfig : public otDnsQueryConfig, public Clearable<QueryConfig> |
| { |
| friend class Client; |
| |
| public: |
| /** |
| * This enumeration type represents the "Recursion Desired" (RD) flag in a `otDnsQueryConfig`. |
| * |
| */ |
| enum RecursionFlag : uint8_t |
| { |
| kFlagUnspecified = OT_DNS_FLAG_UNSPECIFIED, ///< The flag is not specified. |
| kFlagRecursionDesired = OT_DNS_FLAG_RECURSION_DESIRED, ///< Server can resolve the query recursively. |
| kFlagNoRecursion = OT_DNS_FLAG_NO_RECURSION, ///< Server can not resolve the query recursively. |
| }; |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| /** |
| * This enumeration type represents the NAT64 mode. |
| * |
| */ |
| enum Nat64Mode : uint8_t |
| { |
| kNat64Unspecified = OT_DNS_NAT64_UNSPECIFIED, ///< NAT64 mode is not specified. Use default NAT64 mode. |
| kNat64Allow = OT_DNS_NAT64_ALLOW, ///< Allow NAT64 address translation |
| kNat64Disallow = OT_DNS_NAT64_DISALLOW, ///< Disallow NAT64 address translation. |
| }; |
| #endif |
| |
| /** |
| * This is the default constructor for `QueryConfig` object. |
| * |
| */ |
| QueryConfig(void) = default; |
| |
| /** |
| * This method gets the server socket address (IPv6 address and port number). |
| * |
| * @returns The server socket address. |
| * |
| */ |
| const Ip6::SockAddr &GetServerSockAddr(void) const |
| { |
| return static_cast<const Ip6::SockAddr &>(mServerSockAddr); |
| } |
| |
| /** |
| * This method gets the wait time to receive response from server (in msec). |
| * |
| * @returns The timeout interval in msec. |
| * |
| */ |
| uint32_t GetResponseTimeout(void) const { return mResponseTimeout; } |
| |
| /** |
| * This method gets the maximum number of query transmit attempts before reporting failure. |
| * |
| * @returns The maximum number of query transmit attempts. |
| * |
| */ |
| uint8_t GetMaxTxAttempts(void) const { return mMaxTxAttempts; } |
| |
| /** |
| * This method gets the recursion flag indicating whether the server can resolve the query recursively or not. |
| * |
| * @returns The recursion flag. |
| * |
| */ |
| RecursionFlag GetRecursionFlag(void) const { return static_cast<RecursionFlag>(mRecursionFlag); } |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| /** |
| * This method gets the NAT64 mode. |
| * |
| * @returns The NAT64 mode. |
| * |
| */ |
| Nat64Mode GetNat64Mode(void) const { return static_cast<Nat64Mode>(mNat64Mode); } |
| #endif |
| |
| private: |
| static constexpr uint32_t kDefaultResponseTimeout = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT; |
| static constexpr uint16_t kDefaultServerPort = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_PORT; |
| static constexpr uint8_t kDefaultMaxTxAttempts = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS; |
| static constexpr bool kDefaultRecursionDesired = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RECURSION_DESIRED_FLAG; |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| static constexpr bool kDefaultNat64Allowed = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_NAT64_ALLOWED; |
| #endif |
| |
| enum InitMode : uint8_t |
| { |
| kInitFromDefaults, |
| }; |
| |
| static const char kDefaultServerAddressString[]; |
| |
| explicit QueryConfig(InitMode aMode); |
| |
| Ip6::SockAddr &GetServerSockAddr(void) { return AsCoreType(&mServerSockAddr); } |
| |
| void SetResponseTimeout(uint32_t aResponseTimeout) { mResponseTimeout = aResponseTimeout; } |
| void SetMaxTxAttempts(uint8_t aMaxTxAttempts) { mMaxTxAttempts = aMaxTxAttempts; } |
| void SetRecursionFlag(RecursionFlag aFlag) { mRecursionFlag = static_cast<otDnsRecursionFlag>(aFlag); } |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| void SetNat64Mode(Nat64Mode aMode) { mNat64Mode = static_cast<otDnsNat64Mode>(aMode); } |
| #endif |
| |
| void SetFrom(const QueryConfig &aConfig, const QueryConfig &aDefaultConfig); |
| }; |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| /** |
| * This structure provides info for a DNS service instance. |
| * |
| */ |
| typedef otDnsServiceInfo ServiceInfo; |
| #endif |
| |
| /** |
| * This class represents a DNS query response. |
| * |
| */ |
| class Response : public otDnsAddressResponse, |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| public otDnsBrowseResponse, |
| public otDnsServiceResponse, |
| #endif |
| public Clearable<Response> |
| { |
| friend class Client; |
| |
| protected: |
| enum Section : uint8_t |
| { |
| kAnswerSection, |
| kAdditionalDataSection, |
| }; |
| |
| Response(void) { Clear(); } |
| |
| Error GetName(char *aNameBuffer, uint16_t aNameBufferSize) const; |
| void SelectSection(Section aSection, uint16_t &aOffset, uint16_t &aNumRecord) const; |
| Error CheckForHostNameAlias(Section aSection, Name &aHostName) const; |
| Error FindHostAddress(Section aSection, |
| const Name & aHostName, |
| uint16_t aIndex, |
| Ip6::Address &aAddress, |
| uint32_t & aTtl) const; |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| Error FindARecord(Section aSection, const Name &aHostName, uint16_t aIndex, ARecord &aARecord) const; |
| #endif |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| Error FindServiceInfo(Section aSection, const Name &aName, ServiceInfo &aServiceInfo) const; |
| #endif |
| |
| Instance * mInstance; // The OpenThread instance. |
| Query * mQuery; // The associated query. |
| const Message *mMessage; // The response message. |
| uint16_t mAnswerOffset; // Answer section offset in `mMessage`. |
| uint16_t mAnswerRecordCount; // Number of records in answer section. |
| uint16_t mAdditionalOffset; // Additional data section offset in `mMessage`. |
| uint16_t mAdditionalRecordCount; // Number of records in additional data section. |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| // This flag is only used in an IPv6 address query response. |
| // It indicates that the response does not contain any IPv6 |
| // addresses but server provided at least one IPv4 address |
| // in the additional data section for NAT64 address synthesis. |
| bool mIp6QueryResponseRequiresNat64; |
| #endif |
| }; |
| |
| /** |
| * This type represents the function pointer callback which is called when a DNS response for an address resolution |
| * query is received. |
| * |
| */ |
| typedef otDnsAddressCallback AddressCallback; |
| |
| /** |
| * This type represents an address resolution query DNS response. |
| * |
| */ |
| class AddressResponse : public Response |
| { |
| friend class Client; |
| |
| public: |
| /** |
| * This method gets the host name associated with an address resolution DNS response. |
| * |
| * This method MUST only be used from `AddressCallback`. |
| * |
| * @param[out] aNameBuffer A buffer to char array to output the host name. |
| * @param[in] aNameBufferSize The size of @p aNameBuffer. |
| * |
| * @retval kErrorNone The host name was read successfully. |
| * @retval kErrorNoBufs The name does not fit in @p aNameBuffer. |
| * |
| */ |
| Error GetHostName(char *aNameBuffer, uint16_t aNameBufferSize) const |
| { |
| return GetName(aNameBuffer, aNameBufferSize); |
| } |
| |
| /** |
| * This method gets the IPv6 address associated with an address resolution DNS response. |
| * |
| * This method MUST only be used from `AddressCallback`. |
| * |
| * The response may include multiple IPv6 address records. @p aIndex can be used to iterate through the list of |
| * addresses. Index zero gets the the first address and so on. When we reach end of the list, this method |
| * returns `kErrorNotFound`. |
| * |
| * @param[in] aIndex The address record index to retrieve. |
| * @param[out] aAddress A reference to an IPv6 address to output the address. |
| * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address. |
| * |
| * @retval kErrorNone The address was read successfully. |
| * @retval kErrorNotFound No address record at @p aIndex. |
| * @retval kErrorParse Could not parse the records. |
| * @retval kErrorInvalidState No NAT64 prefix (applicable only when NAT64 is allowed). |
| * |
| */ |
| Error GetAddress(uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const; |
| |
| private: |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| Error GetNat64Prefix(Ip6::Prefix &aPrefix) const; |
| #endif |
| }; |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| /** |
| * This type represents the function pointer callback which is called when a response for a browse (service |
| * instance enumeration) DNS query is received. |
| * |
| */ |
| typedef otDnsBrowseCallback BrowseCallback; |
| |
| /** |
| * This type represents a browse (service instance enumeration) DNS response. |
| * |
| */ |
| class BrowseResponse : public Response |
| { |
| friend class Client; |
| |
| public: |
| /** |
| * This method gets the service name associated with a DNS browse response. |
| * |
| * This method MUST only be used from `BrowseCallback`. |
| * |
| * @param[out] aNameBuffer A buffer to char array to output the host name. |
| * @param[in] aNameBufferSize The size of @p aNameBuffer. |
| * |
| * @retval kErrorNone The host name was read successfully. |
| * @retval kErrorNoBufs The name does not fit in @p aNameBuffer. |
| * |
| */ |
| Error GetServiceName(char *aNameBuffer, uint16_t aNameBufferSize) const |
| { |
| return GetName(aNameBuffer, aNameBufferSize); |
| } |
| |
| /** |
| * This method gets a service instance associated with a DNS browse (service instance enumeration) response. |
| * |
| * This method MUST only be used from `BrowseCallback`. |
| * |
| * A response may include multiple service instance records. @p aIndex can be used to iterate through the list. |
| * Index zero gives the the first record. When we reach end of the list, `kErrorNotFound` is returned. |
| * |
| * Note that this method gets the service instance label and not the full service instance name which is of the |
| * form `<Instance>.<Service>.<Domain>`. |
| * |
| * @param[in] aIndex The service instance record index to retrieve. |
| * @param[out] aLabelBuffer A char array to output the service instance label (MUST NOT be NULL). |
| * @param[in] aLabelBufferSize The size of @p aLabelBuffer. |
| * |
| * @retval kErrorNone The service instance was read successfully. |
| * @retval kErrorNoBufs The name does not fit in @p aNameBuffer. |
| * @retval kErrorNotFound No service instance record at @p aIndex. |
| * @retval kErrorParse Could not parse the records. |
| * |
| */ |
| Error GetServiceInstance(uint16_t aIndex, char *aLabelBuffer, uint8_t aLabelBufferSize) const; |
| |
| /** |
| * This method gets info for a service instance from a DNS browse (service instance enumeration) response. |
| * |
| * This method MUST only be used from `BrowseCallback`. |
| * |
| * A browse DNS response should include the SRV, TXT, and AAAA records for the service instances that are |
| * enumerated (note that it is a SHOULD and not a MUST requirement). This method tries to retrieve this info |
| * for a given service instance. |
| * |
| * - If no matching SRV record is found, `kErrorNotFound` is returned. |
| * - If a matching SRV record is found, @p aServiceInfo is updated returning `kErrorNone`. |
| * - If no matching TXT record is found, `mTxtDataSize` in @p aServiceInfo is set to zero. |
| * - If no matching AAAA record is found, `mHostAddress is set to all zero or unspecified address. |
| * - If there are multiple AAAA records for the host name `mHostAddress` is set to the first one. The other |
| * addresses can be retrieved using `GetHostAddress()` method. |
| * |
| * @param[in] aInstanceLabel The service instance label (MUST NOT be `nullptr`). |
| * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information. |
| * |
| * @retval kErrorNone The service instance info was read. @p aServiceInfo is updated. |
| * @retval kErrorNotFound Could not find a matching SRV record for @p aInstanceLabel. |
| * @retval kErrorNoBufs The host name and/or the TXT data could not fit in given buffers. |
| * @retval kErrorParse Could not parse the records. |
| * |
| */ |
| Error GetServiceInfo(const char *aInstanceLabel, ServiceInfo &aServiceInfo) const; |
| |
| /** |
| * This method gets the host IPv6 address from a DNS browse (service instance enumeration) response. |
| * |
| * This method MUST only be used from `BrowseCallback`. |
| * |
| * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the |
| * list of addresses. Index zero gets the first address and so on. When we reach end of the list, this method |
| * returns `kErrorNotFound`. |
| * |
| * @param[in] aHostName The host name to get the address (MUST NOT be `nullptr`). |
| * @param[in] aIndex The address record index to retrieve. |
| * @param[out] aAddress A reference to an IPv6 address to output the address. |
| * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address. |
| * |
| * @retval kErrorNone The address was read successfully. |
| * @retval kErrorNotFound No address record for @p aHostname at @p aIndex. |
| * @retval kErrorParse Could not parse the records. |
| * |
| */ |
| Error GetHostAddress(const char *aHostName, uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const; |
| |
| private: |
| Error FindPtrRecord(const char *aInstanceLabel, Name &aInstanceName) const; |
| }; |
| |
| /** |
| * This type represents the function pointer callback which is called when a response for a service instance |
| * resolution DNS query is received. |
| * |
| */ |
| typedef otDnsServiceCallback ServiceCallback; |
| |
| /** |
| * This type represents a service instance resolution DNS response. |
| * |
| */ |
| class ServiceResponse : public Response |
| { |
| friend class Client; |
| |
| public: |
| /** |
| * This method gets the service instance name associated with a DNS service instance resolution response. |
| * |
| * This method MUST only be used from `ServiceCallback`. |
| * |
| * @param[out] aLabelBuffer A buffer to char array to output the service instance label (MUST NOT be NULL). |
| * @param[in] aLabelBufferSize The size of @p aLabelBuffer. |
| * @param[out] aNameBuffer A buffer to char array to output the rest of service name (can be NULL if user |
| * is not interested in getting the name). |
| * @param[in] aNameBufferSize The size of @p aNameBuffer. |
| * |
| * @retval kErrorNone The service instance name was read successfully. |
| * @retval kErrorNoBufs Either the label or name does not fit in the given buffers. |
| * |
| */ |
| Error GetServiceName(char * aLabelBuffer, |
| uint8_t aLabelBufferSize, |
| char * aNameBuffer, |
| uint16_t aNameBufferSize) const; |
| |
| /** |
| * This method gets info for a service instance from a DNS service instance resolution response. |
| * |
| * This method MUST only be used from `ServiceCallback`. |
| * |
| * - If no matching SRV record is found, `kErrorNotFound` is returned. |
| * - If a matching SRV record is found, @p aServiceInfo is updated and `kErrorNone` is returned. |
| * - If no matching TXT record is found, `mTxtDataSize` in @p aServiceInfo is set to zero. |
| * - If no matching AAAA record is found, `mHostAddress is set to all zero or unspecified address. |
| * - If there are multiple AAAA records for the host name, `mHostAddress` is set to the first one. The other |
| * addresses can be retrieved using `GetHostAddress()` method. |
| * |
| * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information |
| * |
| * @retval kErrorNone The service instance info was read. @p aServiceInfo is updated. |
| * @retval kErrorNotFound Could not find a matching SRV record. |
| * @retval kErrorNoBufs The host name and/or TXT data could not fit in the given buffers. |
| * @retval kErrorParse Could not parse the records in the @p aResponse. |
| * |
| */ |
| Error GetServiceInfo(ServiceInfo &aServiceInfo) const; |
| |
| /** |
| * This method gets the host IPv6 address from a DNS service instance resolution response. |
| * |
| * This method MUST only be used from `ServiceCallback`. |
| * |
| * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the |
| * list of addresses. Index zero gets the first address and so on. When we reach end of the list, this method |
| * returns `kErrorNotFound`. |
| * |
| * @param[in] aHostName The host name to get the address (MUST NOT be `nullptr`). |
| * @param[in] aIndex The address record index to retrieve. |
| * @param[out] aAddress A reference to an IPv6 address to output the address. |
| * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address. |
| * |
| * @retval kErrorNone The address was read successfully. |
| * @retval kErrorNotFound No address record for @p aHostname at @p aIndex. |
| * @retval kErrorParse Could not parse the records. |
| * |
| */ |
| Error GetHostAddress(const char *aHostName, uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const; |
| }; |
| |
| #endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| /** |
| * This constructor initializes the object. |
| * |
| * @param[in] aInstance A reference to the OpenThread instance. |
| * |
| */ |
| explicit Client(Instance &aInstance); |
| |
| /** |
| * This method starts the DNS client. |
| * |
| * @retval kErrorNone Successfully started the DNS client. |
| * @retval kErrorAlready The socket is already open. |
| * |
| */ |
| Error Start(void); |
| |
| /** |
| * This method stops the DNS client. |
| * |
| */ |
| void Stop(void); |
| |
| /** |
| * This method gets the current default query config being used by DNS client. |
| * |
| * @returns The current default query config. |
| * |
| */ |
| const QueryConfig &GetDefaultConfig(void) const { return mDefaultConfig; } |
| |
| /** |
| * This method sets the default query config. |
| * |
| * @param[in] aQueryConfig The new default query config. |
| * |
| */ |
| void SetDefaultConfig(const QueryConfig &aQueryConfig); |
| |
| /** |
| * This method resets the default config to the config used when the OpenThread stack starts. |
| * |
| * When OpenThread stack starts, the default DNS query config is determined from a set of OT config options such as |
| * `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS`, `_DEFAULT_SERVER_PORT`, or `_DEFAULT_RESPONSE_TIMEOUT` |
| * etc. (see `config/dns_client.h` for all related config options). |
| * |
| */ |
| void ResetDefaultConfig(void); |
| |
| /** |
| * This method sends an address resolution DNS query for AAAA (IPv6) record for a given host name. |
| * |
| * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as |
| * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero). |
| * The unspecified fields are then replaced by the values from the default config. |
| * |
| * @param[in] aHostName The host name for which to query the address (MUST NOT be `nullptr`). |
| * @param[in] aCallback A callback function pointer to report the result of query. |
| * @param[in] aContext A pointer to arbitrary context information passed to @p aCallback. |
| * @param[in] aConfig The config to use for this query. |
| * |
| * @retval kErrorNone Successfully sent DNS query. |
| * @retval kErrorNoBufs Failed to allocate retransmission data. |
| * @retval kErrorInvalidArgs The host name is not valid format. |
| * @retval kErrorInvalidState Cannot send query since Thread interface is not up. |
| * |
| */ |
| Error ResolveAddress(const char * aHostName, |
| AddressCallback aCallback, |
| void * aContext, |
| const QueryConfig *aConfig = nullptr); |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| /** |
| * This method sends an address resolution DNS query for A (IPv4) record for a given host name. |
| * |
| * When a successful response is received, the addresses are returned from @p aCallback as NAT64 IPv6 translated |
| * versions of the IPv4 addresses from the query response. |
| * |
| * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as |
| * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero). |
| * The unspecified fields are then replaced by the values from the default config. |
| * |
| * @param[in] aHostName The host name for which to query the address (MUST NOT be `nullptr`). |
| * @param[in] aCallback A callback function pointer to report the result of query. |
| * @param[in] aContext A pointer to arbitrary context information passed to @p aCallback. |
| * @param[in] aConfig The config to use for this query. |
| * |
| * @retval kErrorNone Successfully sent DNS query. |
| * @retval kErrorNoBufs Failed to allocate retransmission data. |
| * @retval kErrorInvalidArgs The host name is not valid format or NAT64 is not enabled in config. |
| * @retval kErrorInvalidState Cannot send query since Thread interface is not up, or there is no NAT64 prefix. |
| * |
| */ |
| Error ResolveIp4Address(const char * aHostName, |
| AddressCallback aCallback, |
| void * aContext, |
| const QueryConfig *aConfig = nullptr); |
| #endif |
| |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| /** |
| * This method sends a browse (service instance enumeration) DNS query for a given service name. |
| * |
| * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as |
| * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero). |
| * The unspecified fields are then replaced by the values from the default config. |
| * |
| * @param[in] aServiceName The service name to query for (MUST NOT be `nullptr`). |
| * @param[in] aCallback The callback to report the response or errors (such as time-out). |
| * @param[in] aContext A pointer to arbitrary context information. |
| * @param[in] aConfig The config to use for this query. |
| * |
| * @retval kErrorNone Query sent successfully. @p aCallback will be invoked to report the status. |
| * @retval kErrorNoBufs Insufficient buffer to prepare and send query. |
| * |
| */ |
| Error Browse(const char * aServiceName, |
| BrowseCallback aCallback, |
| void * aContext, |
| const QueryConfig *aConfig = nullptr); |
| |
| /** |
| * This method sends a DNS service instance resolution query for a given service instance. |
| * |
| * The @p aConfig can be `nullptr`. In this case the default config (from `GetDefaultConfig()`) will be used as |
| * the config for this query. In a non-`nullptr` @p aConfig, some of the fields can be left unspecified (value |
| * zero). The unspecified fields are then replaced by the values from the default config. |
| * |
| * @param[in] aInstanceLabel The service instance label. |
| * @param[in] aServiceName The service name (together with @p aInstanceLabel form full instance name). |
| * @param[in] aCallback A function pointer that shall be called on response reception or time-out. |
| * @param[in] aContext A pointer to arbitrary context information. |
| * @param[in] aConfig The config to use for this query. |
| * |
| * @retval kErrorNone Query sent successfully. @p aCallback will be invoked to report the status. |
| * @retval kErrorNoBufs Insufficient buffer to prepare and send query. |
| * @retval kErrorInvalidArgs @p aInstanceLabel is `nullptr`. |
| * |
| */ |
| Error ResolveService(const char * aInstanceLabel, |
| const char * aServiceName, |
| otDnsServiceCallback aCallback, |
| void * aContext, |
| const QueryConfig * aConfig = nullptr); |
| |
| #endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| |
| private: |
| enum QueryType : uint8_t |
| { |
| kIp6AddressQuery, // IPv6 Address resolution. |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| kIp4AddressQuery, // IPv4 Address resolution |
| #endif |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| kBrowseQuery, // Browse (service instance enumeration). |
| kServiceQuery, // Service instance resolution. |
| #endif |
| }; |
| |
| union Callback |
| { |
| AddressCallback mAddressCallback; |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| BrowseCallback mBrowseCallback; |
| ServiceCallback mServiceCallback; |
| #endif |
| }; |
| |
| typedef MessageQueue QueryList; // List of queries. |
| |
| struct QueryInfo : public Clearable<QueryInfo> // Query related Info |
| { |
| void ReadFrom(const Query &aQuery) { IgnoreError(aQuery.Read(0, *this)); } |
| |
| QueryType mQueryType; |
| uint16_t mMessageId; |
| Callback mCallback; |
| void * mCallbackContext; |
| TimeMilli mRetransmissionTime; |
| QueryConfig mConfig; |
| uint8_t mTransmissionCount; |
| // Followed by the name (service, host, instance) encoded as a `Dns::Name`. |
| }; |
| |
| static constexpr uint16_t kNameOffsetInQuery = sizeof(QueryInfo); |
| |
| Error StartQuery(QueryInfo & aInfo, |
| const QueryConfig *aConfig, |
| const char * aLabel, |
| const char * aName, |
| void * aContext); |
| Error AllocateQuery(const QueryInfo &aInfo, const char *aLabel, const char *aName, Query *&aQuery); |
| void FreeQuery(Query &aQuery); |
| void UpdateQuery(Query &aQuery, const QueryInfo &aInfo) { aQuery.Write(0, aInfo); } |
| void SendQuery(Query &aQuery, QueryInfo &aInfo, bool aUpdateTimer); |
| void FinalizeQuery(Query &aQuery, Error aError); |
| void FinalizeQuery(Response &Response, QueryType aType, Error aError); |
| static void GetCallback(const Query &aQuery, Callback &aCallback, void *&aContext); |
| Error AppendNameFromQuery(const Query &aQuery, Message &aMessage); |
| Query * FindQueryById(uint16_t aMessageId); |
| static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo); |
| void ProcessResponse(const Message &aMessage); |
| Error ParseResponse(Response &aResponse, QueryType &aType, Error &aResponseError); |
| static void HandleTimer(Timer &aTimer); |
| void HandleTimer(void); |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| Error CheckAddressResponse(Response &aResponse, Error aResponseError) const; |
| #endif |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE |
| void UpdateDefaultConfigAddress(void); |
| #endif |
| |
| static const uint8_t kQuestionCount[]; |
| static const uint16_t *kQuestionRecordTypes[]; |
| |
| static const uint16_t kIp6AddressQueryRecordTypes[]; |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE |
| static const uint16_t kIp4AddressQueryRecordTypes[]; |
| #endif |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| static const uint16_t kBrowseQueryRecordTypes[]; |
| static const uint16_t kServiceQueryRecordTypes[]; |
| #endif |
| |
| Ip6::Udp::Socket mSocket; |
| QueryList mQueries; |
| TimerMilli mTimer; |
| QueryConfig mDefaultConfig; |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE |
| bool mUserDidSetDefaultAddress; |
| #endif |
| }; |
| |
| } // namespace Dns |
| |
| DefineCoreType(otDnsQueryConfig, Dns::Client::QueryConfig); |
| DefineCoreType(otDnsAddressResponse, Dns::Client::AddressResponse); |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE |
| DefineCoreType(otDnsBrowseResponse, Dns::Client::BrowseResponse); |
| DefineCoreType(otDnsServiceResponse, Dns::Client::ServiceResponse); |
| DefineCoreType(otDnsServiceInfo, Dns::Client::ServiceInfo); |
| #endif |
| |
| } // namespace ot |
| |
| #endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE |
| |
| #endif // DNS_CLIENT_HPP_ |