diff --git a/kernel/include/net/ip_layer.hpp b/kernel/include/net/ip_layer.hpp index d83da009..8a3cbb0a 100644 --- a/kernel/include/net/ip_layer.hpp +++ b/kernel/include/net/ip_layer.hpp @@ -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; diff --git a/kernel/src/net/dns_layer.cpp b/kernel/src/net/dns_layer.cpp index 3837bd06..24431a9c 100644 --- a/kernel/src/net/dns_layer.cpp +++ b/kernel/src/net/dns_layer.cpp @@ -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(*(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(payload)); + payload += 2; + + auto rr_class = switch_endian_16(*reinterpret_cast(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(*payload); + + std::string domain; + if(label > 64){ + // This is a pointer + auto pointer = switch_endian_16(*reinterpret_cast(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(payload)); + payload += 2; + + auto rr_class = switch_endian_16(*reinterpret_cast(payload)); + payload += 2; + + auto ttl = switch_endian_32(*reinterpret_cast(payload)); + payload += 4; + + auto rd_length = switch_endian_16(*reinterpret_cast(payload)); + payload += 2; + + if(rr_type == 0x1 && rr_class == 0x1){ + auto ip = network::ip::ip32_to_ip(*reinterpret_cast(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::dns::prepare_packet_query(network::interface_descriptor& interface, network::ip::address target_ip, uint16_t source_port, uint16_t identification, size_t payload_size){ diff --git a/kernel/src/net/ip_layer.cpp b/kernel/src/net/ip_layer.cpp index 149ef3a2..86213129 100644 --- a/kernel/src/net/ip_layer.cpp +++ b/kernel/src/net/ip_layer.cpp @@ -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);