- Sun Jun 28, 2015 11:23 am
#21907
blackie wrote:i think the question is in the buffer, so it would be a part of the response.
_udp.write(_buffer, _currentPacketSize);
Edit:
I have it working on Windows.
Code: Select allvoid DNSServer::replyWithIP()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
// _dnsHeader->QDCount = 0;
_dnsHeader->RA = 1; //added
_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();
}
Blackies above code fixes invalid DNS response for Android!!!
blackie wrote:The code I posted above for replyWithIP() fixes the issue with every platform I have tested so far. Windows, OSX, Android
There is still an issue with the DNS response packet created. Dig reports the answer coming back in the "additional", but it should be the "answer" section.
Code: Select allC:\tmp\BIND9.10.2-P1.x64>dig test.com
; <<>> DiG 9.10.2-P1 <<>> test.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53101
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;test.com. IN A
;; ADDITIONAL SECTION:
test.com. 300 IN A 192.168.4.1
;; Query time: 165 msec
;; SERVER: 192.168.4.1#53(192.168.4.1)
;; WHEN: Fri Jun 26 15:21:46 Eastern Daylight Time 2015
;; MSG SIZE rcvd: 53
Blackie, apologies, I did not see your edit with new code change...
Thank you very much for this!!!Burkmurry and others, I can confirm that Blackies code change, which I quoted above works for Android and iOS and returns correct DNS response. In order to make Android go to Captive portal login I added Blackies code change plus the following in setup
server.on("/generate_204", handle_root); for the webserver
I am posting my full code again, with android captive portal addition (works on all OS woot)
Code: Select all#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
const char* ssid = "esp8266";
boolean LEDstate[] = {LOW, false, LOW};
const char* html = "<html><head><title>Success</title><style>.bt{display:block;width:250px;height:100px;padding:10px;margin:10px;"
"text-align:center;border-radius:5px;color:white;font-weight:bold;font-size:70px;text-decoration:none;} "
"body{background:#000;} .r{background:#933;} .g{background:#363;} .y{background:#EE0;height:100px;"
"width:100px;border-radius:50px;} .b{background:#000;height:100px;width:100px;border-radius:50px;} "
".a{font-size:35px;} td{vertical-align:middle;}</style>"
"</head><body><table><tr><td><div class='TGT0'></div></td><td><a class='bt g' href='/L0?v=1'>ON</a></td>"
"<td><a class='bt r' href='/L0?v=0'>OFF</a></td></tr><tr><td><div class='TGT2'></div></td><td>"
"<a class='bt g' href='/L2?v=1'>ON</a></td><td><a class='bt r' href='/L2?v=0'>OFF</a></td></tr>"
"<tr><td> </td><td><a class='bt g a' href='/ALL?v=1'><br/>ALL ON</a></td><td>"
"<a class='bt r a' href='/ALL?v=0'><br/>ALL OFF</a></td></tr></body></html>";
const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
IPAddress netMsk(255, 255, 255, 0);
DNSServer dnsServer;
ESP8266WebServer server(80);
void setup() {
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(2, LEDstate[0]);
digitalWrite(2, LEDstate[2]);
Serial.begin(115200);
Serial.setDebugOutput(true);
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, netMsk);
WiFi.softAP(ssid);
Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", apIP);
Serial.println("USP Server started");
server.on("/", handle_root);
server.on("/generate_204", handle_root); //Android captive portal
server.on("/L0", handle_L0);
server.on("/L2", handle_L2);
server.on("/ALL", handle_ALL);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
dnsServer.processNextRequest();
server.handleClient();
}
void handleNotFound() {
Serial.print("\t\t\t\t URI Not Found: ");
Serial.println(server.uri());
server.send ( 200, "text/plain", "URI Not Found" );
}
void handle_root() {
Serial.println("Page served");
String toSend = html;
toSend.replace("TGT0", LEDstate[0] ? "y" : "b");
toSend.replace("TGT2", LEDstate[2] ? "y" : "b");
server.send(200, "text/html", toSend);
delay(100);
}
void handle_L0() {
change_states(0);
handle_root();
}
void handle_L2() {
change_states(2);
handle_root();
}
void handle_ALL() {
change_states(0);
change_states(2);
handle_root();
}
void change_states(int tgt) {
if (server.hasArg("v")) {
int state = server.arg("v").toInt() == 1;
Serial.print("LED");
Serial.print(tgt);
Serial.print("=");
Serial.println(state);
LEDstate[tgt] = state ? HIGH : LOW;
digitalWrite(tgt, LEDstate[tgt]);
}
}
Some tweaks may still be needed. I noticed repeated page loads under andriod, makes it think sign in failed...So I guess adding some sort of confirm as Burkmurry mentioned would fix that...But as it stands, it will auto open captive portal login for all OS