mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-14 15:06:52 -04:00
Full DNS decoding
"Full" :)
This commit is contained in:
parent
f34b92ff36
commit
9374fded2d
@ -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;
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user