diff --git a/include/dns.h b/include/dns.h index b760b03..c0157cb 100644 --- a/include/dns.h +++ b/include/dns.h @@ -163,7 +163,7 @@ namespace Tins { * * \return uint16_t containing the value of the id field. */ - uint16_t id() { return dns.id; } + uint16_t id() const { return Utils::net_to_host_s(dns.id); } /** * \brief Setter for the query response field. @@ -171,14 +171,14 @@ namespace Tins { * \return QRType containing the value of the query response * field. */ - QRType type() { return static_cast(dns.qr); } + QRType type() const { return static_cast(dns.qr); } /** * \brief Setter for the opcode field. * * \return uint8_t containing the value of the opcode field. */ - uint8_t opcode() { return dns.opcode; } + uint8_t opcode() const { return dns.opcode; } /** * \brief Setter for the authoritative answer field. @@ -186,14 +186,14 @@ namespace Tins { * \return uint8_t containing the value of the authoritative * answer field. */ - uint8_t authoritative_answer() { return dns.aa; } + uint8_t authoritative_answer() const { return dns.aa; } /** * \brief Setter for the truncated field. * * \return uint8_t containing the value of the truncated field. */ - uint8_t truncated() { return dns.tc; } + uint8_t truncated() const { return dns.tc; } /** * \brief Setter for the recursion desired field. @@ -201,7 +201,7 @@ namespace Tins { * \return uint8_t containing the value of the recursion * desired field. */ - uint8_t recursion_desired() { return dns.rd; } + uint8_t recursion_desired() const { return dns.rd; } /** * \brief Setter for the recursion available field. @@ -209,14 +209,14 @@ namespace Tins { * \return uint8_t containing the value of the recursion * available field. */ - uint8_t recursion_available() { return dns.ra; } + uint8_t recursion_available() const { return dns.ra; } /** * \brief Setter for the z desired field. * * \return uint8_t containing the value of the z field. */ - uint8_t z() { return dns.z; } + uint8_t z() const { return dns.z; } /** * \brief Setter for the authenticated data field. @@ -224,7 +224,7 @@ namespace Tins { * \return uint8_t containing the value of the authenticated * data field. */ - uint8_t authenticated_data() { return dns.ad; } + uint8_t authenticated_data() const { return dns.ad; } /** * \brief Setter for the checking disabled field. @@ -232,42 +232,42 @@ namespace Tins { * \return uint8_t containing the value of the checking * disabled field. */ - uint8_t checking_disabled() { return dns.cd; } + uint8_t checking_disabled() const { return dns.cd; } /** * \brief Setter for the rcode field. * * \return uint8_t containing the value of the rcode field. */ - uint8_t rcode() { return dns.rcode; } + uint8_t rcode() const { return dns.rcode; } /** * \brief Setter for the questions field. * * \return uint16_t containing the value of the questions field. */ - uint16_t questions() { return Utils::net_to_host_s(dns.questions); } + uint16_t questions() const { return Utils::net_to_host_s(dns.questions); } /** * \brief Setter for the answers field. * * \return uint16_t containing the value of the answers field. */ - uint16_t answers() { return Utils::net_to_host_s(dns.answers); } + uint16_t answers() const { return Utils::net_to_host_s(dns.answers); } /** * \brief Setter for the authority field. * * \return uint16_t containing the value of the authority field. */ - uint16_t authority() { return Utils::net_to_host_s(dns.authority); } + uint16_t authority() const { return Utils::net_to_host_s(dns.authority); } /** * \brief Setter for the additional field. * * \return uint16_t containing the value of the additional field. */ - uint16_t additional() { return Utils::net_to_host_s(dns.additional); } + uint16_t additional() const { return Utils::net_to_host_s(dns.additional); } /** * \brief Getter for the PDU's type. diff --git a/src/dns.cpp b/src/dns.cpp index 1421419..18a614c 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -136,7 +136,7 @@ uint32_t Tins::DNS::header_size() const { } void Tins::DNS::id(uint16_t new_id) { - dns.id = new_id; + dns.id = Utils::net_to_host_s(new_id); } void Tins::DNS::type(QRType new_qr) { @@ -406,7 +406,7 @@ void Tins::DNS::build_suffix_map() { void Tins::DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) { uint32_t i(0); while(i < sz) { - if(i) + if(i && ptr[i]) out.push_back('.'); if((ptr[i] & 0xc0)) { uint16_t index = Utils::net_to_host_s(*((uint16_t*)(ptr + i))); diff --git a/src/ip.cpp b/src/ip.cpp index 4df6bb6..12870cd 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -65,10 +65,11 @@ Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz) if(total_sz < head_len() * sizeof(uint32_t)) throw std::runtime_error(msg); buffer += head_len() * sizeof(uint32_t); + this->_options_size = 0; this->_padded_options_size = head_len() * sizeof(uint32_t) - sizeof(iphdr); /* While the end of the options is not reached read an option */ - while (total_sz && ptr_buffer < buffer && (*ptr_buffer != 0)) { + while (ptr_buffer < buffer && (*ptr_buffer != 0)) { IPOption opt_to_add; memcpy(&opt_to_add.type, ptr_buffer, sizeof(uint8_t)); ptr_buffer++; @@ -91,21 +92,24 @@ Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz) case DPS: case UMP: case QS: - if(!total_sz || *ptr_buffer == 0) + if(ptr_buffer == buffer || *ptr_buffer == 0) throw std::runtime_error(msg); + { const uint8_t data_size = *ptr_buffer - 1; if(data_size > 0) { - if(total_sz < data_size) + if(buffer - ptr_buffer < data_size) throw std::runtime_error(msg); opt_to_add.optional_data.assign(ptr_buffer, ptr_buffer + data_size); } } + ptr_buffer += opt_to_add.optional_data.size(); } this->_ip_options.push_back(opt_to_add); this->_options_size += opt_to_add.optional_data.size() + 1; } + // check this line PLX total_sz -= head_len() * sizeof(uint32_t); if (total_sz) { switch(_ip.protocol) { diff --git a/tests/src/dns.cpp b/tests/src/dns.cpp new file mode 100644 index 0000000..bf19b7c --- /dev/null +++ b/tests/src/dns.cpp @@ -0,0 +1,162 @@ +#include +#include +#include "dns.h" +#include "utils.h" + +using namespace Tins; + + +class DNSTest : public testing::Test { +public: + static const uint8_t expected_packet[]; + + void test_equals(const DNS &dns1, const DNS &dns2); + void test_equals(const DNS::Query &q1, const DNS::Query &q2); + void test_equals(const DNS::Resource &q1, const DNS::Resource &q2); +}; + +const uint8_t DNSTest::expected_packet[] = { + '\x00', '\x13', '\xd7', '\x9a', '\x00', '\x01', '\x00', '\x01', '\x00', '\x00', '\x00', '\x00', '\x03', 'w', 'w', 'w', '\x07', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '\x03', 'c', 'o', 'm', '\x00', '\x00', '\x01', '\x00', '\x01', '\x03', 'w', 'w', 'w', '\x07', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '\x03', 'c', 'o', 'm', '\x00', '\x00', '\x01', '\x00', '\x01', '\x00', '\x00', '\x12', '4', '\x00', '\x04', '\xc0', '\xa8', '\x00', '\x01' +}; + + + +void DNSTest::test_equals(const DNS &dns1, const DNS &dns2) { + EXPECT_EQ(dns1.id(), dns2.id()); + EXPECT_EQ(dns1.type(), dns2.type()); + EXPECT_EQ(dns1.opcode(), dns2.opcode()); + EXPECT_EQ(dns1.authoritative_answer(), dns2.authoritative_answer()); + EXPECT_EQ(dns1.truncated(), dns2.truncated()); + EXPECT_EQ(dns1.recursion_desired(), dns2.recursion_desired()); + EXPECT_EQ(dns1.recursion_available(), dns2.recursion_available()); + EXPECT_EQ(dns1.z(), dns2.z()); + EXPECT_EQ(dns1.authenticated_data(), dns2.authenticated_data()); + EXPECT_EQ(dns1.checking_disabled(), dns2.checking_disabled()); + EXPECT_EQ(dns1.rcode(), dns2.rcode()); + EXPECT_EQ(dns1.questions(), dns2.questions()); + EXPECT_EQ(dns1.answers(), dns2.answers()); + EXPECT_EQ(dns1.authority(), dns2.authority()); + EXPECT_EQ(dns1.additional(), dns2.additional()); + EXPECT_EQ(dns1.pdu_type(), dns2.pdu_type()); + EXPECT_EQ(dns1.header_size(), dns2.header_size()); +} + +void DNSTest::test_equals(const DNS::Query &q1, const DNS::Query &q2) { + EXPECT_EQ(q1.name, q2.name); + EXPECT_EQ(q1.type, q2.type); + EXPECT_EQ(q1.qclass, q2.qclass); +} + +void DNSTest::test_equals(const DNS::Resource &q1, const DNS::Resource &q2) { + EXPECT_EQ(q1.dname, q2.dname); + EXPECT_EQ(q1.addr, q2.addr); + EXPECT_EQ(q1.type, q2.type); + EXPECT_EQ(q1.qclass, q2.qclass); + EXPECT_EQ(q1.ttl, q2.ttl); +} + +TEST_F(DNSTest, ConstructorFromBuffer) { + DNS dns(expected_packet, sizeof(expected_packet)); + // id=0x13, qr=1, opcode=0xa, aa=1, tc=1, rd=1, ra=1, z=0, rcode=0xa + EXPECT_EQ(dns.id(), 0x13); + EXPECT_EQ(dns.type(), DNS::RESPONSE); + EXPECT_EQ(dns.opcode(), 0xa); + EXPECT_EQ(dns.authoritative_answer(), 1); + EXPECT_EQ(dns.truncated(), 1); + EXPECT_EQ(dns.recursion_desired(), 1); + EXPECT_EQ(dns.recursion_available(), 1); + EXPECT_EQ(dns.z(), 0); + EXPECT_EQ(dns.rcode(), 0xa); + EXPECT_EQ(dns.questions(), 1); + EXPECT_EQ(dns.answers(), 1); + + std::list queries = dns.dns_queries(); + ASSERT_EQ(queries.size(), 1); + test_equals(queries.front(), DNS::Query("www.example.com", DNS::A, DNS::IN)); + + std::list answers = dns.dns_answers(); + ASSERT_EQ(answers.size(), 1); + test_equals(answers.front(), DNS::Resource("www.example.com", "192.168.0.1", DNS::A, DNS::IN, 0x1234)); +} + +TEST_F(DNSTest, ID) { + DNS dns; + dns.id(0x7263); + EXPECT_EQ(dns.id(), 0x7263); +} + +TEST_F(DNSTest, Type) { + DNS dns; + dns.type(DNS::RESPONSE); + EXPECT_EQ(dns.type(), DNS::RESPONSE); +} + +TEST_F(DNSTest, Opcode) { + DNS dns; + dns.opcode(0xa); + EXPECT_EQ(dns.opcode(), 0xa); +} + +TEST_F(DNSTest, AuthoritativeAnswer) { + DNS dns; + dns.authoritative_answer(1); + EXPECT_EQ(dns.authoritative_answer(), 1); +} + +TEST_F(DNSTest, Truncated) { + DNS dns; + dns.truncated(1); + EXPECT_EQ(dns.truncated(), 1); +} + +TEST_F(DNSTest, RecursionDesired) { + DNS dns; + dns.recursion_desired(1); + EXPECT_EQ(dns.recursion_desired(), 1); +} + +TEST_F(DNSTest, RecursionAvailable) { + DNS dns; + dns.recursion_available(1); + EXPECT_EQ(dns.recursion_available(), 1); +} + +TEST_F(DNSTest, Z) { + DNS dns; + dns.z(1); + EXPECT_EQ(dns.z(), 1); +} + +TEST_F(DNSTest, AuthenticatedData) { + DNS dns; + dns.authenticated_data(1); + EXPECT_EQ(dns.authenticated_data(), 1); +} + +TEST_F(DNSTest, CheckingDisabled) { + DNS dns; + dns.checking_disabled(1); + EXPECT_EQ(dns.checking_disabled(), 1); +} + +TEST_F(DNSTest, RCode) { + DNS dns; + dns.rcode(0xa); + EXPECT_EQ(dns.rcode(), 0xa); +} + +TEST_F(DNSTest, Question) { + DNS dns; + dns.add_query("www.example.com", DNS::A, DNS::IN); + dns.add_query("www.example2.com", DNS::MX, DNS::IN); + EXPECT_EQ(dns.questions(), 2); +} + +TEST_F(DNSTest, Answers) { + DNS dns; + dns.add_answer("www.example.com", DNS::A, DNS::IN, 0x762, Utils::ip_to_int("127.0.0.1")); + dns.add_answer("www.example2.com", DNS::MX, DNS::IN, 0x762, Utils::ip_to_int("127.0.0.1")); + EXPECT_EQ(dns.answers(), 2); +} + +