mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
LibDNS: Prefer spans over raw pointers when parsing DNS packets
This means we don't have to keep track of the pointer and size separately.
This commit is contained in:
parent
c1d7a51391
commit
4e3b59a4bb
|
@ -21,14 +21,14 @@ Name::Name(DeprecatedString const& name)
|
||||||
m_name = name;
|
m_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Name Name::parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level)
|
Name Name::parse(ReadonlyBytes data, size_t& offset, size_t recursion_level)
|
||||||
{
|
{
|
||||||
if (recursion_level > 4)
|
if (recursion_level > 4)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (offset >= max_offset)
|
if (offset >= data.size())
|
||||||
return {};
|
return {};
|
||||||
u8 b = data[offset++];
|
u8 b = data[offset++];
|
||||||
if (b == '\0') {
|
if (b == '\0') {
|
||||||
|
@ -36,17 +36,17 @@ Name Name::parse(u8 const* data, size_t& offset, size_t max_offset, size_t recur
|
||||||
return builder.to_deprecated_string();
|
return builder.to_deprecated_string();
|
||||||
} else if ((b & 0xc0) == 0xc0) {
|
} else if ((b & 0xc0) == 0xc0) {
|
||||||
// The two bytes tell us the offset when to continue from.
|
// The two bytes tell us the offset when to continue from.
|
||||||
if (offset >= max_offset)
|
if (offset >= data.size())
|
||||||
return {};
|
return {};
|
||||||
size_t dummy = (b & 0x3f) << 8 | data[offset++];
|
size_t dummy = (b & 0x3f) << 8 | data[offset++];
|
||||||
auto rest_of_name = parse(data, dummy, max_offset, recursion_level + 1);
|
auto rest_of_name = parse(data, dummy, recursion_level + 1);
|
||||||
builder.append(rest_of_name.as_string());
|
builder.append(rest_of_name.as_string());
|
||||||
return builder.to_deprecated_string();
|
return builder.to_deprecated_string();
|
||||||
} else {
|
} else {
|
||||||
// This is the length of a part.
|
// This is the length of a part.
|
||||||
if (offset + b >= max_offset)
|
if (offset + b >= data.size())
|
||||||
return {};
|
return {};
|
||||||
builder.append((char const*)&data[offset], (size_t)b);
|
builder.append({ data.offset_pointer(offset), b });
|
||||||
builder.append('.');
|
builder.append('.');
|
||||||
offset += b;
|
offset += b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
Name() = default;
|
Name() = default;
|
||||||
Name(DeprecatedString const&);
|
Name(DeprecatedString const&);
|
||||||
|
|
||||||
static Name parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level = 0);
|
static Name parse(ReadonlyBytes data, size_t& offset, size_t recursion_level = 0);
|
||||||
|
|
||||||
size_t serialized_size() const;
|
size_t serialized_size() const;
|
||||||
DeprecatedString const& as_string() const { return m_name; }
|
DeprecatedString const& as_string() const { return m_name; }
|
||||||
|
|
|
@ -97,14 +97,14 @@ private:
|
||||||
|
|
||||||
static_assert(sizeof(DNSRecordWithoutName) == 10);
|
static_assert(sizeof(DNSRecordWithoutName) == 10);
|
||||||
|
|
||||||
Optional<Packet> Packet::from_raw_packet(u8 const* raw_data, size_t raw_size)
|
Optional<Packet> Packet::from_raw_packet(ReadonlyBytes bytes)
|
||||||
{
|
{
|
||||||
if (raw_size < sizeof(PacketHeader)) {
|
if (bytes.size() < sizeof(PacketHeader)) {
|
||||||
dbgln("DNS response not large enough ({} out of {}) to be a DNS packet.", raw_size, sizeof(PacketHeader));
|
dbgln("DNS response not large enough ({} out of {}) to be a DNS packet.", bytes.size(), sizeof(PacketHeader));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& header = *(PacketHeader const*)(raw_data);
|
auto const& header = *bit_cast<PacketHeader const*>(bytes.data());
|
||||||
dbgln_if(LOOKUPSERVER_DEBUG, "Got packet (ID: {})", header.id());
|
dbgln_if(LOOKUPSERVER_DEBUG, "Got packet (ID: {})", header.id());
|
||||||
dbgln_if(LOOKUPSERVER_DEBUG, " Question count: {}", header.question_count());
|
dbgln_if(LOOKUPSERVER_DEBUG, " Question count: {}", header.question_count());
|
||||||
dbgln_if(LOOKUPSERVER_DEBUG, " Answer count: {}", header.answer_count());
|
dbgln_if(LOOKUPSERVER_DEBUG, " Answer count: {}", header.answer_count());
|
||||||
|
@ -123,12 +123,12 @@ Optional<Packet> Packet::from_raw_packet(u8 const* raw_data, size_t raw_size)
|
||||||
size_t offset = sizeof(PacketHeader);
|
size_t offset = sizeof(PacketHeader);
|
||||||
|
|
||||||
for (u16 i = 0; i < header.question_count(); i++) {
|
for (u16 i = 0; i < header.question_count(); i++) {
|
||||||
auto name = Name::parse(raw_data, offset, raw_size);
|
auto name = Name::parse(bytes, offset);
|
||||||
struct RawDNSAnswerQuestion {
|
struct RawDNSAnswerQuestion {
|
||||||
NetworkOrdered<u16> record_type;
|
NetworkOrdered<u16> record_type;
|
||||||
NetworkOrdered<u16> class_code;
|
NetworkOrdered<u16> class_code;
|
||||||
};
|
};
|
||||||
auto& record_and_class = *(RawDNSAnswerQuestion const*)&raw_data[offset];
|
auto const& record_and_class = *bit_cast<RawDNSAnswerQuestion const*>(bytes.offset_pointer(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, (RecordType)(u16)record_and_class.record_type, (RecordClass)class_code, mdns_wants_unicast_response);
|
packet.m_questions.empend(name, (RecordType)(u16)record_and_class.record_type, (RecordClass)class_code, mdns_wants_unicast_response);
|
||||||
|
@ -138,18 +138,16 @@ Optional<Packet> Packet::from_raw_packet(u8 const* raw_data, size_t raw_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u16 i = 0; i < header.answer_count(); ++i) {
|
for (u16 i = 0; i < header.answer_count(); ++i) {
|
||||||
auto name = Name::parse(raw_data, offset, raw_size);
|
auto name = Name::parse(bytes, offset);
|
||||||
|
auto const& record = *bit_cast<DNSRecordWithoutName const*>(bytes.offset_pointer(offset));
|
||||||
auto& record = *(DNSRecordWithoutName const*)(&raw_data[offset]);
|
offset += sizeof(DNSRecordWithoutName);
|
||||||
|
|
||||||
DeprecatedString data;
|
DeprecatedString data;
|
||||||
|
|
||||||
offset += sizeof(DNSRecordWithoutName);
|
|
||||||
|
|
||||||
switch ((RecordType)record.type()) {
|
switch ((RecordType)record.type()) {
|
||||||
case RecordType::PTR: {
|
case RecordType::PTR: {
|
||||||
size_t dummy_offset = offset;
|
size_t dummy_offset = offset;
|
||||||
data = Name::parse(raw_data, dummy_offset, raw_size).as_string();
|
data = Name::parse(bytes, dummy_offset).as_string();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RecordType::CNAME:
|
case RecordType::CNAME:
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Packet {
|
||||||
public:
|
public:
|
||||||
Packet() = default;
|
Packet() = default;
|
||||||
|
|
||||||
static Optional<Packet> from_raw_packet(u8 const*, size_t);
|
static Optional<Packet> from_raw_packet(ReadonlyBytes bytes);
|
||||||
ErrorOr<ByteBuffer> to_byte_buffer() const;
|
ErrorOr<ByteBuffer> to_byte_buffer() const;
|
||||||
|
|
||||||
bool is_query() const { return !m_query_or_response; }
|
bool is_query() const { return !m_query_or_response; }
|
||||||
|
|
|
@ -29,7 +29,7 @@ ErrorOr<void> DNSServer::handle_client()
|
||||||
{
|
{
|
||||||
sockaddr_in client_address;
|
sockaddr_in client_address;
|
||||||
auto buffer = TRY(receive(1024, client_address));
|
auto buffer = TRY(receive(1024, client_address));
|
||||||
auto optional_request = Packet::from_raw_packet(buffer.data(), buffer.size());
|
auto optional_request = Packet::from_raw_packet(buffer);
|
||||||
if (!optional_request.has_value()) {
|
if (!optional_request.has_value()) {
|
||||||
dbgln("Got an invalid DNS packet");
|
dbgln("Got an invalid DNS packet");
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -263,13 +263,13 @@ ErrorOr<Vector<Answer>> LookupServer::lookup(Name const& name, DeprecatedString
|
||||||
TRY(udp_socket->write_until_depleted(buffer));
|
TRY(udp_socket->write_until_depleted(buffer));
|
||||||
|
|
||||||
u8 response_buffer[4096];
|
u8 response_buffer[4096];
|
||||||
int nrecv = TRY(udp_socket->read_some({ response_buffer, sizeof(response_buffer) })).size();
|
auto nrecv = TRY(udp_socket->read_some({ response_buffer, sizeof(response_buffer) })).size();
|
||||||
if (udp_socket->is_eof())
|
if (udp_socket->is_eof())
|
||||||
return Vector<Answer> {};
|
return Vector<Answer> {};
|
||||||
|
|
||||||
did_get_response = true;
|
did_get_response = true;
|
||||||
|
|
||||||
auto o_response = Packet::from_raw_packet(response_buffer, nrecv);
|
auto o_response = Packet::from_raw_packet({ response_buffer, nrecv });
|
||||||
if (!o_response.has_value())
|
if (!o_response.has_value())
|
||||||
return Vector<Answer> {};
|
return Vector<Answer> {};
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ MulticastDNS::MulticastDNS(Core::EventReceiver* parent)
|
||||||
ErrorOr<void> MulticastDNS::handle_packet()
|
ErrorOr<void> MulticastDNS::handle_packet()
|
||||||
{
|
{
|
||||||
auto buffer = TRY(receive(1024));
|
auto buffer = TRY(receive(1024));
|
||||||
auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size());
|
auto optional_packet = Packet::from_raw_packet(buffer);
|
||||||
if (!optional_packet.has_value()) {
|
if (!optional_packet.has_value()) {
|
||||||
dbgln("Got an invalid mDNS packet");
|
dbgln("Got an invalid mDNS packet");
|
||||||
return {};
|
return {};
|
||||||
|
@ -175,7 +175,7 @@ ErrorOr<Vector<Answer>> MulticastDNS::lookup(Name const& name, RecordType record
|
||||||
auto buffer = TRY(receive(1024));
|
auto buffer = TRY(receive(1024));
|
||||||
if (buffer.is_empty())
|
if (buffer.is_empty())
|
||||||
return Vector<Answer> {};
|
return Vector<Answer> {};
|
||||||
auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size());
|
auto optional_packet = Packet::from_raw_packet(buffer);
|
||||||
if (!optional_packet.has_value()) {
|
if (!optional_packet.has_value()) {
|
||||||
dbgln("Got an invalid mDNS packet");
|
dbgln("Got an invalid mDNS packet");
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue