Skip to content

Commit 656bf14

Browse files
Makunaearlephilhower
authored andcommitted
Dns server cleanup (#5194)
Clean up the DNSServer class. Removed member variables that are not required outside a member call lifetime, and add destructor/checks. Fixes #5179
1 parent 1de0c34 commit 656bf14

File tree

4 files changed

+96
-67
lines changed

4 files changed

+96
-67
lines changed

Diff for: libraries/DNSServer/keywords.txt

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ stop KEYWORD2
3333
DNS_QR_QUERY LITERAL1 RESERVED_WORD_2
3434
DNS_QR_RESPONSE LITERAL1 RESERVED_WORD_2
3535
DNS_OPCODE_QUERY LITERAL1 RESERVED_WORD_2
36+
MAX_DNSNAME_LENGTH LITERAL1 RESERVED_WORD_2
3637
NoError LITERAL1 RESERVED_WORD_2
3738
FormError LITERAL1 RESERVED_WORD_2
3839
ServerFailure LITERAL1 RESERVED_WORD_2

Diff for: libraries/DNSServer/library.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=DNSServer
2-
version=1.1.0
2+
version=1.1.1
33
author=Kristijan Novoselić
44
maintainer=Kristijan Novoselić, <[email protected]>
55
sentence=A simple DNS server for ESP8266.

Diff for: libraries/DNSServer/src/DNSServer.cpp

+85-59
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName,
1313
const IPAddress &resolvedIP)
1414
{
1515
_port = port;
16-
_buffer = NULL;
16+
1717
_domainName = domainName;
1818
_resolvedIP[0] = resolvedIP[0];
1919
_resolvedIP[1] = resolvedIP[1];
@@ -36,8 +36,6 @@ void DNSServer::setTTL(const uint32_t &ttl)
3636
void DNSServer::stop()
3737
{
3838
_udp.stop();
39-
free(_buffer);
40-
_buffer = NULL;
4139
}
4240

4341
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
@@ -48,82 +46,106 @@ void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
4846

4947
void DNSServer::processNextRequest()
5048
{
51-
_currentPacketSize = _udp.parsePacket();
52-
if (_currentPacketSize)
49+
size_t packetSize = _udp.parsePacket();
50+
51+
if (packetSize >= sizeof(DNSHeader))
5352
{
54-
if (_buffer != NULL) free(_buffer);
55-
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
56-
if (_buffer == NULL) return;
57-
_udp.read(_buffer, _currentPacketSize);
58-
_dnsHeader = (DNSHeader*) _buffer;
59-
60-
if (_dnsHeader->QR == DNS_QR_QUERY &&
61-
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
62-
requestIncludesOnlyOneQuestion() &&
63-
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
53+
uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(packetSize));
54+
if (buffer == NULL) return;
55+
56+
_udp.read(buffer, packetSize);
57+
58+
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
59+
60+
if (dnsHeader->QR == DNS_QR_QUERY &&
61+
dnsHeader->OPCode == DNS_OPCODE_QUERY &&
62+
requestIncludesOnlyOneQuestion(dnsHeader) &&
63+
(_domainName == "*" || getDomainNameWithoutWwwPrefix(buffer, packetSize) == _domainName)
6464
)
6565
{
66-
replyWithIP();
66+
replyWithIP(buffer, packetSize);
6767
}
68-
else if (_dnsHeader->QR == DNS_QR_QUERY)
68+
else if (dnsHeader->QR == DNS_QR_QUERY)
6969
{
70-
replyWithCustomCode();
70+
replyWithCustomCode(buffer, packetSize);
7171
}
7272

73-
free(_buffer);
74-
_buffer = NULL;
73+
free(buffer);
7574
}
7675
}
7776

78-
bool DNSServer::requestIncludesOnlyOneQuestion()
77+
bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
7978
{
80-
return ntohs(_dnsHeader->QDCount) == 1 &&
81-
_dnsHeader->ANCount == 0 &&
82-
_dnsHeader->NSCount == 0 &&
83-
_dnsHeader->ARCount == 0;
79+
return ntohs(dnsHeader->QDCount) == 1 &&
80+
dnsHeader->ANCount == 0 &&
81+
dnsHeader->NSCount == 0 &&
82+
dnsHeader->ARCount == 0;
8483
}
8584

86-
String DNSServer::getDomainNameWithoutWwwPrefix()
85+
String DNSServer::getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize)
8786
{
88-
String parsedDomainName = "";
89-
if (_buffer == NULL) return parsedDomainName;
90-
unsigned char *start = _buffer + 12;
91-
if (*start == 0)
92-
{
93-
return parsedDomainName;
94-
}
95-
int pos = 0;
96-
while(true)
87+
String parsedDomainName;
88+
89+
const uint8_t* pos = buffer + sizeof(DNSHeader);
90+
const uint8_t* end = buffer + packetSize;
91+
92+
// to minimize reallocations due to concats below
93+
// we reserve enough space that a median or average domain
94+
// name size cold be easily contained without a reallocation
95+
// - max size would be 253, in 2013, average is 11 and max was 42
96+
//
97+
parsedDomainName.reserve(32);
98+
99+
uint8_t labelLength = *pos;
100+
101+
while (true)
97102
{
98-
unsigned char labelLength = *(start + pos);
99-
for(int i = 0; i < labelLength; i++)
103+
if (labelLength == 0)
104+
{
105+
// no more labels
106+
downcaseAndRemoveWwwPrefix(parsedDomainName);
107+
return parsedDomainName;
108+
}
109+
110+
// append next label
111+
for (int i = 0; i < labelLength && pos < end; i++)
100112
{
101113
pos++;
102-
parsedDomainName += (char)*(start + pos);
114+
parsedDomainName += static_cast<char>(*pos);
103115
}
104-
pos++;
105-
if (*(start + pos) == 0)
116+
117+
if (pos >= end)
106118
{
107-
downcaseAndRemoveWwwPrefix(parsedDomainName);
108-
return parsedDomainName;
119+
// malformed packet, return an empty domain name
120+
parsedDomainName = "";
121+
return parsedDomainName;
109122
}
110123
else
111124
{
112-
parsedDomainName += ".";
125+
// next label
126+
pos++;
127+
labelLength = *pos;
128+
129+
// if there is another label, add delimiter
130+
if (labelLength != 0)
131+
{
132+
parsedDomainName += ".";
133+
}
113134
}
114135
}
115136
}
116137

117-
void DNSServer::replyWithIP()
138+
void DNSServer::replyWithIP(uint8_t* buffer, size_t packetSize)
118139
{
119-
if (_buffer == NULL) return;
120-
_dnsHeader->QR = DNS_QR_RESPONSE;
121-
_dnsHeader->ANCount = _dnsHeader->QDCount;
122-
_dnsHeader->QDCount = _dnsHeader->QDCount;
123-
//_dnsHeader->RA = 1;
140+
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
141+
142+
dnsHeader->QR = DNS_QR_RESPONSE;
143+
dnsHeader->ANCount = dnsHeader->QDCount;
144+
dnsHeader->QDCount = dnsHeader->QDCount;
145+
//dnsHeader->RA = 1;
124146

125147
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
126-
_udp.write(_buffer, _currentPacketSize);
148+
_udp.write(buffer, packetSize);
127149

128150
_udp.write((uint8_t)192); // answer name is a pointer
129151
_udp.write((uint8_t)12); // pointer to offset at 0x00c
@@ -142,22 +164,26 @@ void DNSServer::replyWithIP()
142164
_udp.write(_resolvedIP, sizeof(_resolvedIP));
143165
_udp.endPacket();
144166

145-
146-
147167
#ifdef DEBUG_ESP_DNS
148168
DEBUG_ESP_PORT.printf("DNS responds: %s for %s\n",
149-
IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix().c_str() );
169+
IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix(buffer, packetSize).c_str() );
150170
#endif
151171
}
152172

153-
void DNSServer::replyWithCustomCode()
173+
void DNSServer::replyWithCustomCode(uint8_t* buffer, size_t packetSize)
154174
{
155-
if (_buffer == NULL) return;
156-
_dnsHeader->QR = DNS_QR_RESPONSE;
157-
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
158-
_dnsHeader->QDCount = 0;
175+
if (packetSize < sizeof(DNSHeader))
176+
{
177+
return;
178+
}
179+
180+
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
181+
182+
dnsHeader->QR = DNS_QR_RESPONSE;
183+
dnsHeader->RCode = (unsigned char)_errorReplyCode;
184+
dnsHeader->QDCount = 0;
159185

160186
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
161-
_udp.write(_buffer, sizeof(DNSHeader));
187+
_udp.write(buffer, sizeof(DNSHeader));
162188
_udp.endPacket();
163189
}

Diff for: libraries/DNSServer/src/DNSServer.h

+9-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define DNS_QR_RESPONSE 1
77
#define DNS_OPCODE_QUERY 0
88

9+
#define MAX_DNSNAME_LENGTH 253
10+
911
enum class DNSReplyCode
1012
{
1113
NoError = 0,
@@ -40,6 +42,9 @@ class DNSServer
4042
{
4143
public:
4244
DNSServer();
45+
~DNSServer() {
46+
stop();
47+
};
4348
void processNextRequest();
4449
void setErrorReplyCode(const DNSReplyCode &replyCode);
4550
void setTTL(const uint32_t &ttl);
@@ -56,16 +61,13 @@ class DNSServer
5661
uint16_t _port;
5762
String _domainName;
5863
unsigned char _resolvedIP[4];
59-
int _currentPacketSize;
60-
unsigned char* _buffer;
61-
DNSHeader* _dnsHeader;
6264
uint32_t _ttl;
6365
DNSReplyCode _errorReplyCode;
6466

6567
void downcaseAndRemoveWwwPrefix(String &domainName);
66-
String getDomainNameWithoutWwwPrefix();
67-
bool requestIncludesOnlyOneQuestion();
68-
void replyWithIP();
69-
void replyWithCustomCode();
68+
String getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize);
69+
bool requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader);
70+
void replyWithIP(uint8_t* buffer, size_t packetSize);
71+
void replyWithCustomCode(uint8_t* buffer, size_t packetSize);
7072
};
7173
#endif

0 commit comments

Comments
 (0)