diff --git a/src/dns.cpp b/src/dns.cpp index c351c1e..d8ecfa4 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -224,9 +224,17 @@ DNSResourceRecord DNS::make_record(const std::string &name, const DNSResourceRecord::info &info, const uint8_t *ptr, uint32_t len) { string nm; + std::basic_string data; parse_domain_name(name, nm); uint16_t index = find_domain_name(nm); DNSResourceRecord res; + if(info.type == MX) { + data.push_back(0); + data.push_back(0); + data.insert(data.end(), ptr, ptr + len); + ptr = &data[0]; + len = data.size(); + } if(index) res = make_offseted_record(Endian::host_to_be(index), ptr, len); else @@ -437,25 +445,36 @@ void DNS::convert_resources(const ResourcesType &lst, std::list &res) } ptr = it->data_ptr(); sz = it->data_size(); - if(sz == 4) - addr = IPv4Address(*(uint32_t*)ptr).to_string(); - else { - if(Endian::be_to_host(it->information().type) == MX) { - ptr += 2; - sz -= 2; - } - if(Endian::be_to_host(it->information().type) == DNS::AAAA) { + uint16_t record_type = Endian::be_to_host(it->information().type); + // Skip the preference field if it's MX + if(record_type == MX) { + ptr += 2; + sz -= 2; + } + switch(record_type) { + case AAAA: if(sz != 16) - throw std::runtime_error("Malformed IPv6 address"); + throw malformed_packet(); addr = IPv6Address(ptr).to_string(); - } - else if(Endian::be_to_host(it->information().type) <= NSEC3PARAM) + break; + case A: + if(sz != 4) + throw malformed_packet(); + addr = IPv4Address(*(uint32_t*)ptr).to_string(); + break; + case NS: + case CNAME: + case DNAM: + case PTR: + case MX: compose_name(ptr, sz, addr); - else + break; + default: addr.assign(ptr, ptr + sz); + break; } res.push_back( - Resource(dname, addr, Endian::be_to_host(it->information().type), + Resource(dname, addr, record_type, Endian::host_to_be(it->information().qclass), Endian::be_to_host(it->information().ttl) ) diff --git a/tests/src/dns.cpp b/tests/src/dns.cpp index 35f2bc6..dbf0143 100644 --- a/tests/src/dns.cpp +++ b/tests/src/dns.cpp @@ -204,7 +204,7 @@ 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), IPv4Address("127.0.0.1")); + dns.add_answer("www.example2.com", DNS::make_info(DNS::MX, DNS::IN, 0x762), std::string("mail.example.com")); ASSERT_EQ(dns.answers_count(), 2); DNS::resources_type resources = dns.answers(); @@ -219,7 +219,7 @@ TEST_F(DNSTest, Answers) { else if(it->dname() == "www.example2.com") { EXPECT_EQ(it->type(), DNS::MX); EXPECT_EQ(it->ttl(), 0x762); - EXPECT_EQ(it->data(), "127.0.0.1"); + EXPECT_EQ(it->data(), "mail.example.com"); EXPECT_EQ(it->query_class(), DNS::IN); } }