11#define UDP_HEADER_SIZE 8
12#define DNS_HEADER_SIZE 12
15#define RESPONSE_FLAG (1<<15)
16#define QUERY_RESPONSE_MASK (1<<15)
17#define OPCODE_STANDARD_QUERY (0)
18#define OPCODE_INVERSE_QUERY (1<<11)
19#define OPCODE_STATUS_REQUEST (2<<11)
20#define OPCODE_MASK (15<<11)
21#define AUTHORITATIVE_FLAG (1<<10)
22#define TRUNCATION_FLAG (1<<9)
23#define RECURSION_DESIRED_FLAG (1<<8)
24#define RECURSION_AVAILABLE_FLAG (1<<7)
25#define RESP_NO_ERROR (0)
26#define RESP_FORMAT_ERROR (1)
27#define RESP_SERVER_FAILURE (2)
28#define RESP_NAME_ERROR (3)
29#define RESP_NOT_IMPLEMENTED (4)
30#define RESP_REFUSED (5)
32#define TYPE_A (0x0001)
33#define CLASS_IN (0x0001)
34#define LABEL_COMPRESSION_MASK (0xC0)
41#define INVALID_SERVER -2
43#define INVALID_RESPONSE -4
45void DNSClient::begin(
const IPAddress& aDNSServer)
47 iDNSServer = aDNSServer;
52int DNSClient::inet_aton(
const char* aIPAddrString, IPAddress& aResult)
55 const char* p =aIPAddrString;
57 ( (*p ==
'.') || (*p >=
'0') || (*p <=
'9') ))
68 while (*p && (segment < 4))
73 if (segmentValue > 255)
80 aResult[segment] = (byte)segmentValue;
88 segmentValue = (segmentValue*10)+(*p -
'0');
94 if ((segmentValue > 255) || (segment > 3))
102 aResult[segment] = (byte)segmentValue;
112int DNSClient::getHostByName(
const char* aHostname, IPAddress& aResult)
117 if (inet_aton(aHostname, aResult))
124 if (iDNSServer == INADDR_NONE)
127 return INVALID_SERVER;
131 if (iUdp.begin(1024+(millis() & 0xF)) == 1)
138 ret = iUdp.beginPacket(iDNSServer, DNS_PORT);
142 ret = BuildRequest(aHostname);
146 ret = iUdp.endPacket();
150 int wait_retries = 0;
152 while ((wait_retries < 3) && (ret == TIMED_OUT))
154 ret = ProcessResponse(5000, aResult);
170uint16_t DNSClient::BuildRequest(
const char* aName)
190 iRequestId = millis();
191 uint16_t twoByteBuffer;
195 iUdp.write((uint8_t*)&iRequestId,
sizeof(iRequestId));
197 twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
198 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
200 twoByteBuffer = htons(1);
201 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
204 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
206 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
208 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
211 const char* start =aName;
212 const char* end =start;
219 while (*end && (*end !=
'.') )
228 iUdp.write(&len,
sizeof(len));
230 iUdp.write((uint8_t*)start, end-start);
238 iUdp.write(&len,
sizeof(len));
240 twoByteBuffer = htons(TYPE_A);
241 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
243 twoByteBuffer = htons(CLASS_IN);
244 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
250uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)
252 uint32_t startTime = millis();
255 while(iUdp.parsePacket() <= 0)
257 if((millis() - startTime) > aTimeout){
266 uint8_t header[DNS_HEADER_SIZE];
268 if ( (iDNSServer != iUdp.remoteIP()) ||
269 (iUdp.remotePort() != DNS_PORT) )
273 return INVALID_SERVER;
277 if (iUdp.available() < DNS_HEADER_SIZE)
283 iUdp.read(header, DNS_HEADER_SIZE);
285 uint16_t header_flags = htons(*((uint16_t*)&header[2]));
287 if ( ( iRequestId != (*((uint16_t*)&header[0])) ) ||
288 ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) )
293 return INVALID_RESPONSE;
297 if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) )
306 uint16_t answerCount = htons(*((uint16_t*)&header[6]));
307 if (answerCount == 0 )
318 for (uint16_t i =0; i < HTONS(*((uint16_t*)&header[4])); i++)
339 for (
int i =0; i < 4; i++)
350 for (uint16_t i =0; i < answerCount; i++)
356 iUdp.read(&len,
sizeof(len));
357 if ((len & LABEL_COMPRESSION_MASK) == 0)
388 uint16_t answerClass;
389 iUdp.read((uint8_t*)&answerType,
sizeof(answerType));
390 iUdp.read((uint8_t*)&answerClass,
sizeof(answerClass));
392 IF_RF24ETHERNET_DEBUG_DNS( Serial.print(F(
"RF24DNS Type: ")); Serial.println(HTONS(answerType),HEX); Serial.print(F(
"RF24DNS Class: ")); Serial.println(HTONS(answerClass),HEX); );
394 for (
int i =0; i < TTL_SIZE; i++)
401 iUdp.read((uint8_t*)&header_flags,
sizeof(header_flags));
403 if ( (HTONS(answerType) == TYPE_A) && (HTONS(answerClass) == CLASS_IN) )
406 if (HTONS(header_flags) != 4)
414 iUdp.read(aAddress.raw_address(), 4);
421 for (uint16_t i =0; i < HTONS(header_flags); i++)
#define IF_RF24ETHERNET_DEBUG_DNS(x)