1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 05:57:44 +00:00

LookupServer: Turn #defines into enum classes and add formatter

This commit is contained in:
Gunnar Beutner 2021-05-07 23:58:51 +02:00 committed by Andreas Kling
parent 6e70888315
commit 7b3bed7910
11 changed files with 120 additions and 49 deletions

View file

@ -30,7 +30,7 @@ void ClientConnection::die()
Messages::LookupServer::LookupNameResponse ClientConnection::lookup_name(String const& name) Messages::LookupServer::LookupNameResponse ClientConnection::lookup_name(String const& name)
{ {
auto answers = LookupServer::the().lookup(name, T_A); auto answers = LookupServer::the().lookup(name, DNSRecordType::A);
if (answers.is_empty()) if (answers.is_empty())
return { 1, Vector<String>() }; return { 1, Vector<String>() };
Vector<String> addresses; Vector<String> addresses;
@ -50,7 +50,7 @@ Messages::LookupServer::LookupAddressResponse ClientConnection::lookup_address(S
ip_address[2], ip_address[2],
ip_address[1], ip_address[1],
ip_address[0]); ip_address[0]);
auto answers = LookupServer::the().lookup(name, T_PTR); auto answers = LookupServer::the().lookup(name, DNSRecordType::PTR);
if (answers.is_empty()) if (answers.is_empty())
return { 1, String() }; return { 1, String() };
return { 0, answers[0].record_data() }; return { 0, answers[0].record_data() };

View file

@ -5,11 +5,12 @@
*/ */
#include "DNSAnswer.h" #include "DNSAnswer.h"
#include <AK/Stream.h>
#include <time.h> #include <time.h>
namespace LookupServer { namespace LookupServer {
DNSAnswer::DNSAnswer(const DNSName& name, u16 type, u16 class_code, u32 ttl, const String& record_data, bool mdns_cache_flush) DNSAnswer::DNSAnswer(const DNSName& name, DNSRecordType type, DNSRecordClass class_code, u32 ttl, const String& record_data, bool mdns_cache_flush)
: m_name(name) : m_name(name)
, m_type(type) , m_type(type)
, m_class_code(class_code) , m_class_code(class_code)
@ -29,3 +30,42 @@ bool DNSAnswer::has_expired() const
} }
} }
void AK::Formatter<LookupServer::DNSRecordType>::format(AK::FormatBuilder& builder, LookupServer::DNSRecordType value)
{
switch (value) {
case LookupServer::DNSRecordType::A:
builder.put_string("A");
return;
case LookupServer::DNSRecordType::NS:
builder.put_string("NS");
return;
case LookupServer::DNSRecordType::CNAME:
builder.put_string("CNAME");
return;
case LookupServer::DNSRecordType::SOA:
builder.put_string("SOA");
return;
case LookupServer::DNSRecordType::PTR:
builder.put_string("PTR");
return;
case LookupServer::DNSRecordType::MX:
builder.put_string("MX");
return;
}
builder.put_string("DNS record type ");
builder.put_u64((u16)value);
}
void AK::Formatter<LookupServer::DNSRecordClass>::format(AK::FormatBuilder& builder, LookupServer::DNSRecordClass value)
{
switch (value) {
case LookupServer::DNSRecordClass::IN:
builder.put_string("IN");
return;
}
builder.put_string("DNS record class ");
builder.put_u64((u16)value);
}

View file

@ -7,21 +7,35 @@
#pragma once #pragma once
#include "DNSName.h" #include "DNSName.h"
#include <AK/Format.h>
#include <AK/String.h> #include <AK/String.h>
#include <AK/Types.h> #include <AK/Types.h>
namespace LookupServer { namespace LookupServer {
enum class DNSRecordType : u16 {
A = 1,
NS = 2,
CNAME = 5,
SOA = 6,
PTR = 12,
MX = 15,
};
enum class DNSRecordClass : u16 {
IN = 1
};
#define MDNS_CACHE_FLUSH 0x8000 #define MDNS_CACHE_FLUSH 0x8000
class DNSAnswer { class DNSAnswer {
public: public:
DNSAnswer(const DNSName& name, u16 type, u16 class_code, u32 ttl, const String& record_data, bool mdns_cache_flush); DNSAnswer(const DNSName& name, DNSRecordType type, DNSRecordClass class_code, u32 ttl, const String& record_data, bool mdns_cache_flush);
const DNSName& name() const { return m_name; } const DNSName& name() const { return m_name; }
u16 type() const { return m_type; } DNSRecordType type() const { return m_type; }
u16 class_code() const { return m_class_code; } DNSRecordClass class_code() const { return m_class_code; }
u16 raw_class_code() const { return m_class_code | (m_mdns_cache_flush ? MDNS_CACHE_FLUSH : 0); } u16 raw_class_code() const { return (u16)m_class_code | (m_mdns_cache_flush ? MDNS_CACHE_FLUSH : 0); }
u32 ttl() const { return m_ttl; } u32 ttl() const { return m_ttl; }
const String& record_data() const { return m_record_data; } const String& record_data() const { return m_record_data; }
bool mdns_cache_flush() const { return m_mdns_cache_flush; } bool mdns_cache_flush() const { return m_mdns_cache_flush; }
@ -30,8 +44,8 @@ public:
private: private:
DNSName m_name; DNSName m_name;
u16 m_type { 0 }; DNSRecordType m_type { 0 };
u16 m_class_code { 0 }; DNSRecordClass m_class_code { 0 };
u32 m_ttl { 0 }; u32 m_ttl { 0 };
time_t m_expiration_time { 0 }; time_t m_expiration_time { 0 };
String m_record_data; String m_record_data;
@ -39,3 +53,24 @@ private:
}; };
} }
template<>
struct AK::Formatter<LookupServer::DNSRecordType> : StandardFormatter {
Formatter() = default;
explicit Formatter(StandardFormatter formatter)
: StandardFormatter(formatter)
{
}
void format(AK::FormatBuilder&, LookupServer::DNSRecordType);
};
template<>
struct AK::Formatter<LookupServer::DNSRecordClass> : StandardFormatter {
Formatter() = default;
explicit Formatter(StandardFormatter formatter)
: StandardFormatter(formatter)
{
}
void format(AK::FormatBuilder&, LookupServer::DNSRecordClass);
};

View file

@ -55,15 +55,15 @@ ByteBuffer DNSPacket::to_byte_buffer() const
stream << ReadonlyBytes { &header, sizeof(header) }; stream << ReadonlyBytes { &header, sizeof(header) };
for (auto& question : m_questions) { for (auto& question : m_questions) {
stream << question.name(); stream << question.name();
stream << htons(question.record_type()); stream << htons((u16)question.record_type());
stream << htons(question.raw_class_code()); stream << htons(question.raw_class_code());
} }
for (auto& answer : m_answers) { for (auto& answer : m_answers) {
stream << answer.name(); stream << answer.name();
stream << htons(answer.type()); stream << htons((u16)answer.type());
stream << htons(answer.raw_class_code()); stream << htons(answer.raw_class_code());
stream << htonl(answer.ttl()); stream << htonl(answer.ttl());
if (answer.type() == T_PTR) { if (answer.type() == DNSRecordType::PTR) {
DNSName name { answer.record_data() }; DNSName name { answer.record_data() };
stream << htons(name.serialized_size()); stream << htons(name.serialized_size());
stream << name; stream << name;
@ -131,7 +131,7 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
auto& record_and_class = *(const RawDNSAnswerQuestion*)&raw_data[offset]; auto& record_and_class = *(const RawDNSAnswerQuestion*)&raw_data[offset];
u16 class_code = record_and_class.class_code & ~MDNS_WANTS_UNICAST_RESPONSE; u16 class_code = record_and_class.class_code & ~MDNS_WANTS_UNICAST_RESPONSE;
bool mdns_wants_unicast_response = record_and_class.class_code & MDNS_WANTS_UNICAST_RESPONSE; bool mdns_wants_unicast_response = record_and_class.class_code & MDNS_WANTS_UNICAST_RESPONSE;
packet.m_questions.empend(name, record_and_class.record_type, class_code, mdns_wants_unicast_response); packet.m_questions.empend(name, (DNSRecordType)(u16)record_and_class.record_type, (DNSRecordClass)class_code, mdns_wants_unicast_response);
offset += 4; offset += 4;
auto& question = packet.m_questions.last(); auto& question = packet.m_questions.last();
dbgln_if(LOOKUPSERVER_DEBUG, "Question #{}: name=_{}_, type={}, class={}", i, question.name(), question.record_type(), question.class_code()); dbgln_if(LOOKUPSERVER_DEBUG, "Question #{}: name=_{}_, type={}, class={}", i, question.name(), question.record_type(), question.class_code());
@ -146,19 +146,24 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
offset += sizeof(DNSRecordWithoutName); offset += sizeof(DNSRecordWithoutName);
if (record.type() == T_PTR) { switch ((DNSRecordType)record.type()) {
case DNSRecordType::PTR: {
size_t dummy_offset = offset; size_t dummy_offset = offset;
data = DNSName::parse(raw_data, dummy_offset, raw_size).as_string(); data = DNSName::parse(raw_data, dummy_offset, raw_size).as_string();
} else if (record.type() == T_A) { break;
data = { record.data(), record.data_length() };
} else {
// FIXME: Parse some other record types perhaps?
dbgln("data=(unimplemented record type {})", record.type());
} }
case DNSRecordType::A:
data = { record.data(), record.data_length() };
break;
default:
// FIXME: Parse some other record types perhaps?
dbgln("data=(unimplemented record type {})", (u16)record.type());
}
dbgln_if(LOOKUPSERVER_DEBUG, "Answer #{}: name=_{}_, type={}, ttl={}, length={}, data=_{}_", i, name, record.type(), record.ttl(), record.data_length(), data); dbgln_if(LOOKUPSERVER_DEBUG, "Answer #{}: name=_{}_, type={}, ttl={}, length={}, data=_{}_", i, name, record.type(), record.ttl(), record.data_length(), data);
u16 class_code = record.record_class() & ~MDNS_CACHE_FLUSH; u16 class_code = record.record_class() & ~MDNS_CACHE_FLUSH;
bool mdns_cache_flush = record.record_class() & MDNS_CACHE_FLUSH; bool mdns_cache_flush = record.record_class() & MDNS_CACHE_FLUSH;
packet.m_answers.empend(name, record.type(), class_code, record.ttl(), data, mdns_cache_flush); packet.m_answers.empend(name, (DNSRecordType)record.type(), (DNSRecordClass)class_code, record.ttl(), data, mdns_cache_flush);
offset += record.data_length(); offset += record.data_length();
} }

View file

@ -13,15 +13,6 @@
#include <AK/Types.h> #include <AK/Types.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#define T_A 1
#define T_NS 2
#define T_CNAME 5
#define T_SOA 6
#define T_PTR 12
#define T_MX 15
#define C_IN 1
namespace LookupServer { namespace LookupServer {
enum class ShouldRandomizeCase { enum class ShouldRandomizeCase {

View file

@ -15,7 +15,7 @@ namespace LookupServer {
class DNSQuestion { class DNSQuestion {
public: public:
DNSQuestion(const DNSName& name, u16 record_type, u16 class_code, bool mdns_wants_unicast_response) DNSQuestion(const DNSName& name, DNSRecordType record_type, DNSRecordClass class_code, bool mdns_wants_unicast_response)
: m_name(name) : m_name(name)
, m_record_type(record_type) , m_record_type(record_type)
, m_class_code(class_code) , m_class_code(class_code)
@ -23,16 +23,16 @@ public:
{ {
} }
u16 record_type() const { return m_record_type; } DNSRecordType record_type() const { return m_record_type; }
u16 class_code() const { return m_class_code; } DNSRecordClass class_code() const { return m_class_code; }
u16 raw_class_code() const { return (u16)m_class_code | (m_mdns_wants_unicast_response ? MDNS_WANTS_UNICAST_RESPONSE : 0); } u16 raw_class_code() const { return (u16)m_class_code | (m_mdns_wants_unicast_response ? MDNS_WANTS_UNICAST_RESPONSE : 0); }
const DNSName& name() const { return m_name; } const DNSName& name() const { return m_name; }
bool mdns_wants_unicast_response() const { return m_mdns_wants_unicast_response; } bool mdns_wants_unicast_response() const { return m_mdns_wants_unicast_response; }
private: private:
DNSName m_name; DNSName m_name;
u16 m_record_type { 0 }; DNSRecordType m_record_type { 0 };
u16 m_class_code { 0 }; DNSRecordClass m_class_code { 0 };
bool m_mdns_wants_unicast_response { false }; bool m_mdns_wants_unicast_response { false };
}; };

View file

@ -43,7 +43,7 @@ void DNSServer::handle_client()
response.set_id(request.id()); response.set_id(request.id());
for (auto& question : request.questions()) { for (auto& question : request.questions()) {
if (question.class_code() != C_IN) if (question.class_code() != DNSRecordClass::IN)
continue; continue;
response.add_question(question); response.add_question(question);
auto answers = lookup_server.lookup(question.name(), question.record_type()); auto answers = lookup_server.lookup(question.name(), question.record_type());

View file

@ -69,13 +69,13 @@ void LookupServer::load_etc_hosts()
// The value here is 1 day. // The value here is 1 day.
static constexpr u32 static_ttl = 86400; static constexpr u32 static_ttl = 86400;
auto add_answer = [this](const DNSName& name, unsigned short record_type, String data) { auto add_answer = [this](const DNSName& name, DNSRecordType record_type, String data) {
auto it = m_etc_hosts.find(name); auto it = m_etc_hosts.find(name);
if (it == m_etc_hosts.end()) { if (it == m_etc_hosts.end()) {
m_etc_hosts.set(name, {}); m_etc_hosts.set(name, {});
it = m_etc_hosts.find(name); it = m_etc_hosts.find(name);
} }
it->value.empend(name, record_type, (u16)C_IN, static_ttl, data, false); it->value.empend(name, record_type, DNSRecordClass::IN, static_ttl, data, false);
}; };
auto file = Core::File::construct("/etc/hosts"); auto file = Core::File::construct("/etc/hosts");
@ -97,7 +97,7 @@ void LookupServer::load_etc_hosts()
auto raw_addr = addr.to_in_addr_t(); auto raw_addr = addr.to_in_addr_t();
DNSName name = fields[1]; DNSName name = fields[1];
add_answer(name, T_A, String { (const char*)&raw_addr, sizeof(raw_addr) }); add_answer(name, DNSRecordType::A, String { (const char*)&raw_addr, sizeof(raw_addr) });
IPv4Address reverse_addr { IPv4Address reverse_addr {
(u8)atoi(sections[3].characters()), (u8)atoi(sections[3].characters()),
@ -108,11 +108,11 @@ void LookupServer::load_etc_hosts()
StringBuilder builder; StringBuilder builder;
builder.append(reverse_addr.to_string()); builder.append(reverse_addr.to_string());
builder.append(".in-addr.arpa"); builder.append(".in-addr.arpa");
add_answer(builder.to_string(), T_PTR, name.as_string()); add_answer(builder.to_string(), DNSRecordType::PTR, name.as_string());
} }
} }
Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, unsigned short record_type) Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, DNSRecordType record_type)
{ {
dbgln_if(LOOKUPSERVER_DEBUG, "Got request for '{}'", name.as_string()); dbgln_if(LOOKUPSERVER_DEBUG, "Got request for '{}'", name.as_string());
@ -190,7 +190,7 @@ Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, unsigned short recor
return answers; return answers;
} }
Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, const String& nameserver, bool& did_get_response, unsigned short record_type, ShouldRandomizeCase should_randomize_case) Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, const String& nameserver, bool& did_get_response, DNSRecordType record_type, ShouldRandomizeCase should_randomize_case)
{ {
DNSPacket request; DNSPacket request;
request.set_is_query(); request.set_is_query();
@ -198,7 +198,7 @@ Vector<DNSAnswer> LookupServer::lookup(const DNSName& name, const String& namese
DNSName name_in_question = name; DNSName name_in_question = name;
if (should_randomize_case == ShouldRandomizeCase::Yes) if (should_randomize_case == ShouldRandomizeCase::Yes)
name_in_question.randomize_case(); name_in_question.randomize_case();
request.add_question({ name_in_question, record_type, C_IN, false }); request.add_question({ name_in_question, record_type, DNSRecordClass::IN, false });
auto buffer = request.to_byte_buffer(); auto buffer = request.to_byte_buffer();

View file

@ -21,7 +21,7 @@ class LookupServer final : public Core::Object {
public: public:
static LookupServer& the(); static LookupServer& the();
Vector<DNSAnswer> lookup(const DNSName& name, unsigned short record_type); Vector<DNSAnswer> lookup(const DNSName& name, DNSRecordType record_type);
private: private:
LookupServer(); LookupServer();
@ -29,7 +29,7 @@ private:
void load_etc_hosts(); void load_etc_hosts();
void put_in_cache(const DNSAnswer&); void put_in_cache(const DNSAnswer&);
Vector<DNSAnswer> lookup(const DNSName& hostname, const String& nameserver, bool& did_get_response, unsigned short record_type, ShouldRandomizeCase = ShouldRandomizeCase::Yes); Vector<DNSAnswer> lookup(const DNSName& hostname, const String& nameserver, bool& did_get_response, DNSRecordType record_type, ShouldRandomizeCase = ShouldRandomizeCase::Yes);
RefPtr<Core::LocalServer> m_local_server; RefPtr<Core::LocalServer> m_local_server;
RefPtr<DNSServer> m_dns_server; RefPtr<DNSServer> m_dns_server;

View file

@ -87,8 +87,8 @@ void MulticastDNS::announce()
auto raw_addr = address.to_in_addr_t(); auto raw_addr = address.to_in_addr_t();
DNSAnswer answer { DNSAnswer answer {
m_hostname, m_hostname,
T_A, DNSRecordType::A,
C_IN, DNSRecordClass::IN,
120, 120,
String { (const char*)&raw_addr, sizeof(raw_addr) }, String { (const char*)&raw_addr, sizeof(raw_addr) },
true, true,
@ -138,11 +138,11 @@ Vector<IPv4Address> MulticastDNS::local_addresses() const
return addresses; return addresses;
} }
Vector<DNSAnswer> MulticastDNS::lookup(const DNSName& name, unsigned short record_type) Vector<DNSAnswer> MulticastDNS::lookup(const DNSName& name, DNSRecordType record_type)
{ {
DNSPacket request; DNSPacket request;
request.set_is_query(); request.set_is_query();
request.add_question({ name, record_type, C_IN, false }); request.add_question({ name, record_type, DNSRecordClass::IN, false });
if (emit_packet(request) < 0) { if (emit_packet(request) < 0) {
perror("failed to emit request packet"); perror("failed to emit request packet");

View file

@ -18,7 +18,7 @@ namespace LookupServer {
class MulticastDNS : public Core::UDPServer { class MulticastDNS : public Core::UDPServer {
C_OBJECT(MulticastDNS) C_OBJECT(MulticastDNS)
public: public:
Vector<DNSAnswer> lookup(const DNSName&, unsigned short record_type); Vector<DNSAnswer> lookup(const DNSName&, DNSRecordType record_type);
private: private:
explicit MulticastDNS(Object* parent = nullptr); explicit MulticastDNS(Object* parent = nullptr);