libraries/pcappp/include/pcapplusplus/DnsResource.h

238 lines
8.3 KiB
C++

#ifndef PACKETPP_DNS_RESOURCE
#define PACKETPP_DNS_RESOURCE
#include "DnsLayer.h"
#include "DnsLayerEnums.h"
#include "DnsResourceData.h"
#include <stdio.h>
#include <string>
#include <stdint.h>
/// @file
/**
* \namespace pcpp
* \brief The main namespace for the PcapPlusPlus lib
*/
namespace pcpp
{
// forward declarations
class DnsLayer;
class IDnsResourceData;
class DnsResourceDataPtr;
/**
* @class IDnsResource
* An abstract class for representing all types of DNS records. This class gives access to all available record data such as DNS type, class,
* name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this class for each DNS record in the DNS packet
*/
class IDnsResource
{
protected:
friend class DnsLayer;
friend class IDnsResourceData;
protected:
DnsLayer* m_DnsLayer;
size_t m_OffsetInLayer;
IDnsResource* m_NextResource;
std::string m_DecodedName;
size_t m_NameLength;
uint8_t* m_ExternalRawData;
IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer);
IDnsResource(uint8_t* emptyRawData);
size_t decodeName(const char* encodedName, char* result, int iteration = 1);
void encodeName(const std::string& decodedName, char* result, size_t& resultLen);
IDnsResource* getNextResource() const { return m_NextResource; }
void setNexResource(IDnsResource* next) { m_NextResource = next; }
uint8_t* getRawData() const;
void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer);
public:
virtual ~IDnsResource() {}
/**
* @return The DNS type of this record
*/
DnsType getDnsType() const;
/**
* Set DNS type for this record
* @param[in] newType The type to set
*/
void setDnsType(DnsType newType);
/**
* @return The DNS class of this record
*/
DnsClass getDnsClass() const;
/**
* Set DNS class for this record
* @param[in] newClass The class to set
*/
void setDnsClass(DnsClass newClass);
/**
* @return The name of this record
*/
const std::string& getName() const { return m_DecodedName; }
/**
* @return The record name's offset in the packet
*/
size_t getNameOffset() const { return m_OffsetInLayer; }
/**
* Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain
* a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name).
* The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you
* want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where '#{offset}'
* is a the offset from the start of the layer. For example: if the string 'yahoo.com' already appears in offset
* 12 in the packet and you want to set the name of the current record to 'my.subdomain.yahoo.com' you may use
* the following string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12.<BR>
* Please notice the new name can be shorter or longer of the old name, so this method can cause the packet to be
* shorten or extended
* @param[in] newName The name to set
* @return True if name was set successfully or false if input string is malformed or if an error occurred
*/
bool setName(const std::string& newName);
// abstract methods
/**
* @return The total size in bytes of this record
*/
virtual size_t getSize() const = 0;
/**
* @return The type of this record (query, answer, authority, additional)
*/
virtual DnsResourceType getType() const = 0;
};
/**
* @class DnsQuery
* Representing a DNS query record
*/
class DnsQuery : public IDnsResource
{
friend class DnsLayer;
private:
DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) {}
DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) {}
public:
virtual ~DnsQuery() {}
// implementation of abstract methods
virtual size_t getSize() const { return m_NameLength + 2 * sizeof(uint16_t); }
virtual DnsResourceType getType() const { return DnsQueryType; }
};
/**
* @class DnsResource
* Representing DNS record other than DNS query
*/
class DnsResource : public IDnsResource
{
friend class DnsLayer;
private:
DnsResourceType m_ResourceType;
DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) : IDnsResource(dnsLayer, offsetInLayer) { m_ResourceType = resourceType; }
DnsResource(uint8_t* emptyRawData, DnsResourceType resType) : IDnsResource(emptyRawData), m_ResourceType(resType) {}
public:
virtual ~DnsResource() {}
/**
* @return The time-to-leave value for this record
*/
uint32_t getTTL() const;
/**
* Set time-to-leave value for this record
* @param[in] newTTL The new TTL value to set
*/
void setTTL(uint32_t newTTL);
/**
* @return The data length value for this record (taken from the "data length" field of the record)
*/
size_t getDataLength() const;
/**
* @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed that the
* smart pointer will always point to an object and never to NULL. The specific object type depends on the DNS type of this record:<BR>
* - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains the IPv4 address<BR>
* - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that contains the IPv6 address<BR>
* - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the return value is
* a smart pointer to StringDnsResourceData object that contains the name<BR>
* - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains the MX data (preference and
* mail exchange name)<BR>
* - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte array of the data
*/
DnsResourceDataPtr getData() const;
/**
* @return The offset of data in the DNS layer
*/
size_t getDataOffset() const;
/**
* Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. For example: if DNS type is A
* and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a log error will be printed and the method will return false.
* This method currently supports the following DNS types:<BR>
* - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 address
* - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 address
* - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a pointer to StringDnsResourceData
* object that contains a host name, e.g: 'www.google.com'
* - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX data
* - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string (valid hex string means a string
* which has an even number of characters representing a valid hex data. e.g: '0d0a45569a9b')
* @param[in] data The pointer to the data object, as described above
* @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the packet (appropriate error log is
* printed in all cases)
*/
bool setData(IDnsResourceData* data);
/**
* Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
* user to receive these bytes
* @return The value stored in this place
*/
uint16_t getCustomDnsClass() const;
/**
* Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
* user to set these bytes
* @param[in] customValue The value to set
*/
void setCustomDnsClass(uint16_t customValue);
// implementation of abstract methods
virtual size_t getSize() const { return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); }
virtual DnsResourceType getType() const { return m_ResourceType; }
};
}
#endif // PACKETPP_DNS_RESOURCE