9 #define SOCKET_NONE 255
11 #define UDP_HEADER_SIZE 8
12 #define DNS_HEADER_SIZE 12
14 #define QUERY_FLAG (0)
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)
31 #define RESP_MASK (15)
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;
51int DNSClient::inet_aton(
const char* aIPAddrString, IPAddress& aResult)
54 const char* p = aIPAddrString;
55 while (*p && ((*p ==
'.') || (*p >=
'0') || (*p <=
'9')))
66 while (*p && (segment < 4))
71 if (segmentValue > 255)
78 aResult[segment] = (byte)segmentValue;
86 segmentValue = (segmentValue * 10) + (*p -
'0');
92 if ((segmentValue > 255) || (segment > 3))
100 aResult[segment] = (byte)segmentValue;
110int DNSClient::getHostByName(
const char* aHostname, IPAddress& aResult)
115 if (inet_aton(aHostname, aResult))
122 if (iDNSServer == INADDR_NONE)
125 return INVALID_SERVER;
129 if (iUdp.begin(1024 + (millis() & 0xF)) == 1)
136 ret = iUdp.beginPacket(iDNSServer, DNS_PORT);
140 ret = BuildRequest(aHostname);
144 ret = iUdp.endPacket();
148 int wait_retries = 0;
150 while ((wait_retries < 3) && (ret == TIMED_OUT))
152 ret = ProcessResponse(5000, aResult);
168uint16_t DNSClient::BuildRequest(
const char* aName)
188 iRequestId = millis();
189 uint16_t twoByteBuffer;
193 iUdp.write((uint8_t*)&iRequestId,
sizeof(iRequestId));
195 twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
196 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
198 twoByteBuffer = htons(1);
199 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
202 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
204 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
206 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
209 const char* start = aName;
210 const char* end = start;
217 while (*end && (*end !=
'.'))
226 iUdp.write(&len,
sizeof(len));
228 iUdp.write((uint8_t*)start, end - start);
236 iUdp.write(&len,
sizeof(len));
238 twoByteBuffer = htons(TYPE_A);
239 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
241 twoByteBuffer = htons(CLASS_IN);
242 iUdp.write((uint8_t*)&twoByteBuffer,
sizeof(twoByteBuffer));
247uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)
249 uint32_t startTime = millis();
252 while (iUdp.parsePacket() <= 0)
254 if ((millis() - startTime) > aTimeout) {
263 uint8_t header[DNS_HEADER_SIZE];
265 if ((iDNSServer != iUdp.remoteIP()) || (iUdp.remotePort() != DNS_PORT))
269 return INVALID_SERVER;
273 if (iUdp.available() < DNS_HEADER_SIZE)
279 iUdp.read(header, DNS_HEADER_SIZE);
281 uint16_t header_flags = htons(*((uint16_t*)&header[2]));
283 if ((iRequestId != (*((uint16_t*)&header[0]))) || ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG))
288 return INVALID_RESPONSE;
292 if ((header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK))
301 uint16_t answerCount = htons(*((uint16_t*)&header[6]));
302 if (answerCount == 0)
313 for (uint16_t i = 0; i < HTONS(*((uint16_t*)&header[4])); i++)
334 for (
int i = 0; i < 4; i++)
345 for (uint16_t i = 0; i < answerCount; i++)
351 iUdp.read(&len,
sizeof(len));
352 if ((len & LABEL_COMPRESSION_MASK) == 0)
383 uint16_t answerClass;
384 iUdp.read((uint8_t*)&answerType,
sizeof(answerType));
385 iUdp.read((uint8_t*)&answerClass,
sizeof(answerClass));
387 IF_RF24ETHERNET_DEBUG_DNS(Serial.print(F(
"RF24DNS Type: ")); Serial.println(HTONS(answerType), HEX); Serial.print(F(
"RF24DNS Class: ")); Serial.println(HTONS(answerClass), HEX););
389 for (
int i = 0; i < TTL_SIZE; i++)
396 iUdp.read((uint8_t*)&header_flags,
sizeof(header_flags));
398 if ((HTONS(answerType) == TYPE_A) && (HTONS(answerClass) == CLASS_IN))
401 if (HTONS(header_flags) != 4)
409 iUdp.read(aAddress.raw_address(), 4);
416 for (uint16_t i = 0; i < HTONS(header_flags); i++)
#define IF_RF24ETHERNET_DEBUG_DNS(x)