Full DNS decoding

"Full" :)
This commit is contained in:
Baptiste Wicht 2016-09-11 16:18:30 +02:00
parent f34b92ff36
commit 9374fded2d
3 changed files with 101 additions and 4 deletions

View File

@ -20,6 +20,7 @@ namespace ip {
address ip32_to_ip(uint32_t raw);
uint32_t ip_to_ip32(address ip);
std::string ip_to_str(address ip);
struct header {
uint8_t version_ihl;

View File

@ -52,6 +52,32 @@ void prepare_packet_query(network::ethernet::packet& packet, uint16_t identifica
packet.index += sizeof(network::dns::header);
}
std::string decode_domain(char* payload, size_t& offset){
std::string domain;
offset = 0;
while(true){
auto label_size = static_cast<uint8_t>(*(payload + offset));
++offset;
if(!label_size){
break;
}
if(!domain.empty()){
domain += '.';
}
for(size_t i = 0; i < label_size; ++i){
domain += *(payload + offset);
++offset;
}
}
return domain;
}
} //end of anonymous namespace
void network::dns::decode(network::interface_descriptor& /*interface*/, network::ethernet::packet& packet){
@ -73,8 +99,6 @@ void network::dns::decode(network::interface_descriptor& /*interface*/, network:
logging::logf(logging::log_level::TRACE, "dns: Authorithy RRs %u \n", size_t(authority_rrs));
logging::logf(logging::log_level::TRACE, "dns: Additional RRs %u \n", size_t(additional_rrs));
auto flags = dns_header->flags;
if(*flag_qr(&dns_header->flags)){
logging::logf(logging::log_level::TRACE, "dns: Query\n");
} else {
@ -82,6 +106,68 @@ void network::dns::decode(network::interface_descriptor& /*interface*/, network:
if(response_code == 0x0){
logging::logf(logging::log_level::TRACE, "dns: Response OK\n");
auto* payload = packet.payload + packet.index + sizeof(header);
// Decode the questions (simply wrap around it)
for(size_t i = 0; i < questions; ++i){
size_t length;
auto domain = decode_domain(payload, length);
payload += length;
auto rr_type = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
payload += 2;
auto rr_class = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
payload += 2;
logging::logf(logging::log_level::TRACE, "dns: Query %u Type %u Class %u Name %s\n", i, rr_type, rr_class, domain.c_str());
}
for(size_t i = 0; i < answers; ++i){
auto label = static_cast<uint8_t>(*payload);
std::string domain;
if(label > 64){
// This is a pointer
auto pointer = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
auto offset = pointer & (0xFFFF >> 2);
payload += 2;
size_t ignored;
domain = decode_domain(packet.payload + packet.index + offset, ignored);
} else {
logging::logf(logging::log_level::TRACE, "dns: Unable to handle non-compressed data\n");
return;
}
auto rr_type = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
payload += 2;
auto rr_class = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
payload += 2;
auto ttl = switch_endian_32(*reinterpret_cast<uint32_t*>(payload));
payload += 4;
auto rd_length = switch_endian_16(*reinterpret_cast<uint16_t*>(payload));
payload += 2;
if(rr_type == 0x1 && rr_class == 0x1){
auto ip = network::ip::ip32_to_ip(*reinterpret_cast<uint32_t*>(payload));
auto ip_str = network::ip::ip_to_str(ip);
logging::logf(logging::log_level::TRACE, "dns: Answer %u Domain %s Type %u Class %u TTL %u IP: %s\n", i, domain.c_str(), rr_type, rr_class, ttl, ip_str.c_str());
} else {
logging::logf(logging::log_level::TRACE, "dns: Answer %u Domain %s Type %u Class %u TTL %u \n", i, rr_type, rr_class, ttl, domain.c_str());
logging::logf(logging::log_level::TRACE, "dns: Answer %u Unable to read data for type and class\n", i);
}
payload += rd_length;
}
} else if(response_code == 0x1){
logging::logf(logging::log_level::TRACE, "dns: Format Error\n");
} else if(response_code == 0x2){
@ -94,8 +180,6 @@ void network::dns::decode(network::interface_descriptor& /*interface*/, network:
logging::logf(logging::log_level::TRACE, "dns: Refused\n");
}
}
//TODO
}
std::expected<network::ethernet::packet> network::dns::prepare_packet_query(network::interface_descriptor& interface, network::ip::address target_ip, uint16_t source_port, uint16_t identification, size_t payload_size){

View File

@ -72,6 +72,18 @@ uint32_t network::ip::ip_to_ip32(address ip){
return switch_endian_32(ip.raw_address);
}
std::string network::ip::ip_to_str(address ip){
std::string value;
value += std::to_string(ip(0));
value += '.';
value += std::to_string(ip(1));
value += '.';
value += std::to_string(ip(2));
value += '.';
value += std::to_string(ip(3));
return value;
}
void network::ip::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){
packet.tag(1, packet.index);