| /* |
| * Copyright (c) 2017, 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" |
| |
| #include <openthread/dns.h> |
| |
| #include "common/message.hpp" |
| #include "common/timer.hpp" |
| #include "net/dns_headers.hpp" |
| #include "net/ip6.hpp" |
| #include "net/netif.hpp" |
| |
| /** |
| * @file |
| * This file includes definitions for the DNS client. |
| */ |
| |
| namespace ot { |
| namespace Dns { |
| |
| /** |
| * This class implements metadata required for DNS retransmission. |
| * |
| */ |
| class QueryMetadata |
| { |
| friend class Client; |
| |
| public: |
| /** |
| * Default constructor for the object. |
| * |
| */ |
| QueryMetadata(void); |
| |
| /** |
| * This constructor initializes the object with specific values. |
| * |
| * @param[in] aHandler Pointer to a handler function for the response. |
| * @param[in] aContext Context for the handler function. |
| * |
| */ |
| QueryMetadata(otDnsResponseHandler aHandler, void *aContext); |
| |
| /** |
| * This method appends request data to the message. |
| * |
| * @param[in] aMessage A reference to the message. |
| * |
| * @retval OT_ERROR_NONE Successfully appended the bytes. |
| * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message. |
| * |
| */ |
| otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); } |
| |
| /** |
| * This method reads request data from the message. |
| * |
| * @param[in] aMessage A reference to the message. |
| * |
| */ |
| void ReadFrom(const Message &aMessage) |
| { |
| uint16_t length = aMessage.Read(aMessage.GetLength() - sizeof(*this), sizeof(*this), this); |
| OT_ASSERT(length == sizeof(*this)); |
| OT_UNUSED_VARIABLE(length); |
| } |
| |
| /** |
| * This method updates request data in the message. |
| * |
| * @param[in] aMessage A reference to the message. |
| * |
| * @returns The number of bytes updated. |
| * |
| */ |
| int UpdateIn(Message &aMessage) const |
| { |
| return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this); |
| } |
| |
| private: |
| const char * mHostname; ///< A hostname to be find. |
| otDnsResponseHandler mResponseHandler; ///< A function pointer that is called on response reception. |
| void * mResponseContext; ///< A pointer to arbitrary context information. |
| TimeMilli mTransmissionTime; ///< Time when the timer should shoot for this message. |
| Ip6::Address mSourceAddress; ///< IPv6 address of the message source. |
| Ip6::Address mDestinationAddress; ///< IPv6 address of the message destination. |
| uint16_t mDestinationPort; ///< UDP port of the message destination. |
| uint8_t mRetransmissionCount; ///< Number of retransmissions. |
| }; |
| |
| /** |
| * This class implements DNS client. |
| * |
| */ |
| class Client |
| { |
| public: |
| /** |
| * This constructor initializes the object. |
| * |
| * @param[in] aNetif A reference to the network interface that DNS client should be assigned to. |
| * |
| */ |
| explicit Client(Ip6::Netif &aNetif); |
| |
| /** |
| * This method starts the DNS client. |
| * |
| * @retval OT_ERROR_NONE Successfully started the DNS client. |
| * @retval OT_ERROR_ALREADY The socket is already open. |
| */ |
| otError Start(void); |
| |
| /** |
| * This method stops the DNS client. |
| * |
| * @retval OT_ERROR_NONE Successfully stopped the DNS client. |
| * |
| */ |
| otError Stop(void); |
| |
| /** |
| * This method sends a DNS query. |
| * |
| * @param[in] aQuery A pointer to specify DNS query parameters. |
| * @param[in] aHandler A function pointer that shall be called on response reception or time-out. |
| * @param[in] aContext A pointer to arbitrary context information. |
| * |
| * @retval OT_ERROR_NONE Successfully sent DNS query. |
| * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data. |
| * @retval OT_ERROR_INVALID_ARGS Invalid arguments supplied. |
| * |
| */ |
| otError Query(const otDnsQuery *aQuery, otDnsResponseHandler aHandler, void *aContext); |
| |
| private: |
| /** |
| * Retransmission parameters. |
| * |
| */ |
| enum |
| { |
| kResponseTimeout = OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT, |
| kMaxRetransmit = OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT, |
| }; |
| |
| /** |
| * Special DNS symbols. |
| */ |
| enum |
| { |
| kLabelTerminator = 0, |
| kLabelSeparator = '.', |
| kCompressionOffsetMask = 0xc0 |
| }; |
| |
| /** |
| * Operating on message buffers. |
| */ |
| enum |
| { |
| kBufSize = 16 |
| }; |
| |
| Message *NewMessage(const Header &aHeader); |
| Message *CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata); |
| void DequeueMessage(Message &aMessage); |
| otError SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| |
| otError AppendCompressedHostname(Message &aMessage, const char *aHostname); |
| otError CompareQuestions(Message &aMessageResponse, Message &aMessageQuery, uint16_t &aOffset); |
| otError SkipHostname(Message &aMessage, uint16_t &aOffset); |
| |
| Message *FindRelatedQuery(const Header &aResponseHeader, QueryMetadata &aQueryMetadata); |
| void FinalizeDnsTransaction(Message & aQuery, |
| const QueryMetadata &aQueryMetadata, |
| const otIp6Address * aAddress, |
| uint32_t aTtl, |
| otError aResult); |
| |
| static void HandleRetransmissionTimer(Timer &aTimer); |
| void HandleRetransmissionTimer(void); |
| |
| static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); |
| void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); |
| |
| Ip6::Udp::Socket mSocket; |
| |
| uint16_t mMessageId; |
| MessageQueue mPendingQueries; |
| TimerMilli mRetransmissionTimer; |
| }; |
| |
| } // namespace Dns |
| } // namespace ot |
| |
| #endif // DNS_CLIENT_HPP_ |