summaryrefslogtreecommitdiff
path: root/Userland/Services/LookupServer
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@serenityos.org>2021-02-14 15:10:39 +0300
committerAndreas Kling <kling@serenityos.org>2021-02-15 09:14:42 +0100
commit42bc5f2cc19c5c528aed8902bb8a48e902da025f (patch)
tree4ab3109bd2957b82efde621ea8483fd7159111ef /Userland/Services/LookupServer
parentae1e82fd2f307ed49586c1bfc35f9f2fb30c8942 (diff)
downloadserenity-42bc5f2cc19c5c528aed8902bb8a48e902da025f.zip
LookupServer: Move parse_dns_name() -> DNSName::parse()
While at it, refactor it slightly.
Diffstat (limited to 'Userland/Services/LookupServer')
-rw-r--r--Userland/Services/LookupServer/DNSName.cpp33
-rw-r--r--Userland/Services/LookupServer/DNSName.h4
-rw-r--r--Userland/Services/LookupServer/DNSPacket.cpp39
3 files changed, 41 insertions, 35 deletions
diff --git a/Userland/Services/LookupServer/DNSName.cpp b/Userland/Services/LookupServer/DNSName.cpp
index 7385868076..ce9ad68f56 100644
--- a/Userland/Services/LookupServer/DNSName.cpp
+++ b/Userland/Services/LookupServer/DNSName.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Sergey Bugaev <bugaevc@serenityos.org>
* All rights reserved.
*
@@ -36,4 +37,36 @@ DNSName::DNSName(const String& name)
m_name = name;
}
+DNSName DNSName::parse(const u8* data, size_t& offset, size_t max_offset, size_t recursion_level)
+{
+ if (recursion_level > 4)
+ return DNSName({});
+
+ StringBuilder builder;
+ while (true) {
+ if (offset >= max_offset)
+ return DNSName({});
+ u8 b = data[offset++];
+ if (b == '\0') {
+ // This terminates the name.
+ return builder.to_string();
+ } else if ((b & 0xc0) == 0xc0) {
+ // The two bytes tell us the offset when to continue from.
+ if (offset >= max_offset)
+ return DNSName({});
+ size_t dummy = (b & 0x3f) << 8 | data[offset++];
+ auto rest_of_name = parse(data, dummy, max_offset, recursion_level + 1);
+ builder.append(rest_of_name.as_string());
+ return builder.to_string();
+ } else {
+ // This is the length of a part.
+ if (offset + b >= max_offset)
+ return DNSName({});
+ builder.append((const char*)&data[offset], (size_t)b);
+ builder.append('.');
+ offset += b;
+ }
+ }
+}
+
}
diff --git a/Userland/Services/LookupServer/DNSName.h b/Userland/Services/LookupServer/DNSName.h
index 20f1c91fba..21d1b88e47 100644
--- a/Userland/Services/LookupServer/DNSName.h
+++ b/Userland/Services/LookupServer/DNSName.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Sergey Bugaev <bugaevc@serenityos.org>
* All rights reserved.
*
@@ -33,6 +34,9 @@ namespace LookupServer {
class DNSName {
public:
DNSName(const String&);
+
+ static DNSName parse(const u8* data, size_t& offset, size_t max_offset, size_t recursion_level = 0);
+
const String& as_string() const { return m_name; }
private:
diff --git a/Userland/Services/LookupServer/DNSPacket.cpp b/Userland/Services/LookupServer/DNSPacket.cpp
index 6248318640..0bf84d5ac3 100644
--- a/Userland/Services/LookupServer/DNSPacket.cpp
+++ b/Userland/Services/LookupServer/DNSPacket.cpp
@@ -26,6 +26,7 @@
*/
#include "DNSPacket.h"
+#include "DNSName.h"
#include "DNSPacketHeader.h"
#include <AK/IPv4Address.h>
#include <AK/MemoryStream.h>
@@ -108,8 +109,6 @@ ByteBuffer DNSPacket::to_byte_buffer() const
return stream.copy_into_contiguous_buffer();
}
-static String parse_dns_name(const u8* data, size_t& offset, size_t max_offset, size_t recursion_level = 0);
-
class [[gnu::packed]] DNSRecordWithoutName {
public:
DNSRecordWithoutName() { }
@@ -159,7 +158,7 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
size_t offset = sizeof(DNSPacketHeader);
for (u16 i = 0; i < header.question_count(); i++) {
- auto name = parse_dns_name(raw_data, offset, raw_size);
+ auto name = DNSName::parse(raw_data, offset, raw_size);
struct RawDNSAnswerQuestion {
NetworkOrdered<u16> record_type;
NetworkOrdered<u16> class_code;
@@ -174,7 +173,7 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
}
for (u16 i = 0; i < header.answer_count(); ++i) {
- auto name = parse_dns_name(raw_data, offset, raw_size);
+ auto name = DNSName::parse(raw_data, offset, raw_size);
auto& record = *(const DNSRecordWithoutName*)(&raw_data[offset]);
@@ -184,7 +183,7 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
if (record.type() == T_PTR) {
size_t dummy_offset = offset;
- data = parse_dns_name(raw_data, dummy_offset, raw_size);
+ data = DNSName::parse(raw_data, dummy_offset, raw_size).as_string();
} else if (record.type() == T_A) {
data = { record.data(), record.data_length() };
} else {
@@ -201,34 +200,4 @@ Optional<DNSPacket> DNSPacket::from_raw_packet(const u8* raw_data, size_t raw_si
return packet;
}
-String parse_dns_name(const u8* data, size_t& offset, size_t max_offset, size_t recursion_level)
-{
- if (recursion_level > 4)
- return {};
- Vector<char, 128> buf;
- while (offset < max_offset) {
- u8 ch = data[offset];
- if (ch == '\0') {
- ++offset;
- break;
- }
- if ((ch & 0xc0) == 0xc0) {
- if ((offset + 1) >= max_offset)
- return {};
- size_t dummy = (ch & 0x3f) << 8 | data[offset + 1];
- offset += 2;
- StringBuilder builder;
- builder.append(buf.data(), buf.size());
- auto okay = parse_dns_name(data, dummy, max_offset, recursion_level + 1);
- builder.append(okay);
- return builder.to_string();
- }
- for (size_t i = 0; i < ch; ++i)
- buf.append(data[offset + i + 1]);
- buf.append('.');
- offset += ch + 1;
- }
- return String::copy(buf);
-}
-
}