blob: 1ad0bd61880f78b04731099adfcf91f2bc725b71 [file] [log] [blame]
/*
* 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.
*/
/**
* @file
* This file includes definitions for generating and processing DNS headers.
*/
#ifndef DNS_HEADER_HPP_
#define DNS_HEADER_HPP_
#include "utils/wrap_string.h"
#include <openthread/types.h>
#include "common/encoding.hpp"
#include "common/message.hpp"
using ot::Encoding::BigEndian::HostSwap16;
using ot::Encoding::BigEndian::HostSwap32;
namespace ot {
/**
* @namespace ot::Dns
* @brief
* This namespace includes definitions for DNS.
*
*/
namespace Dns {
/**
* @addtogroup core-dns
*
* @brief
* This module includes definitions for DNS.
*
* @{
*
*/
/**
* This class implements DNS header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class Header
{
public:
/**
* Default constructor for DNS Header.
*
*/
Header(void) { memset(this, 0, sizeof(*this)); }
/**
* This method returns the Message ID.
*
* @returns The Message ID value.
*
*/
uint16_t GetMessageId(void) const { return HostSwap16(mMessageId); }
/**
* This method sets the Message ID.
*
* @param[in] aMessageId The Message ID value.
*
*/
void SetMessageId(uint16_t aMessageId) { mMessageId = HostSwap16(aMessageId); }
/**
* Defines types of DNS message.
*
*/
enum Type
{
kTypeQuery = 0,
kTypeResponse = 1,
};
/**
* This method returns the type of the message.
*
* @returns The type of the message.
*/
Type GetType(void) const { return static_cast<Type>((mFlags[0] & kQrFlagMask) >> kQrFlagOffset); }
/**
* This method sets the type of the message.
*
* @param[in] aType The type of the message.
*
*/
void SetType(Type aType) {
mFlags[0] &= ~kQrFlagMask;
mFlags[0] |= static_cast<uint8_t>(aType) << kQrFlagOffset;
}
/**
* Defines types of query.
*
*/
enum QueryType
{
kQueryTypeStandard = 0,
kQueryTypeInverse = 1,
kQueryTypeStatus = 2,
kQueryTypeNotify = 4,
kQueryTypeUpdate = 5
};
/**
* This method returns the type of the query.
*
* @returns The type of the query.
*/
QueryType GetQueryType(void) const { return static_cast<QueryType>((mFlags[0] & kOpCodeMask) >> kOpCodeOffset); }
/**
* This method sets the type of the query.
*
* @param[in] aType The type of the query.
*
*/
void SetQueryType(QueryType aType) {
mFlags[0] &= ~kOpCodeMask;
mFlags[0] |= static_cast<uint8_t>(aType) << kOpCodeOffset;
}
/**
* This method specifies in response message if the responding name server is an
* authority for the domain name in question section.
*
* @returns True if Authoritative Answer flag (AA) is set in the header, false otherwise.
*/
bool IsAuthoritativeAnswerFlagSet(void) const { return (mFlags[0] & kAaFlagMask) == kAaFlagMask; }
/**
* This method clears the Authoritative Answer flag (AA) in the header.
*
*/
void ClearAuthoritativeAnswerFlag(void) { mFlags[0] &= ~kAaFlagMask; }
/**
* This method sets the Authoritative Answer flag (AA) in the header.
*
*/
void SetAuthoritativeAnswerFlag(void) { mFlags[0] |= kAaFlagMask; }
/**
* This method specifies if message is truncated.
*
* @returns True if Truncation flag (TC) is set in the header, false otherwise.
*/
bool IsTruncationFlagSet(void) const { return (mFlags[0] & kTcFlagMask) == kTcFlagMask; }
/**
* This method clears the Truncation flag (TC) in the header.
*
*/
void ClearTruncationFlag(void) { mFlags[0] &= ~kTcFlagMask; }
/**
* This method sets the Truncation flag (TC) in the header.
*
*/
void SetTruncationFlag(void) { mFlags[0] |= kTcFlagMask; }
/**
* This method specifies if resolver wants to direct the name server to pursue
* the query recursively.
*
* @returns True if Recursion Desired flag (RD) is set in the header, false otherwise.
*/
bool IsRecursionDesiredFlagSet(void) const { return (mFlags[0] & kRdFlagMask) == kRdFlagMask; }
/**
* This method clears the Recursion Desired flag (RD) in the header.
*
*/
void ClearRecursionDesiredFlag(void) { mFlags[0] &= ~kRdFlagMask; }
/**
* This method sets the Recursion Desired flag (RD) in the header.
*
*/
void SetRecursionDesiredFlag(void) { mFlags[0] |= kRdFlagMask; }
/**
* This method denotes whether recursive query support is available in the name server.
*
* @returns True if Recursion Available flag (RA) is set in the header, false otherwise.
*/
bool IsRecursionAvailableFlagSet(void) const { return (mFlags[1] & kRaFlagMask) == kRaFlagMask; }
/**
* This method clears the Recursion Available flag (RA) in the header.
*
*/
void ClearRecursionAvailableFlag(void) { mFlags[1] &= ~kRaFlagMask; }
/**
* This method sets the Recursion Available flag (RA) in the header.
*
*/
void SetRecursionAvailableFlag(void) { mFlags[1] |= kRaFlagMask; }
/**
* Defines response codes.
*
*/
enum Response
{
kResponseSuccess = 0,
kResponseFormatError = 1,
kResponseServerFailure = 2,
kResponseNameError = 3,
kResponseNotImplemented = 4,
kResponseRefused = 5,
kResponseNotAuth = 9,
kResponseNotZone = 10,
kResponseBadName = 20,
kResponseBadAlg = 21,
kResponseBadTruncation = 22,
};
/**
* This method returns the response code.
*
* @returns The response code from the header.
*/
Response GetResponseCode(void) const { return static_cast<Response>((mFlags[1] & kRCodeMask) >> kRCodeOffset); }
/**
* This method sets the response code.
*
* @param[in] aResponse The type of the response.
*
*/
void SetResponseCode(Response aResponse) {
mFlags[1] &= ~kRCodeMask;
mFlags[1] |= static_cast<uint8_t>(aResponse) << kRCodeOffset;
}
/**
* This method returns the number of entries in question section.
*
* @returns The number of entries in question section.
*
*/
uint16_t GetQuestionCount(void) const { return HostSwap16(mQdCount); }
/**
* This method sets the number of entries in question section.
*
* @param[in] aCount The number of entries in question section.
*
*/
void SetQuestionCount(uint16_t aCount) { mQdCount = HostSwap16(aCount); }
/**
* This method returns the number of entries in answer section.
*
* @returns The number of entries in answer section.
*
*/
uint16_t GetAnswerCount(void) const { return HostSwap16(mAnCount); }
/**
* This method sets the number of entries in answer section.
*
* @param[in] aCount The number of entries in answer section.
*
*/
void SetAnswerCount(uint16_t aCount) { mAnCount = HostSwap16(aCount); }
/**
* This method returns the number of entries in authority records section.
*
* @returns The number of entries in authority records section.
*
*/
uint16_t GetAuthorityRecordsCount(void) const { return HostSwap16(mNsCount); }
/**
* This method sets the number of entries in authority records section.
*
* @param[in] aCount The number of entries in authority records section.
*
*/
void SetAuthorityRecordsCount(uint16_t aCount) { mNsCount = HostSwap16(aCount); }
/**
* This method returns the number of entries in additional records section.
*
* @returns The number of entries in additional records section.
*
*/
uint16_t GetAdditionalRecordsCount(void) const { return HostSwap16(mArCount); }
/**
* This method sets the number of entries in additional records section.
*
* @param[in] aCount The number of entries in additional records section.
*
*/
void SetAdditionalRecordsCount(uint16_t aCount) { mArCount = HostSwap16(aCount); }
private:
/**
* Protocol Constants (RFC 1035).
*
*/
enum
{
kQrFlagOffset = 7, ///< QR Flag offset.
kQrFlagMask = 0x01 << kQrFlagOffset, ///< QR Flag mask.
kOpCodeOffset = 3, ///< OpCode field offset.
kOpCodeMask = 0x0f << kOpCodeOffset, ///< OpCode field mask.
kAaFlagOffset = 2, ///< AA Flag offset.
kAaFlagMask = 0x01 << kAaFlagOffset, ///< AA Flag mask.
kTcFlagOffset = 1, ///< TC Flag offset.
kTcFlagMask = 0x01 << kTcFlagOffset, ///< TC Flag mask.
kRdFlagOffset = 0, ///< RD Flag offset.
kRdFlagMask = 0x01 << kRdFlagOffset, ///< RD Flag mask.
kRaFlagOffset = 7, ///< RA Flag offset.
kRaFlagMask = 0x01 << kRaFlagOffset, ///< RA Flag mask.
kRCodeOffset = 0, ///< RCODE field offset.
kRCodeMask = 0x0f << kRCodeOffset, ///< RCODE field mask.
};
uint16_t mMessageId; ///< A message identifier that is used by the requester to match up replies to outstanding queries.
uint8_t mFlags[2]; ///< DNS header flags.
uint16_t mQdCount; ///< A number specifying the number of entries in the question section.
uint16_t mAnCount; ///< A number specifying the number of entries in the answer section.
uint16_t mNsCount; ///< A number specifying the number of entries in the authority records section.
uint16_t mArCount; ///< A number specifying the number of entries in the additional records section.
} OT_TOOL_PACKED_END;
/**
* This class implements Resource Record body format (RR).
*
*/
OT_TOOL_PACKED_BEGIN
class ResourceRecord
{
public:
/**
* This method returns the type of the resource record.
*
* @returns The type of the resource record.
*/
uint16_t GetType(void) const { return HostSwap16(mType); }
/**
* This method sets the type of the resource record.
*
* @param[in] aType The type of the resource record.
*
*/
void SetType(uint16_t aType) { mType = HostSwap16(aType); }
/**
* This method returns the class of the resource record.
*
* @returns The class of the resource record.
*/
uint16_t GetClass(void) const { return HostSwap16(mClass); }
/**
* This method sets the class of the resource record.
*
* @param[in] aClass The class of the resource record.
*
*/
void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
/**
* This method returns the time to live field of the resource record.
*
* @returns The time to live field of the resource record.
*/
uint32_t GetTtl(void) const { return HostSwap32(mTtl); }
/**
* This method sets the time to live field of the resource record.
*
* @param[in] aTtl The time to live field of the resource record.
*
*/
void SetTtl(uint32_t aTtl) { mTtl = HostSwap32(aTtl); }
/**
* This method returns the length of the resource record.
*
* @returns The length of the resource record.
*/
uint16_t GetLength(void) const { return HostSwap16(mLength); }
/**
* This method sets the length of the resource record.
*
* @param[in] aLength The length of the resource record.
*
*/
void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
private:
uint16_t mType; ///< The type of the data in RDATA section.
uint16_t mClass; ///< The class of the data in RDATA section.
uint32_t mTtl; ///< Specifies the maximum time that the resource record may be cached.
uint16_t mLength; ///< The length of RDATA section in bytes.
} OT_TOOL_PACKED_END;
/**
* This class implements Resource Record body format of AAAA type.
*
*/
OT_TOOL_PACKED_BEGIN
class ResourceRecordAaaa: public ResourceRecord
{
public:
enum
{
kType = 0x1C, ///< AAAA Resource Record type.
kClass = 0x01, ///< The value of the Internet class.
kLength = 16, ///< Size of the AAAA Resource Record type.
};
/**
* This method initializes the AAAA Resource Record.
*
*/
void Init(void) {
ResourceRecord::SetType(kType);
ResourceRecord::SetClass(kClass);
ResourceRecord::SetTtl(0);
ResourceRecord::SetLength(kLength);
memset(&mAddress, 0, sizeof(mAddress));
}
/**
* This method sets the IPv6 address of the resource record.
*
* @param[in] aAddress The IPv6 address of the resource record.
*
*/
void SetAddress(otIp6Address &aAddress) { mAddress = aAddress; }
/**
* This method returns the reference to IPv6 address of the resource record.
*
* @returns The reference to IPv6 address of the resource record.
*/
otIp6Address &GetAddress(void) { return mAddress; }
private:
otIp6Address mAddress; ///< Ipv6 Address of AAAA Resource Record.
} OT_TOOL_PACKED_END;
/**
* This class implements Question format.
*
*/
OT_TOOL_PACKED_BEGIN
class Question
{
public:
/**
* Constructor for Question.
*
*/
Question(uint16_t aType, uint16_t aClass) {
SetType(aType);
SetClass(aClass);
};
/**
* This method returns the type of the question.
*
* @returns The type of the question.
*/
uint16_t GetType(void) const { return HostSwap16(mType); }
/**
* This method sets the type of the question.
*
* @param[in] aType The type of the question.
*
*/
void SetType(uint16_t aType) { mType = HostSwap16(aType); }
/**
* This method returns the class of the question.
*
* @returns The class of the question.
*/
uint16_t GetClass(void) const { return HostSwap16(mClass); }
/**
* This method sets the class of the question.
*
* @param[in] aClass The class of the question.
*
*/
void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
private:
uint16_t mType; ///< The type of the data in question section.
uint16_t mClass; ///< The class of the data in question section.
} OT_TOOL_PACKED_END;
/**
* This class implements Question format of AAAA type.
*
*/
class QuestionAaaa: public Question
{
public:
enum
{
kType = 0x1C, ///< AAAA Resource Record type.
kClass = 0x01, ///< The value of the Internet class.
};
/**
* Default constructor for AAAA Question.
*
*/
QuestionAaaa(void) : Question(kType, kClass) {};
/**
* 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));
};
};
/**
* @}
*
*/
} // namespace Dns
} // namespace ot
#endif // DNS_HEADER_HPP_