diff --git a/Makefile.am b/Makefile.am index c473f8c9..2bcb0ee6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,6 @@ libtins_la_SOURCES=src/arp.cpp \ src/dhcp.cpp \ src/dhcpv6.cpp \ src/dns.cpp \ - src/dns_record.cpp \ src/dot3.cpp \ src/dot1q.cpp \ src/eapol.cpp \ @@ -71,7 +70,6 @@ libtins_HEADERS = include/internals.h \ include/small_uint.h \ include/ip.h \ include/ipsec.h \ - include/dns_record.h \ include/eapol.h \ include/tcp_stream.h \ include/pppoe.h \ diff --git a/Makefile.in b/Makefile.in index cd99c6c5..0dc10cf8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,16 +108,15 @@ libtins_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo \ src/handshake_capturer.lo src/stp.lo src/pppoe.lo \ - src/crypto.lo src/dhcp.lo src/dhcpv6.lo src/dns.lo \ - src/dns_record.lo src/dot3.lo src/dot1q.lo src/eapol.lo \ - src/ethernetII.lo src/icmp.lo src/icmpv6.lo src/internals.lo \ - src/ip_reassembler.lo src/ip.lo src/ip_address.lo src/ipv6.lo \ - src/ipv6_address.lo src/ipsec.lo src/llc.lo src/loopback.lo \ - src/network_interface.lo src/packet_sender.lo \ - src/packet_writer.lo src/ppi.lo src/pdu.lo src/radiotap.lo \ - src/address_range.lo src/rawpdu.lo src/rsn_information.lo \ - src/sll.lo src/snap.lo src/sniffer.lo src/tcp.lo \ - src/tcp_stream.lo src/udp.lo src/utils.lo \ + src/crypto.lo src/dhcp.lo src/dhcpv6.lo src/dns.lo src/dot3.lo \ + src/dot1q.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \ + src/icmpv6.lo src/internals.lo src/ip_reassembler.lo src/ip.lo \ + src/ip_address.lo src/ipv6.lo src/ipv6_address.lo src/ipsec.lo \ + src/llc.lo src/loopback.lo src/network_interface.lo \ + src/packet_sender.lo src/packet_writer.lo src/ppi.lo \ + src/pdu.lo src/radiotap.lo src/address_range.lo src/rawpdu.lo \ + src/rsn_information.lo src/sll.lo src/snap.lo src/sniffer.lo \ + src/tcp.lo src/tcp_stream.lo src/udp.lo src/utils.lo \ src/dot11/dot11_base.lo src/dot11/dot11_data.lo \ src/dot11/dot11_mgmt.lo src/dot11/dot11_beacon.lo \ src/dot11/dot11_assoc.lo src/dot11/dot11_auth.lo \ @@ -309,7 +308,6 @@ libtins_la_SOURCES = src/arp.cpp \ src/dhcp.cpp \ src/dhcpv6.cpp \ src/dns.cpp \ - src/dns_record.cpp \ src/dot3.cpp \ src/dot1q.cpp \ src/eapol.cpp \ @@ -359,7 +357,6 @@ libtins_HEADERS = include/internals.h \ include/small_uint.h \ include/ip.h \ include/ipsec.h \ - include/dns_record.h \ include/eapol.h \ include/tcp_stream.h \ include/pppoe.h \ @@ -522,7 +519,6 @@ src/crypto.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dhcp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dhcpv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dns.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/dns_record.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dot3.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dot1q.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/eapol.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) @@ -601,8 +597,6 @@ mostlyclean-compile: -rm -f src/dhcpv6.lo -rm -f src/dns.$(OBJEXT) -rm -f src/dns.lo - -rm -f src/dns_record.$(OBJEXT) - -rm -f src/dns_record.lo -rm -f src/dot11/dot11_assoc.$(OBJEXT) -rm -f src/dot11/dot11_assoc.lo -rm -f src/dot11/dot11_auth.$(OBJEXT) @@ -696,7 +690,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dhcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dhcpv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns_record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot1q.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/eapol.Plo@am__quote@ diff --git a/include/dns.h b/include/dns.h index d8996468..81b32f6f 100644 --- a/include/dns.h +++ b/include/dns.h @@ -39,7 +39,6 @@ #include "macros.h" #include "pdu.h" #include "endianness.h" -#include "dns_record.h" namespace Tins { class IPv4Address; @@ -200,14 +199,24 @@ namespace Tins { */ class Resource { public: - Resource(const std::string &nm, const std::string &ad, - uint16_t t, uint16_t c, uint32_t tt) - : dname_(nm), addr_(ad), type_(t), qclass_(c), ttl_(tt) {} + /** + * Constructs a Resource object. + * + * \param dname The domain name for which this records + * provides an answer. + * \param data The resource's payload. + * \param type The type of this record. + * \param rclass The class of this record. + * \param ttl The time-to-live of this record. + */ + Resource(const std::string &dname, const std::string &data, + uint16_t type, uint16_t rclass, uint32_t ttl) + : dname_(dname), data_(data), type_(type), qclass_(rclass), ttl_(ttl) {} Resource() : type_(), qclass_(), ttl_() {} /** - * \brief Getter for the dname field. + * \brief Getter for the domain name field. * * This returns the domain name for which this record * provides an answer. @@ -215,9 +224,9 @@ namespace Tins { const std::string &dname() const { return dname_; } /** - * Getter for the type field. + * Getter for the data field. */ - const std::string &data() const { return addr_; } + const std::string &data() const { return data_; } /** * Getter for the query type field. @@ -233,8 +242,52 @@ namespace Tins { * Getter for the type field. */ uint32_t ttl() const { return ttl_; } + + /** + * Setter for the domain name field. + */ + void dname(const std::string &data) { + dname_ = data; + } + + /** + * \brief Setter for the data field. + * + * The data will be encoded properly by the DNS class before + * being added to this packet. That means that if the type is + * A or AAAA, it will be properly encoded as an IPv4 or + * IPv6 address. + * + * The same happens for records that contain domain names, + * such as NS or CNAME. This data will be encoded using + * DNS domain name encoding. + */ + void data(const std::string &data) { + data_ = data; + } + + /** + * Setter for the type field. + */ + void type(uint16_t data) { + type_ = data; + } + + /** + * Setter for the class field. + */ + void query_class(uint16_t data) { + qclass_ = data; + } + + /** + * Setter for the time-to-live field. + */ + void ttl(uint16_t data) { + ttl_ = data; + } private: - std::string dname_, addr_; + std::string dname_, data_; uint16_t type_, qclass_; uint32_t ttl_; }; @@ -482,79 +535,25 @@ namespace Tins { void add_query(const Query &query); /** - * \brief Add a query response. - * - * \param name The resolved name. - * \param type The type of this answer. - * \param qclass The class of this answer. - * \param ttl The time-to-live of this answer. - * \param ip The ip address of the resolved name. - */ - void add_answer(const std::string &name, - const DNSResourceRecord::info &info, address_type ip); - - /** - * \brief Add a query response. - * - * \param name The resolved name. - * \param type The type of this answer. - * \param qclass The class of this answer. - * \param ttl The time-to-live of this answer. - * \param ip The ip address of the resolved name. - */ - void add_answer(const std::string &name, - const DNSResourceRecord::info &info, address_v6_type ip); - - /** - * \brief Add a query response. + * \brief Add an answer resource record. * - * \param name The resolved name. - * \param type The type of this answer. - * \param qclass The class of this answer. - * \param ttl The time-to-live of this answer. - * \param dname The domain of the resolved name. + * \param resource The resource to be added. */ - void add_answer(const std::string &name, - const DNSResourceRecord::info &info, const std::string &dname); - - /** - * \brief Add a query response. - * - * \param name The resolved name. - * \param type The type of this answer. - * \param qclass The class of this answer. - * \param ttl The time-to-live of this answer. - * \param data The data of this option. - * \param sz The size of the data. - */ - void add_answer(const std::string &name, - const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz); - + void add_answer(const Resource &resource); + /** - * \brief Add an authority record. + * \brief Add an authority resource record. * - * \param name The resolved name. - * \param type The type of this record. - * \param qclass The class of this record. - * \param ttl The time-to-live of this record. - * \param data The data of this option. - * \param sz The size of the data. + * \param resource The resource to be added. */ - void add_authority(const std::string &name, - const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz); + void add_authority(const Resource &resource); /** - * \brief Add an additional record. + * \brief Add an additional resource record. * - * \param name The resolved name. - * \param type The type of this record. - * \param qclass The class of this record. - * \param ttl The time-to-live of this record. - * \param ip The ip address of the resolved name. + * \param resource The resource to be added. */ - void add_additional(const std::string &name, - const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz); - + void add_additional(const Resource &resource); /** * \brief Getter for this PDU's DNS queries. @@ -616,17 +615,6 @@ namespace Tins { DNS *clone() const { return new DNS(*this); } - - /** - * Helper function to create a resource record information. - * - * \param type The type of the query. - * \param qclass The class of the query. - * \param ttl The time-to-live of the query. - */ - static DNSResourceRecord::info make_info(QueryType type, QueryClass qclass, uint32_t ttl) { - return DNSResourceRecord::info((uint16_t)type, (uint16_t)qclass, ttl); - } private: TINS_BEGIN_PACK struct dnshdr { @@ -672,8 +660,7 @@ namespace Tins { static void inline_convert_v4(uint32_t value, char *output); static bool contains_dname(uint16_t type); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); - void add_record(const std::string &name, const DNSResourceRecord::info &info, - const uint8_t *data, uint32_t sz, const sections_type §ions); + void add_record(const Resource &resource, const sections_type §ions); dnshdr dns; byte_array records_data; diff --git a/include/dns_record.h b/include/dns_record.h deleted file mode 100644 index ff36c189..00000000 --- a/include/dns_record.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2012, Matias Fontanini - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * - * 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 - * OWNER 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 TINS_DNS_RECORD_H -#define TINS_DNS_RECORD_H - -#include -#include -#include -#include "cxxstd.h" -#include "macros.h" - -namespace Tins { -/** - * \cond - */ -class DNSRRImpl { -public: - virtual ~DNSRRImpl() {} - virtual uint32_t size() const = 0; - virtual uint32_t do_write(uint8_t *buffer) const = 0; - virtual bool matches(const std::string &dname) const { return false; } - virtual DNSRRImpl *clone() const = 0; -}; - -/** - * \brief Abstracts a DNS resource record. - */ -class DNSResourceRecord { -public: - /** - * \brief The type used to store resource records' information. - */ - TINS_BEGIN_PACK - struct info { - uint16_t type, qclass; - uint32_t ttl; - - info(uint16_t tp, uint16_t qc, uint32_t tm) - : type(tp), qclass(qc), ttl(tm) { } - - info() : type(), qclass(), ttl() {} - } TINS_END_PACK; - - /** - * \brief Constructs a record. - * \param impl A pointer to the impl object. - * \param data A pointer to the start of the data buffer. - * \param len The length of the data. - */ - DNSResourceRecord(DNSRRImpl *impl = 0, const uint8_t *data = 0, uint16_t len = 0); - - /** - * \brief Constructs a record. - * - * If the input data is malformed, a malformed_packet exception - * is thrown. - * - * \param buffer A pointer to the start of the data buffer. - * \param len The length of the data. - */ - DNSResourceRecord(const uint8_t *buffer, uint32_t size); - - /** - * \brief Constructs a record from an input range. - * \param impl A pointer to the impl object. - * \param start The begining of the range. - * \param end The end of the range. - */ - template - DNSResourceRecord(DNSRRImpl *impl, ForwardIterator start, ForwardIterator end) - : impl(impl), data(start, end) - { } - - /** - * \brief Copy constructor. - * - * This handles cloning the impl object. - * \param rhs The record which will be copied. - */ - DNSResourceRecord(const DNSResourceRecord &rhs); - - /** - * \brief Copy assignment operator. - * - * This handles cloning the impl object. - * \param rhs The record which will be copied. - */ - DNSResourceRecord& operator=(const DNSResourceRecord &rhs); - - #if TINS_IS_CXX11 - /** - * Move constructor. - */ - DNSResourceRecord(DNSResourceRecord &&rhs) noexcept - : info_(rhs.info_), data(std::move(rhs.data)), impl(0) { - std::swap(impl, rhs.impl); - } - - /** - * Move assignment operator. - */ - DNSResourceRecord& operator=(DNSResourceRecord &&rhs) noexcept - { - info_ = rhs.info_; - data = std::move(rhs.data); - delete impl; - impl = 0; - std::swap(impl, rhs.impl); - return *this; - } - #endif // TINS_IS_CXX11 - - /** - * \brief Destructor. - * - * This frees the impl object. - */ - ~DNSResourceRecord(); - - /** - * \brief Writes this record to a buffer. - * - * \param buffer The buffer in which to store the serialization. - * \return uint32_t containing the number of bytes written. - */ - uint32_t write(uint8_t *buffer) const; - - /** - * \brief Returns the size of the data in this record. - */ - uint32_t data_size() const { - return data.size(); - } - - /** - * \brief Returns the pointer to the start of the data buffer. - */ - const uint8_t *data_ptr() const { - return &data[0]; - } - - /** - * \brief Returns a bool indicating whether this record contains - * a domain name as the name being resolved. - */ - bool has_domain_name() const; - - /** - * \brief Returns a pointer to the domain name stored in this record. - * - * This will throw a std::bad_cast exception if the impl object is - * not of the type NamedDNSRRImpl. - */ - const std::string *dname() const; - - /** - * \brief Returns the offset stored in this record. - * - * This will throw a std::bad_cast exception if the impl object is - * not of the type OffsetedDNSRRImpl. - */ - uint16_t offset() const; - - /** - * \brief Returns the size of this record. - */ - uint32_t size() const; - - /** - * \brief Returns a reference to the info field. - */ - info &information() { - return info_; - } - - /** - * \brief Returns a const reference to the info field. - */ - const info &information() const { - return info_; - } - - /** - * \brief Checks if the domain name stored in this record matches - * the given one. - * - * This is a shortcut - */ - bool matches(const std::string &dname) const; -private: - DNSRRImpl *clone_impl() const; - size_t impl_size() const; - - info info_; - std::vector data; - DNSRRImpl *impl; -}; - -class OffsetedDNSRRImpl : public DNSRRImpl { -public: - OffsetedDNSRRImpl(uint16_t off); - - uint32_t do_write(uint8_t *buffer) const; - uint32_t size() const; - OffsetedDNSRRImpl *clone() const; - uint16_t offset() const; -private: - uint16_t offset_; -}; - -class NamedDNSRRImpl : public DNSRRImpl { -public: - NamedDNSRRImpl(const std::string &nm); - - template - NamedDNSRRImpl(ForwardIterator start, ForwardIterator end) - : name(start, end) - { } - - uint32_t do_write(uint8_t *buffer) const; - - uint32_t size() const; - - bool matches(const std::string &dname) const; - - const std::string *dname_pointer() const; - NamedDNSRRImpl *clone() const; -private: - std::string name; -}; - -/** - * \endcond - */ - -inline DNSResourceRecord make_offseted_record(uint16_t offset, const uint8_t *data = 0, uint32_t size = 0) { - return DNSResourceRecord(new OffsetedDNSRRImpl(offset), data, size); -} - -inline DNSResourceRecord make_named_record(const std::string &name, const uint8_t *data = 0, uint32_t size = 0) { - return DNSResourceRecord(new NamedDNSRRImpl(name), data, size); -} -} - -#endif // TINS_DNS_RECORD_H diff --git a/src/dns.cpp b/src/dns.cpp index c13ba20c..ce2d7f68 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -185,61 +185,40 @@ void DNS::add_query(const Query &query) { ); } -void DNS::add_answer(const string &name, const DNSResourceRecord::info &info, - address_type ip) -{ - uint32_t ip_int = ip; - add_answer( - name, - info, - (const uint8_t*)&ip_int, - sizeof(ip_int) - ); -} - -void DNS::add_answer(const string &name, const DNSResourceRecord::info &info, - address_v6_type ip) -{ - add_answer( - name, - info, - ip.begin(), - address_v6_type::address_size - ); -} - -void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info, - const std::string &dname) -{ - std::string parsed = encode_domain_name(dname); - add_answer( - name, - info, - (const uint8_t*)parsed.c_str(), - parsed.size() - ); -} - -void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info, - const uint8_t *data, uint32_t sz) -{ +void DNS::add_answer(const Resource &resource) { sections_type sections; sections.push_back(std::make_pair(&authority_idx, authority_count())); sections.push_back(std::make_pair(&additional_idx, additional_count())); - add_record(name, info, data, sz, sections); + add_record(resource, sections); dns.answers = Endian::host_to_be( answers_count() + 1 ); } -void DNS::add_record(const std::string &name, const DNSResourceRecord::info &info, - const uint8_t *data, uint32_t sz, const sections_type §ions) -{ - std::string buffer = encode_domain_name(name); - uint32_t offset = buffer.size() + sizeof(uint16_t) * 3 + sizeof(uint32_t) + sz, +void DNS::add_record(const Resource &resource, const sections_type §ions) { + // We need to check that the data provided is correct. Otherwise, the sections + // will end up being inconsistent. + IPv4Address v4_addr; + IPv6Address v6_addr; + std::string buffer = encode_domain_name(resource.dname()), encoded_data; + // By default the data size is the length of the data field. + uint32_t data_size = resource.data().size(); + if(resource.type() == A) { + v4_addr = resource.data(); + data_size = 4; + } + else if(resource.type() == AAAA) { + v6_addr = resource.data(); + data_size = IPv6Address::address_size; + } + else if(contains_dname(resource.type())) { + encoded_data = encode_domain_name(resource.data()); + data_size = encoded_data.size(); + } + uint32_t offset = buffer.size() + sizeof(uint16_t) * 3 + sizeof(uint32_t) + data_size, threshold = sections.empty() ? records_data.size() : *sections.front().first; // Skip the preference field - if(info.type == MX) { + if(resource.type() == MX) { offset += sizeof(uint16_t); } for(size_t i = 0; i < sections.size(); ++i) { @@ -256,39 +235,45 @@ void DNS::add_record(const std::string &name, const DNSResourceRecord::info &inf buffer.end(), &records_data[threshold] ); - *(uint16_t*)ptr = Endian::host_to_be(info.type); + *(uint16_t*)ptr = Endian::host_to_be(resource.type()); ptr += sizeof(uint16_t); - *(uint16_t*)ptr = Endian::host_to_be(info.qclass); + *(uint16_t*)ptr = Endian::host_to_be(resource.query_class()); ptr += sizeof(uint16_t); - *(uint32_t*)ptr = Endian::host_to_be(info.ttl); + *(uint32_t*)ptr = Endian::host_to_be(resource.ttl()); ptr += sizeof(uint32_t); - *(uint16_t*)ptr = Endian::host_to_be(sz + (info.type == MX ? 2 : 0)); + *(uint16_t*)ptr = Endian::host_to_be( + data_size + (resource.type() == MX ? 2 : 0) + ); ptr += sizeof(uint16_t); - if(info.type == MX) { + if(resource.type() == MX) { ptr += sizeof(uint16_t); } - std::copy( - data, - data + sz, - ptr - ); + if(resource.type() == A) { + uint32_t ip_int = v4_addr; + std::memcpy(ptr, &ip_int, sizeof(ip_int)); + } + else if(resource.type() == AAAA) { + std::copy(v6_addr.begin(), v6_addr.end(), ptr); + } + else if(!encoded_data.empty()) { + std::copy(encoded_data.begin(), encoded_data.end(), ptr); + } + else { + std::copy(resource.data().begin(), resource.data().end(), ptr); + } } -void DNS::add_authority(const string &name, const DNSResourceRecord::info &info, - const uint8_t *data, uint32_t sz) -{ +void DNS::add_authority(const Resource &resource) { sections_type sections; sections.push_back(std::make_pair(&additional_idx, additional_count())); - add_record(name, info, data, sz, sections); + add_record(resource, sections); dns.authority = Endian::host_to_be( authority_count() + 1 ); } -void DNS::add_additional(const string &name, const DNSResourceRecord::info &info, - const uint8_t *data, uint32_t sz) -{ - add_record(name, info, data, sz, sections_type()); +void DNS::add_additional(const Resource &resource){ + add_record(resource, sections_type()); dns.additional = Endian::host_to_be( additional_count() + 1 ); diff --git a/src/dns_record.cpp b/src/dns_record.cpp deleted file mode 100644 index 8599ae99..00000000 --- a/src/dns_record.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2012, Matias Fontanini - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * - * 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 - * OWNER 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 -#include -#include -#include -#include "dns_record.h" -#include "endianness.h" -#include "exceptions.h" - -namespace Tins { -bool contains_dname(uint16_t type) { - type = Endian::be_to_host(type); - return type == 1 || type == 2 || - type == 5 || type == 6 || - type == 12 || type == 15 || - type == 28 || type == 41; -} - -DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl, - const uint8_t *d, uint16_t len) : impl(impl) -{ - if(d && len) - data.assign(d, d + len); -} - -DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size) -{ - const uint8_t *buffer_end = buffer + size; - Internals::smart_ptr::type tmp_impl; - if((*buffer & 0xc0)) { - uint16_t offset(*reinterpret_cast(buffer)); - offset = Endian::be_to_host(offset) & 0x3fff; - tmp_impl.reset(new OffsetedDNSRRImpl(Endian::host_to_be(offset))); - buffer += sizeof(uint16_t); - } - else { - const uint8_t *str_end(buffer); - while(str_end < buffer_end && *str_end) - str_end++; - if(str_end == buffer_end) - throw malformed_packet(); - //str_end++; - tmp_impl.reset(new NamedDNSRRImpl(buffer, str_end)); - buffer = ++str_end; - } - if(buffer + sizeof(info_) > buffer_end) - throw malformed_packet(); - std::memcpy(&info_, buffer, sizeof(info_)); - buffer += sizeof(info_); - if(buffer + sizeof(uint16_t) > buffer_end) - throw malformed_packet(); - - // Store the option size. - data.resize( - Endian::be_to_host(*reinterpret_cast(buffer)) - ); - buffer += sizeof(uint16_t); - if(buffer + data.size() > buffer_end) - throw malformed_packet(); - if(contains_dname(info_.type) || data.size() != sizeof(uint32_t)) - std::copy(buffer, buffer + data.size(), data.begin()); - else if(data.size() == sizeof(uint32_t)) - *(uint32_t*)&data[0] = *(uint32_t*)buffer; - impl = tmp_impl.release(); -} - -DNSResourceRecord::DNSResourceRecord(const DNSResourceRecord &rhs) -: info_(rhs.info_), data(rhs.data), impl(rhs.clone_impl()) -{ - -} - -DNSResourceRecord& DNSResourceRecord::operator=(const DNSResourceRecord &rhs) -{ - delete impl; - info_ = rhs.info_; - data = rhs.data; - impl = rhs.clone_impl(); - return *this; -} - -DNSResourceRecord::~DNSResourceRecord() { - delete impl; -} - -uint32_t DNSResourceRecord::write(uint8_t *buffer) const { - const uint32_t sz(impl ? impl->do_write(buffer) : 0); - buffer += sz; - std::memcpy(buffer, &info_, sizeof(info_)); - buffer += sizeof(info_); - *((uint16_t*)buffer) = Endian::host_to_be(data.size()); - buffer += sizeof(uint16_t); - std::copy(data.begin(), data.end(), buffer); - return sz + sizeof(info_) + sizeof(uint16_t) + data.size(); -} - -DNSRRImpl *DNSResourceRecord::clone_impl() const { - return impl ? impl->clone() : 0; -} - -bool DNSResourceRecord::has_domain_name() const { - if(!impl) - throw std::bad_cast(); - return dynamic_cast(impl) != 0; -} - -const std::string *DNSResourceRecord::dname() const { - if(!impl) - throw std::bad_cast(); - return dynamic_cast(*impl).dname_pointer(); -} - -uint16_t DNSResourceRecord::offset() const { - return dynamic_cast(*impl).offset(); -} - -size_t DNSResourceRecord::impl_size() const { - return impl ? impl->size() : 0; -} - -uint32_t DNSResourceRecord::size() const { - return sizeof(info_) + data.size() + sizeof(uint16_t) + impl_size(); -} - -bool DNSResourceRecord::matches(const std::string &dname) const { - return impl ? impl->matches(dname) : false; -} - -// OffsetedRecord - -OffsetedDNSRRImpl::OffsetedDNSRRImpl(uint16_t off) -: offset_(off | Endian::host_to_be(0xc000)) -{ - -} - -uint32_t OffsetedDNSRRImpl::do_write(uint8_t *buffer) const { - std::memcpy(buffer, &offset_, sizeof(offset_)); - return sizeof(offset_); -} - -uint32_t OffsetedDNSRRImpl::size() const { - return sizeof(offset_); -} - -OffsetedDNSRRImpl *OffsetedDNSRRImpl::clone() const { - return new OffsetedDNSRRImpl(*this); -} - -uint16_t OffsetedDNSRRImpl::offset() const { - return offset_; -} - -// NamedRecord - -NamedDNSRRImpl::NamedDNSRRImpl(const std::string &nm) -: name(nm) -{ - -} - -uint32_t NamedDNSRRImpl::size() const { - return name.size() + 1; -} - -uint32_t NamedDNSRRImpl::do_write(uint8_t *buffer) const { - buffer = std::copy(name.begin(), name.end(), buffer); - *buffer = 0; - return name.size() + 1; -} - -const std::string *NamedDNSRRImpl::dname_pointer() const { - return &name; -} - -bool NamedDNSRRImpl::matches(const std::string &dname) const { - return dname == name; -} - -NamedDNSRRImpl *NamedDNSRRImpl::clone() const { - return new NamedDNSRRImpl(*this); -} - -} diff --git a/tests/depends.d b/tests/depends.d index 6e5294df..35496b56 100644 --- a/tests/depends.d +++ b/tests/depends.d @@ -107,8 +107,8 @@ ../include/dot11/../dot11/../endianness.h \ ../include/dot11/../dot11/../internals.h \ ../include/dot11/../dot11/../ip_address.h \ - ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../ipv6_address.h \ + ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../small_uint.h \ ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../endianness.h \ @@ -174,10 +174,10 @@ ../include/dot11/../dot11/../ip_address.h: -../include/dot11/../dot11/../hw_address.h: - ../include/dot11/../dot11/../ipv6_address.h: +../include/dot11/../dot11/../hw_address.h: + ../include/dot11/../dot11/../small_uint.h: ../include/dot11/../dot11/../hw_address.h: @@ -270,7 +270,7 @@ ../include/exceptions.h: ../src/dns.o: ../src/dns.cpp ../include/dns.h ../include/macros.h \ ../include/pdu.h ../include/cxxstd.h ../include/exceptions.h \ - ../include/endianness.h ../include/dns_record.h ../include/ip_address.h \ + ../include/endianness.h ../include/ip_address.h \ ../include/ipv6_address.h ../include/exceptions.h ../include/rawpdu.h ../include/dns.h: @@ -285,8 +285,6 @@ ../include/endianness.h: -../include/dns_record.h: - ../include/ip_address.h: ../include/ipv6_address.h: @@ -294,19 +292,6 @@ ../include/exceptions.h: ../include/rawpdu.h: -../src/dns_record.o: ../src/dns_record.cpp ../include/dns_record.h \ - ../include/cxxstd.h ../include/macros.h ../include/endianness.h \ - ../include/exceptions.h - -../include/dns_record.h: - -../include/cxxstd.h: - -../include/macros.h: - -../include/endianness.h: - -../include/exceptions.h: ../src/dot11/dot11_assoc.o: ../src/dot11/dot11_assoc.cpp \ ../include/dot11/dot11_assoc.h ../include/dot11/../config.h \ ../include/dot11/../dot11/dot11_mgmt.h \ @@ -1976,7 +1961,16 @@ ../include/exceptions.h: ../src/rsn_information.o: ../src/rsn_information.cpp \ ../include/rsn_information.h ../include/endianness.h ../include/macros.h \ - ../include/exceptions.h + ../include/exceptions.h ../include/dot11/dot11_base.h \ + ../include/dot11/../config.h ../include/dot11/../pdu.h \ + ../include/dot11/../macros.h ../include/dot11/../cxxstd.h \ + ../include/dot11/../exceptions.h ../include/dot11/../pdu_option.h \ + ../include/dot11/../endianness.h ../include/dot11/../internals.h \ + ../include/dot11/../constants.h ../include/dot11/../pdu.h \ + ../include/dot11/../hw_address.h ../include/dot11/../ip_address.h \ + ../include/dot11/../ipv6_address.h ../include/dot11/../small_uint.h \ + ../include/dot11/../hw_address.h ../include/dot11/../endianness.h \ + ../include/dot11/../cxxstd.h ../include/dot11/../macros.h ../include/rsn_information.h: @@ -1985,6 +1979,44 @@ ../include/macros.h: ../include/exceptions.h: + +../include/dot11/dot11_base.h: + +../include/dot11/../config.h: + +../include/dot11/../pdu.h: + +../include/dot11/../macros.h: + +../include/dot11/../cxxstd.h: + +../include/dot11/../exceptions.h: + +../include/dot11/../pdu_option.h: + +../include/dot11/../endianness.h: + +../include/dot11/../internals.h: + +../include/dot11/../constants.h: + +../include/dot11/../pdu.h: + +../include/dot11/../hw_address.h: + +../include/dot11/../ip_address.h: + +../include/dot11/../ipv6_address.h: + +../include/dot11/../small_uint.h: + +../include/dot11/../hw_address.h: + +../include/dot11/../endianness.h: + +../include/dot11/../cxxstd.h: + +../include/dot11/../macros.h: ../src/sll.o: ../src/sll.cpp ../include/sll.h ../include/pdu.h \ ../include/macros.h ../include/cxxstd.h ../include/exceptions.h \ ../include/endianness.h ../include/hw_address.h ../include/internals.h \ @@ -2063,7 +2095,7 @@ ../include/dot11/../exceptions.h ../include/dot11/../endianness.h \ ../include/dot11/../macros.h ../include/dot11/../internals.h \ ../include/dot11/../ip_address.h ../include/dot11/../cxxstd.h \ - ../include/dot11/../hw_address.h ../include/dot11/../ipv6_address.h \ + ../include/dot11/../ipv6_address.h ../include/dot11/../hw_address.h \ ../include/dot11/../small_uint.h ../include/dot11/../hw_address.h \ ../include/dot11/../endianness.h ../include/dot11/../cxxstd.h \ ../include/dot11/../macros.h ../include/ethernetII.h \ @@ -2111,10 +2143,10 @@ ../include/dot11/../cxxstd.h: -../include/dot11/../hw_address.h: - ../include/dot11/../ipv6_address.h: +../include/dot11/../hw_address.h: + ../include/dot11/../small_uint.h: ../include/dot11/../hw_address.h: @@ -2524,10 +2556,9 @@ src/dhcpv6.o: src/dhcpv6.cpp ../include/dhcpv6.h ../include/pdu.h \ ../include/ip_address.h: src/dns.o: src/dns.cpp ../include/dns.h ../include/macros.h \ ../include/pdu.h ../include/cxxstd.h ../include/exceptions.h \ - ../include/endianness.h ../include/dns_record.h \ - ../include/ipv6_address.h ../include/utils.h ../include/ip_address.h \ - ../include/ipv6_address.h ../include/hw_address.h ../include/internals.h \ - ../include/constants.h + ../include/endianness.h ../include/ipv6_address.h ../include/utils.h \ + ../include/ip_address.h ../include/ipv6_address.h \ + ../include/hw_address.h ../include/internals.h ../include/constants.h ../include/dns.h: @@ -2541,8 +2572,6 @@ src/dns.o: src/dns.cpp ../include/dns.h ../include/macros.h \ ../include/endianness.h: -../include/dns_record.h: - ../include/ipv6_address.h: ../include/utils.h: @@ -4889,8 +4918,8 @@ src/wep_decrypt.o: src/wep_decrypt.cpp ../include/config.h \ ../include/dot11/../dot11/../endianness.h \ ../include/dot11/../dot11/../internals.h \ ../include/dot11/../dot11/../ip_address.h \ - ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../ipv6_address.h \ + ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../small_uint.h \ ../include/dot11/../dot11/../hw_address.h \ ../include/dot11/../dot11/../endianness.h \ @@ -4957,10 +4986,10 @@ src/wep_decrypt.o: src/wep_decrypt.cpp ../include/config.h \ ../include/dot11/../dot11/../ip_address.h: -../include/dot11/../dot11/../hw_address.h: - ../include/dot11/../dot11/../ipv6_address.h: +../include/dot11/../dot11/../hw_address.h: + ../include/dot11/../dot11/../small_uint.h: ../include/dot11/../dot11/../hw_address.h: diff --git a/tests/src/dns.cpp b/tests/src/dns.cpp index 6c6f02dd..d1e75b76 100644 --- a/tests/src/dns.cpp +++ b/tests/src/dns.cpp @@ -119,7 +119,9 @@ TEST_F(DNSTest, ConstructorFromBuffer2) { if(i == 0) { dns.add_query(DNS::Query("google.com", DNS::A, DNS::IN)); dns.add_query(DNS::Query("google.com", DNS::MX, DNS::IN)); - dns.add_answer("google.com", DNS::make_info(DNS::MX, DNS::IN, 0x762), std::string("alt5.aspmx.l.google.com")); + dns.add_answer( + DNS::Resource("google.com", "alt5.aspmx.l.google.com", DNS::MX, DNS::IN, 0x762) + ); } } } @@ -243,8 +245,12 @@ TEST_F(DNSTest, Question) { TEST_F(DNSTest, Answers) { DNS dns; - dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.1")); - dns.add_answer("www.example2.com", DNS::make_info(DNS::MX, DNS::IN, 0x762), std::string("mail.example.com")); + dns.add_answer( + DNS::Resource("www.example.com", "127.0.0.1", DNS::A, DNS::IN, 0x762) + ); + dns.add_answer( + DNS::Resource("www.example2.com", "mail.example.com", DNS::MX, DNS::IN, 0x762) + ); ASSERT_EQ(dns.answers_count(), 2); @@ -269,9 +275,13 @@ TEST_F(DNSTest, Answers) { TEST_F(DNSTest, Authority) { DNS dns; - std::string encoded = DNS::encode_domain_name("carlos.example.com"); - dns.add_authority("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); - dns.add_authority("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); + const char *domain = "carlos.example.com"; + dns.add_authority( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); + dns.add_authority( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); ASSERT_EQ(dns.authority_count(), 2); @@ -281,7 +291,7 @@ TEST_F(DNSTest, Authority) { EXPECT_EQ("www.example.com", it->dname()); EXPECT_EQ(it->type(), DNS::CNAME); EXPECT_EQ(it->ttl(), 0x762U); - EXPECT_EQ(it->data(), "carlos.example.com"); + EXPECT_EQ(it->data(), domain); EXPECT_EQ(it->query_class(), DNS::IN); } } @@ -289,9 +299,13 @@ TEST_F(DNSTest, Authority) { TEST_F(DNSTest, Additional) { DNS dns; - std::string encoded = DNS::encode_domain_name("carlos.example.com"); - dns.add_additional("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); - dns.add_additional("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); + const char *domain = "carlos.example.com"; + dns.add_additional( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); + dns.add_additional( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); ASSERT_EQ(dns.additional_count(), 2); @@ -300,15 +314,19 @@ TEST_F(DNSTest, Additional) { EXPECT_EQ("www.example.com", it->dname()); EXPECT_EQ(it->type(), DNS::CNAME); EXPECT_EQ(it->ttl(), 0x762U); - EXPECT_EQ(it->data(), "carlos.example.com"); + EXPECT_EQ(it->data(), domain); EXPECT_EQ(it->query_class(), DNS::IN); } } TEST_F(DNSTest, AnswersWithSameName) { DNS dns; - dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.1")); - dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.2")); + dns.add_answer( + DNS::Resource("www.example.com", "127.0.0.1", DNS::A, DNS::IN, 0x762) + ); + dns.add_answer( + DNS::Resource("www.example.com", "127.0.0.2", DNS::A, DNS::IN, 0x762) + ); ASSERT_EQ(dns.answers_count(), 2); DNS::resources_type resources = dns.answers(); for(DNS::resources_type::const_iterator it = resources.begin(); it != resources.end(); ++it) { @@ -322,8 +340,12 @@ TEST_F(DNSTest, AnswersWithSameName) { TEST_F(DNSTest, AnswersV6) { DNS dns; - dns.add_answer("www.example.com", DNS::make_info(DNS::AAAA, DNS::IN, 0x762), IPv6Address("f9a8:239::1:1")); - dns.add_answer("www.example.com", DNS::make_info(DNS::AAAA, DNS::IN, 0x762), IPv6Address("f9a8:239::1:1")); + dns.add_answer( + DNS::Resource("www.example.com", "f9a8:239::1:1", DNS::AAAA, DNS::IN, 0x762) + ); + dns.add_answer( + DNS::Resource("www.example.com", "f9a8:239::1:1", DNS::AAAA, DNS::IN, 0x762) + ); ASSERT_EQ(dns.answers_count(), 2); DNS::resources_type resources = dns.answers(); @@ -341,9 +363,13 @@ TEST_F(DNSTest, ItAintGonnaCorrupt) { EXPECT_EQ(dns.questions_count(), 1); EXPECT_EQ(dns.answers_count(), 5); - std::string encoded = DNS::encode_domain_name("carlos.example.com"); - dns.add_additional("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); - dns.add_authority("www.example.com", DNS::make_info(DNS::CNAME, DNS::IN, 0x762), (const uint8_t*)encoded.c_str(), encoded.size()); + const char *domain = "carlos.example.com"; + dns.add_additional( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); + dns.add_authority( + DNS::Resource("www.example.com", domain, DNS::CNAME, DNS::IN, 0x762) + ); dns.add_query(DNS::Query("google.com", DNS::A, DNS::IN)); DNS::queries_type queries(dns.queries()); @@ -376,7 +402,7 @@ TEST_F(DNSTest, ItAintGonnaCorrupt) { EXPECT_EQ("www.example.com", it->dname()); EXPECT_EQ(it->type(), DNS::CNAME); EXPECT_EQ(it->ttl(), 0x762U); - EXPECT_EQ(it->data(), "carlos.example.com"); + EXPECT_EQ(it->data(), domain); EXPECT_EQ(it->query_class(), DNS::IN); } @@ -388,7 +414,7 @@ TEST_F(DNSTest, ItAintGonnaCorrupt) { EXPECT_EQ("www.example.com", it->dname()); EXPECT_EQ(it->type(), DNS::CNAME); EXPECT_EQ(it->ttl(), 0x762U); - EXPECT_EQ(it->data(), "carlos.example.com"); + EXPECT_EQ(it->data(), domain); EXPECT_EQ(it->query_class(), DNS::IN); } }