summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2016-05-23 17:48:51 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2016-05-23 17:48:51 +0200
commitd93f727e82c38e51ebc645456a44208042e54b8c (patch)
tree5468306e4daec16265162a7fa797e4cd4a9173d9
downloadportal-d93f727e82c38e51ebc645456a44208042e54b8c.tar.gz
portal-d93f727e82c38e51ebc645456a44208042e54b8c.zip
first commitHEADmaster
-rw-r--r--portal.ino233
1 files changed, 233 insertions, 0 deletions
diff --git a/portal.ino b/portal.ino
new file mode 100644
index 0000000..b688a6b
--- /dev/null
+++ b/portal.ino
@@ -0,0 +1,233 @@
+/* Portal */
+#include <ESP8266WiFi.h>
+#include <ESP8266WebServer.h>
+#include <WiFiUdp.h>
+
+
+/* DNSServer.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();
+
+ // Returns true if successful, false if there are no sockets available
+ bool start(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;
+
+ bool requestIncludesOnlyOneQuestion();
+ String getDomainName();
+ void replyWithIP();
+};
+/* end DNSServer.h */
+
+
+/* main code */
+
+DNSServer dns;
+ESP8266WebServer server(80);
+
+#define LOGLENGTH 50
+String domainlog[LOGLENGTH];
+int logptr = 0;
+
+void logDomain(String requestUrl) {
+ if (++logptr == LOGLENGTH) {
+ logptr = 0;
+ }
+ domainlog[logptr] = requestUrl;
+}
+
+void serve() {
+ String answer = "";
+ for (int i=0; i<logptr; i++) {
+ answer.concat(domainlog[i]);
+ answer += "\n";
+ }
+ server.send(200, "text/plain", answer);
+}
+
+void setup() {
+ WiFi.softAP("Portal");
+ IPAddress ip = WiFi.softAPIP();
+
+ dns.start(ip);
+
+ server.onNotFound(serve);
+ server.begin();
+}
+
+void loop() {
+ dns.processNextRequest();
+ server.handleClient();
+}
+
+/* end main code */
+
+
+/* modified DNSServer.cpp */
+
+#include <lwip/def.h>
+#include <Arduino.h>
+
+DNSServer::DNSServer()
+{
+ _ttl = htonl(600);
+ _errorReplyCode = DNSReplyCode::NonExistentDomain;
+}
+
+bool DNSServer::start(const IPAddress &resolvedIP)
+{
+ _port = 53;
+ _buffer = NULL;
+ _resolvedIP[0] = resolvedIP[0];
+ _resolvedIP[1] = resolvedIP[1];
+ _resolvedIP[2] = resolvedIP[2];
+ _resolvedIP[3] = resolvedIP[3];
+ return _udp.begin(_port) == 1;
+}
+
+void DNSServer::stop()
+{
+ _udp.stop();
+ free(_buffer);
+ _buffer = NULL;
+}
+
+void DNSServer::processNextRequest()
+{
+ _currentPacketSize = _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 &&
+ _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
+ requestIncludesOnlyOneQuestion())
+ {
+ logDomain(getDomainName());
+ replyWithIP(); // reply with the same ip regardless of request
+ }
+ }
+}
+
+String DNSServer::getDomainName()
+{
+ String parsedDomainName = "";
+ if (_buffer == NULL) return 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)
+ {
+ return parsedDomainName;
+ }
+ else
+ {
+ parsedDomainName += ".";
+ }
+ }
+}
+
+bool DNSServer::requestIncludesOnlyOneQuestion()
+{
+ return ntohs(_dnsHeader->QDCount) == 1 &&
+ _dnsHeader->ANCount == 0 &&
+ _dnsHeader->NSCount == 0 &&
+ _dnsHeader->ARCount == 0;
+}
+
+void DNSServer::replyWithIP()
+{
+ if (_buffer == NULL) return;
+ _dnsHeader->QR = DNS_QR_RESPONSE;
+ _dnsHeader->ANCount = _dnsHeader->QDCount;
+ _dnsHeader->QDCount = _dnsHeader->QDCount;
+ //_dnsHeader->RA = 1;
+
+ _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
+ _udp.write(_buffer, _currentPacketSize);
+
+ _udp.write((uint8_t)192); // answer name is a pointer
+ _udp.write((uint8_t)12); // pointer to offset at 0x00c
+
+ _udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
+ _udp.write((uint8_t)1);
+
+ _udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
+ _udp.write((uint8_t)1);
+
+ _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();
+}
+
+/* end DNSServer.cpp */