1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-12 01:53:07 +03:00

Added a DNSServer library

This commit is contained in:
Kristijan Novoselic
2015-06-06 22:12:18 +02:00
committed by Ivan Grokhotkov
parent 533b6c184b
commit c570d0f593
5 changed files with 263 additions and 18 deletions

View File

@ -0,0 +1,133 @@
#include "DNSServer.h"
#include <lwip/def.h>
#include <Arduino.h>
DNSServer::DNSServer()
{
_ttl = htonl(60);
_errorReplyCode = DNSReplyCode::NonExistentDomain;
}
bool DNSServer::start(const uint16_t &port, const String &domainName,
const IPAddress &resolvedIP)
{
_port = port;
_domainName = domainName;
_resolvedIP[0] = resolvedIP[0];
_resolvedIP[1] = resolvedIP[1];
_resolvedIP[2] = resolvedIP[2];
_resolvedIP[3] = resolvedIP[3];
downcaseAndRemoveWwwPrefix(_domainName);
return _udp.begin(_port) == 1;
}
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
{
_errorReplyCode = replyCode;
}
void DNSServer::setTTL(const uint32_t &ttl)
{
_ttl = htonl(ttl);
}
void DNSServer::stop()
{
_udp.stop();
}
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
{
domainName.toLowerCase();
domainName.replace("www.", "");
}
void DNSServer::processNextRequest()
{
_currentPacketSize = _udp.parsePacket();
if (_currentPacketSize)
{
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
_udp.read(_buffer, _currentPacketSize);
_dnsHeader = (DNSHeader*) _buffer;
if (_dnsHeader->QR == DNS_QR_QUERY &&
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
requestIncludesOnlyOneQuestion() &&
getDomainNameWithoutWwwPrefix() == _domainName)
{
replyWithIP();
}
else if (_dnsHeader->QR == DNS_QR_QUERY)
{
replyWithCustomCode();
}
free(_buffer);
}
}
bool DNSServer::requestIncludesOnlyOneQuestion()
{
return ntohs(_dnsHeader->QDCount) == 1 &&
_dnsHeader->ANCount == 0 &&
_dnsHeader->NSCount == 0 &&
_dnsHeader->ARCount == 0;
}
String DNSServer::getDomainNameWithoutWwwPrefix()
{
String parsedDomainName = "";
unsigned char *start = _buffer + 12;
if (*start == 0)
{
return parsedDomainName;
}
int pos = 0;
while(true)
{
unsigned char labelLength = *(start + pos);
for(int i = 0; i < labelLength; i++)
{
pos++;
parsedDomainName += (char)*(start + pos);
}
pos++;
if (*(start + pos) == 0)
{
downcaseAndRemoveWwwPrefix(parsedDomainName);
return parsedDomainName;
}
else
{
parsedDomainName += ".";
}
}
}
void DNSServer::replyWithIP()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
_dnsHeader->QDCount = 0;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, _currentPacketSize);
_udp.write((unsigned char*)&_ttl, 4);
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
_udp.write((uint8_t)0);
_udp.write((uint8_t)4);
_udp.write(_resolvedIP, sizeof(_resolvedIP));
_udp.endPacket();
}
void DNSServer::replyWithCustomCode()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
_dnsHeader->QDCount = 0;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, sizeof(DNSHeader));
_udp.endPacket();
}

View File

@ -0,0 +1,72 @@
#ifndef DNSServer_h
#define DNSServer_h
#include <WiFiUdp.h>
#define DNS_QR_QUERY 0
#define DNS_QR_RESPONSE 1
#define DNS_OPCODE_QUERY 0
enum class DNSReplyCode
{
NoError = 0,
FormError = 1,
ServerFailure = 2,
NonExistentDomain = 3,
NotImplemented = 4,
Refused = 5,
YXDomain = 6,
YXRRSet = 7,
NXRRSet = 8
};
struct DNSHeader
{
uint16_t ID; // identification number
unsigned char RD : 1; // recursion desired
unsigned char TC : 1; // truncated message
unsigned char AA : 1; // authoritive answer
unsigned char OPCode : 4; // message_type
unsigned char QR : 1; // query/response flag
unsigned char RCode : 4; // response code
unsigned char Z : 3; // its z! reserved
unsigned char RA : 1; // recursion available
uint16_t QDCount; // number of question entries
uint16_t ANCount; // number of answer entries
uint16_t NSCount; // number of authority entries
uint16_t ARCount; // number of resource entries
};
class DNSServer
{
public:
DNSServer();
void processNextRequest();
void setErrorReplyCode(const DNSReplyCode &replyCode);
void setTTL(const uint32_t &ttl);
// Returns true if successful, false if there are no sockets available
bool start(const uint16_t &port,
const String &domainName,
const IPAddress &resolvedIP);
// stops the DNS server
void stop();
private:
WiFiUDP _udp;
uint16_t _port;
String _domainName;
unsigned char _resolvedIP[4];
int _currentPacketSize;
unsigned char* _buffer;
DNSHeader* _dnsHeader;
uint32_t _ttl;
DNSReplyCode _errorReplyCode;
void downcaseAndRemoveWwwPrefix(String &domainName);
String getDomainNameWithoutWwwPrefix();
bool requestIncludesOnlyOneQuestion();
void replyWithIP();
void replyWithCustomCode();
};
#endif