mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
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
This commit is contained in:
parent
1de0c341b5
commit
656bf146bc
@ -33,6 +33,7 @@ stop KEYWORD2
|
|||||||
DNS_QR_QUERY LITERAL1 RESERVED_WORD_2
|
DNS_QR_QUERY LITERAL1 RESERVED_WORD_2
|
||||||
DNS_QR_RESPONSE LITERAL1 RESERVED_WORD_2
|
DNS_QR_RESPONSE LITERAL1 RESERVED_WORD_2
|
||||||
DNS_OPCODE_QUERY LITERAL1 RESERVED_WORD_2
|
DNS_OPCODE_QUERY LITERAL1 RESERVED_WORD_2
|
||||||
|
MAX_DNSNAME_LENGTH LITERAL1 RESERVED_WORD_2
|
||||||
NoError LITERAL1 RESERVED_WORD_2
|
NoError LITERAL1 RESERVED_WORD_2
|
||||||
FormError LITERAL1 RESERVED_WORD_2
|
FormError LITERAL1 RESERVED_WORD_2
|
||||||
ServerFailure LITERAL1 RESERVED_WORD_2
|
ServerFailure LITERAL1 RESERVED_WORD_2
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name=DNSServer
|
name=DNSServer
|
||||||
version=1.1.0
|
version=1.1.1
|
||||||
author=Kristijan Novoselić
|
author=Kristijan Novoselić
|
||||||
maintainer=Kristijan Novoselić, <kristijan.novoselic@gmail.com>
|
maintainer=Kristijan Novoselić, <kristijan.novoselic@gmail.com>
|
||||||
sentence=A simple DNS server for ESP8266.
|
sentence=A simple DNS server for ESP8266.
|
||||||
|
@ -13,7 +13,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName,
|
|||||||
const IPAddress &resolvedIP)
|
const IPAddress &resolvedIP)
|
||||||
{
|
{
|
||||||
_port = port;
|
_port = port;
|
||||||
_buffer = NULL;
|
|
||||||
_domainName = domainName;
|
_domainName = domainName;
|
||||||
_resolvedIP[0] = resolvedIP[0];
|
_resolvedIP[0] = resolvedIP[0];
|
||||||
_resolvedIP[1] = resolvedIP[1];
|
_resolvedIP[1] = resolvedIP[1];
|
||||||
@ -36,8 +36,6 @@ void DNSServer::setTTL(const uint32_t &ttl)
|
|||||||
void DNSServer::stop()
|
void DNSServer::stop()
|
||||||
{
|
{
|
||||||
_udp.stop();
|
_udp.stop();
|
||||||
free(_buffer);
|
|
||||||
_buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
|
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
|
||||||
@ -48,82 +46,106 @@ void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
|
|||||||
|
|
||||||
void DNSServer::processNextRequest()
|
void DNSServer::processNextRequest()
|
||||||
{
|
{
|
||||||
_currentPacketSize = _udp.parsePacket();
|
size_t packetSize = _udp.parsePacket();
|
||||||
if (_currentPacketSize)
|
|
||||||
{
|
|
||||||
if (_buffer != NULL) free(_buffer);
|
|
||||||
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
|
|
||||||
if (_buffer == NULL) return;
|
|
||||||
_udp.read(_buffer, _currentPacketSize);
|
|
||||||
_dnsHeader = (DNSHeader*) _buffer;
|
|
||||||
|
|
||||||
if (_dnsHeader->QR == DNS_QR_QUERY &&
|
if (packetSize >= sizeof(DNSHeader))
|
||||||
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
|
{
|
||||||
requestIncludesOnlyOneQuestion() &&
|
uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(packetSize));
|
||||||
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
|
if (buffer == NULL) return;
|
||||||
|
|
||||||
|
_udp.read(buffer, packetSize);
|
||||||
|
|
||||||
|
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
|
||||||
|
|
||||||
|
if (dnsHeader->QR == DNS_QR_QUERY &&
|
||||||
|
dnsHeader->OPCode == DNS_OPCODE_QUERY &&
|
||||||
|
requestIncludesOnlyOneQuestion(dnsHeader) &&
|
||||||
|
(_domainName == "*" || getDomainNameWithoutWwwPrefix(buffer, packetSize) == _domainName)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
replyWithIP();
|
replyWithIP(buffer, packetSize);
|
||||||
}
|
}
|
||||||
else if (_dnsHeader->QR == DNS_QR_QUERY)
|
else if (dnsHeader->QR == DNS_QR_QUERY)
|
||||||
{
|
{
|
||||||
replyWithCustomCode();
|
replyWithCustomCode(buffer, packetSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(_buffer);
|
free(buffer);
|
||||||
_buffer = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DNSServer::requestIncludesOnlyOneQuestion()
|
bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
|
||||||
{
|
{
|
||||||
return ntohs(_dnsHeader->QDCount) == 1 &&
|
return ntohs(dnsHeader->QDCount) == 1 &&
|
||||||
_dnsHeader->ANCount == 0 &&
|
dnsHeader->ANCount == 0 &&
|
||||||
_dnsHeader->NSCount == 0 &&
|
dnsHeader->NSCount == 0 &&
|
||||||
_dnsHeader->ARCount == 0;
|
dnsHeader->ARCount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DNSServer::getDomainNameWithoutWwwPrefix()
|
String DNSServer::getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize)
|
||||||
{
|
{
|
||||||
String parsedDomainName = "";
|
String parsedDomainName;
|
||||||
if (_buffer == NULL) return parsedDomainName;
|
|
||||||
unsigned char *start = _buffer + 12;
|
const uint8_t* pos = buffer + sizeof(DNSHeader);
|
||||||
if (*start == 0)
|
const uint8_t* end = buffer + packetSize;
|
||||||
|
|
||||||
|
// to minimize reallocations due to concats below
|
||||||
|
// we reserve enough space that a median or average domain
|
||||||
|
// name size cold be easily contained without a reallocation
|
||||||
|
// - max size would be 253, in 2013, average is 11 and max was 42
|
||||||
|
//
|
||||||
|
parsedDomainName.reserve(32);
|
||||||
|
|
||||||
|
uint8_t labelLength = *pos;
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
return parsedDomainName;
|
if (labelLength == 0)
|
||||||
}
|
{
|
||||||
int pos = 0;
|
// no more labels
|
||||||
while(true)
|
downcaseAndRemoveWwwPrefix(parsedDomainName);
|
||||||
{
|
return parsedDomainName;
|
||||||
unsigned char labelLength = *(start + pos);
|
}
|
||||||
for(int i = 0; i < labelLength; i++)
|
|
||||||
|
// append next label
|
||||||
|
for (int i = 0; i < labelLength && pos < end; i++)
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
parsedDomainName += (char)*(start + pos);
|
parsedDomainName += static_cast<char>(*pos);
|
||||||
}
|
}
|
||||||
pos++;
|
|
||||||
if (*(start + pos) == 0)
|
if (pos >= end)
|
||||||
{
|
{
|
||||||
downcaseAndRemoveWwwPrefix(parsedDomainName);
|
// malformed packet, return an empty domain name
|
||||||
return parsedDomainName;
|
parsedDomainName = "";
|
||||||
|
return parsedDomainName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parsedDomainName += ".";
|
// next label
|
||||||
|
pos++;
|
||||||
|
labelLength = *pos;
|
||||||
|
|
||||||
|
// if there is another label, add delimiter
|
||||||
|
if (labelLength != 0)
|
||||||
|
{
|
||||||
|
parsedDomainName += ".";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::replyWithIP()
|
void DNSServer::replyWithIP(uint8_t* buffer, size_t packetSize)
|
||||||
{
|
{
|
||||||
if (_buffer == NULL) return;
|
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
|
||||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
|
||||||
_dnsHeader->ANCount = _dnsHeader->QDCount;
|
dnsHeader->QR = DNS_QR_RESPONSE;
|
||||||
_dnsHeader->QDCount = _dnsHeader->QDCount;
|
dnsHeader->ANCount = dnsHeader->QDCount;
|
||||||
//_dnsHeader->RA = 1;
|
dnsHeader->QDCount = dnsHeader->QDCount;
|
||||||
|
//dnsHeader->RA = 1;
|
||||||
|
|
||||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||||
_udp.write(_buffer, _currentPacketSize);
|
_udp.write(buffer, packetSize);
|
||||||
|
|
||||||
_udp.write((uint8_t)192); // answer name is a pointer
|
_udp.write((uint8_t)192); // answer name is a pointer
|
||||||
_udp.write((uint8_t)12); // pointer to offset at 0x00c
|
_udp.write((uint8_t)12); // pointer to offset at 0x00c
|
||||||
@ -142,22 +164,26 @@ void DNSServer::replyWithIP()
|
|||||||
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
||||||
_udp.endPacket();
|
_udp.endPacket();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_ESP_DNS
|
#ifdef DEBUG_ESP_DNS
|
||||||
DEBUG_ESP_PORT.printf("DNS responds: %s for %s\n",
|
DEBUG_ESP_PORT.printf("DNS responds: %s for %s\n",
|
||||||
IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix().c_str() );
|
IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix(buffer, packetSize).c_str() );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::replyWithCustomCode()
|
void DNSServer::replyWithCustomCode(uint8_t* buffer, size_t packetSize)
|
||||||
{
|
{
|
||||||
if (_buffer == NULL) return;
|
if (packetSize < sizeof(DNSHeader))
|
||||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
{
|
||||||
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
|
return;
|
||||||
_dnsHeader->QDCount = 0;
|
}
|
||||||
|
|
||||||
|
DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);
|
||||||
|
|
||||||
|
dnsHeader->QR = DNS_QR_RESPONSE;
|
||||||
|
dnsHeader->RCode = (unsigned char)_errorReplyCode;
|
||||||
|
dnsHeader->QDCount = 0;
|
||||||
|
|
||||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||||
_udp.write(_buffer, sizeof(DNSHeader));
|
_udp.write(buffer, sizeof(DNSHeader));
|
||||||
_udp.endPacket();
|
_udp.endPacket();
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#define DNS_QR_RESPONSE 1
|
#define DNS_QR_RESPONSE 1
|
||||||
#define DNS_OPCODE_QUERY 0
|
#define DNS_OPCODE_QUERY 0
|
||||||
|
|
||||||
|
#define MAX_DNSNAME_LENGTH 253
|
||||||
|
|
||||||
enum class DNSReplyCode
|
enum class DNSReplyCode
|
||||||
{
|
{
|
||||||
NoError = 0,
|
NoError = 0,
|
||||||
@ -40,6 +42,9 @@ class DNSServer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DNSServer();
|
DNSServer();
|
||||||
|
~DNSServer() {
|
||||||
|
stop();
|
||||||
|
};
|
||||||
void processNextRequest();
|
void processNextRequest();
|
||||||
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
||||||
void setTTL(const uint32_t &ttl);
|
void setTTL(const uint32_t &ttl);
|
||||||
@ -56,16 +61,13 @@ class DNSServer
|
|||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
String _domainName;
|
String _domainName;
|
||||||
unsigned char _resolvedIP[4];
|
unsigned char _resolvedIP[4];
|
||||||
int _currentPacketSize;
|
|
||||||
unsigned char* _buffer;
|
|
||||||
DNSHeader* _dnsHeader;
|
|
||||||
uint32_t _ttl;
|
uint32_t _ttl;
|
||||||
DNSReplyCode _errorReplyCode;
|
DNSReplyCode _errorReplyCode;
|
||||||
|
|
||||||
void downcaseAndRemoveWwwPrefix(String &domainName);
|
void downcaseAndRemoveWwwPrefix(String &domainName);
|
||||||
String getDomainNameWithoutWwwPrefix();
|
String getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize);
|
||||||
bool requestIncludesOnlyOneQuestion();
|
bool requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader);
|
||||||
void replyWithIP();
|
void replyWithIP(uint8_t* buffer, size_t packetSize);
|
||||||
void replyWithCustomCode();
|
void replyWithCustomCode(uint8_t* buffer, size_t packetSize);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
Loading…
x
Reference in New Issue
Block a user