mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Added a DNSServer library
This commit is contained in:
parent
533b6c184b
commit
c570d0f593
@ -184,6 +184,11 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo
|
|||||||
Currently the library only works on STA interface, AP interface is not supported.
|
Currently the library only works on STA interface, AP interface is not supported.
|
||||||
See attached example and library README file for details.
|
See attached example and library README file for details.
|
||||||
|
|
||||||
|
#### DNS server (DNSServer library) ####
|
||||||
|
|
||||||
|
Implements a simple DNS server that can be used in both STA and AP modes. The DNS server currently supports only one domain (for all other domains it will reply with NXDOMAIN or custom status code). With it clients can open a web server running on ESP8266 using a domain name, not an IP address.
|
||||||
|
See attached example for details.
|
||||||
|
|
||||||
#### Servo ####
|
#### Servo ####
|
||||||
|
|
||||||
This library exposes the ability to control RC (hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servo counts above 12 will use Timer1 and features that use it will be effected.
|
This library exposes the ability to control RC (hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servo counts above 12 will use Timer1 and features that use it will be effected.
|
||||||
@ -306,5 +311,3 @@ Esptool written by Christian Klippel is licensed under GPLv2, currently maintain
|
|||||||
ESP8266 core support, ESP8266WiFi, Ticker, ESP8266WebServer libraries were written by Ivan Grokhotkov, ivan@esp8266.com.
|
ESP8266 core support, ESP8266WiFi, Ticker, ESP8266WebServer libraries were written by Ivan Grokhotkov, ivan@esp8266.com.
|
||||||
|
|
||||||
[SPI Flash File System (SPIFFS)](https://github.com/pellepl/spiffs) written by Peter Andersson is used in this project. It is distributed under MIT license.
|
[SPI Flash File System (SPIFFS)](https://github.com/pellepl/spiffs) written by Peter Andersson is used in this project. It is distributed under MIT license.
|
||||||
|
|
||||||
|
|
||||||
|
28
libraries/DNSServer/examples/DNSServer/DNSServer.ino
Normal file
28
libraries/DNSServer/examples/DNSServer/DNSServer.ino
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <DNSServer.h>
|
||||||
|
|
||||||
|
const byte DNS_PORT = 53;
|
||||||
|
IPAddress apIP(192, 168, 1, 1);
|
||||||
|
DNSServer dnsServer;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||||
|
WiFi.softAP("DNSServer example");
|
||||||
|
|
||||||
|
// modify TTL associated with the domain name (in seconds)
|
||||||
|
// default is 60 seconds
|
||||||
|
dnsServer.setTTL(300);
|
||||||
|
// set which return code will be used for all other domains (e.g. sending
|
||||||
|
// ServerFailure instead of NonExistentDomain will reduce number of queries
|
||||||
|
// sent by clients)
|
||||||
|
// default is DNSReplyCode::NonExistentDomain
|
||||||
|
dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
|
||||||
|
|
||||||
|
//start DNS server for a specific domain name
|
||||||
|
dnsServer.start(DNS_PORT, "www.example.com", apIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
dnsServer.processNextRequest();
|
||||||
|
}
|
9
libraries/DNSServer/library.properties
Normal file
9
libraries/DNSServer/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=DNSServer
|
||||||
|
version=1.0.0
|
||||||
|
author=Kristijan Novoselić
|
||||||
|
maintainer=Kristijan Novoselić, <kristijan.novoselic@gmail.com>
|
||||||
|
sentence=A simple DNS server for ESP8266.
|
||||||
|
paragraph=This library implements a simple DNS server.
|
||||||
|
category=Communication
|
||||||
|
url=
|
||||||
|
architectures=esp8266
|
133
libraries/DNSServer/src/DNSServer.cpp
Normal file
133
libraries/DNSServer/src/DNSServer.cpp
Normal 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();
|
||||||
|
}
|
72
libraries/DNSServer/src/DNSServer.h
Normal file
72
libraries/DNSServer/src/DNSServer.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user