UIPEthernet library for Arduino IDE, Eclipse with arduino plugin and MBED/SMeshStudio (AVR,STM32F,ESP8266,Intel ARC32,Nordic nRF51,Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip. Compatible with Wiznet W5100 Ethernet library API. Compiled and tested on Nucleo-F302R8. Master repository is: https://github.com/UIPEthernet/UIPEthernet/

Committer:
cassyarduino
Date:
Thu Dec 29 10:41:59 2016 +0000
Revision:
9:312e0937630f
Parent:
0:e3fb1267e3c3
Child:
19:e416943f7119
Corrections for MBED support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cassyarduino 0:e3fb1267e3c3 1 // Arduino DNS client for Enc28J60-based Ethernet shield
cassyarduino 0:e3fb1267e3c3 2 // (c) Copyright 2009-2010 MCQN Ltd.
cassyarduino 0:e3fb1267e3c3 3 // Released under Apache License, version 2.0
cassyarduino 0:e3fb1267e3c3 4
cassyarduino 0:e3fb1267e3c3 5 #include "Dns.h"
cassyarduino 0:e3fb1267e3c3 6 #include <string.h>
cassyarduino 0:e3fb1267e3c3 7 //#include <stdlib.h>
cassyarduino 0:e3fb1267e3c3 8 #if defined(ARDUINO)
cassyarduino 0:e3fb1267e3c3 9 #include "Arduino.h"
cassyarduino 0:e3fb1267e3c3 10 #include "Udp.h"
cassyarduino 0:e3fb1267e3c3 11 #endif
cassyarduino 0:e3fb1267e3c3 12 #if defined(__MBED__)
cassyarduino 0:e3fb1267e3c3 13 #include <mbed.h>
cassyarduino 0:e3fb1267e3c3 14 #include "mbed/Udp.h"
cassyarduino 0:e3fb1267e3c3 15 #include "mbed/millis.h"
cassyarduino 0:e3fb1267e3c3 16 #define delay(x) wait_ms(x)
cassyarduino 0:e3fb1267e3c3 17 #endif
cassyarduino 0:e3fb1267e3c3 18 #include "utility/logging.h"
cassyarduino 0:e3fb1267e3c3 19 #include "utility/uip.h"
cassyarduino 0:e3fb1267e3c3 20
cassyarduino 0:e3fb1267e3c3 21
cassyarduino 0:e3fb1267e3c3 22 #define SOCKET_NONE 255
cassyarduino 0:e3fb1267e3c3 23 // Various flags and header field values for a DNS message
cassyarduino 0:e3fb1267e3c3 24 #define UDP_HEADER_SIZE 8
cassyarduino 0:e3fb1267e3c3 25 #define DNS_HEADER_SIZE 12
cassyarduino 0:e3fb1267e3c3 26 #define TTL_SIZE 4
cassyarduino 0:e3fb1267e3c3 27 #define QUERY_FLAG (0)
cassyarduino 0:e3fb1267e3c3 28 #define RESPONSE_FLAG (1<<15)
cassyarduino 0:e3fb1267e3c3 29 #define QUERY_RESPONSE_MASK (1<<15)
cassyarduino 0:e3fb1267e3c3 30 #define OPCODE_STANDARD_QUERY (0)
cassyarduino 0:e3fb1267e3c3 31 #define OPCODE_INVERSE_QUERY (1<<11)
cassyarduino 0:e3fb1267e3c3 32 #define OPCODE_STATUS_REQUEST (2<<11)
cassyarduino 0:e3fb1267e3c3 33 #define OPCODE_MASK (15<<11)
cassyarduino 0:e3fb1267e3c3 34 #define AUTHORITATIVE_FLAG (1<<10)
cassyarduino 0:e3fb1267e3c3 35 #define TRUNCATION_FLAG (1<<9)
cassyarduino 0:e3fb1267e3c3 36 #define RECURSION_DESIRED_FLAG (1<<8)
cassyarduino 0:e3fb1267e3c3 37 #define RECURSION_AVAILABLE_FLAG (1<<7)
cassyarduino 0:e3fb1267e3c3 38 #define RESP_NO_ERROR (0)
cassyarduino 0:e3fb1267e3c3 39 #define RESP_FORMAT_ERROR (1)
cassyarduino 0:e3fb1267e3c3 40 #define RESP_SERVER_FAILURE (2)
cassyarduino 0:e3fb1267e3c3 41 #define RESP_NAME_ERROR (3)
cassyarduino 0:e3fb1267e3c3 42 #define RESP_NOT_IMPLEMENTED (4)
cassyarduino 0:e3fb1267e3c3 43 #define RESP_REFUSED (5)
cassyarduino 0:e3fb1267e3c3 44 #define RESP_MASK (15)
cassyarduino 0:e3fb1267e3c3 45 #define TYPE_A (0x0001)
cassyarduino 0:e3fb1267e3c3 46 #define CLASS_IN (0x0001)
cassyarduino 0:e3fb1267e3c3 47 #define LABEL_COMPRESSION_MASK (0xC0)
cassyarduino 0:e3fb1267e3c3 48 // Port number that DNS servers listen on
cassyarduino 0:e3fb1267e3c3 49 #define DNS_PORT 53
cassyarduino 0:e3fb1267e3c3 50
cassyarduino 0:e3fb1267e3c3 51 // Possible return codes from ProcessResponse
cassyarduino 0:e3fb1267e3c3 52 #define SUCCESS 1
cassyarduino 0:e3fb1267e3c3 53 #define TIMED_OUT -1
cassyarduino 0:e3fb1267e3c3 54 #define INVALID_SERVER -2
cassyarduino 0:e3fb1267e3c3 55 #define TRUNCATED -3
cassyarduino 0:e3fb1267e3c3 56 #define INVALID_RESPONSE -4
cassyarduino 0:e3fb1267e3c3 57
cassyarduino 0:e3fb1267e3c3 58 void DNSClient::begin(const IPAddress& aDNSServer)
cassyarduino 0:e3fb1267e3c3 59 {
cassyarduino 0:e3fb1267e3c3 60 iDNSServer = aDNSServer;
cassyarduino 0:e3fb1267e3c3 61 iRequestId = 0;
cassyarduino 0:e3fb1267e3c3 62 }
cassyarduino 0:e3fb1267e3c3 63
cassyarduino 0:e3fb1267e3c3 64
cassyarduino 0:e3fb1267e3c3 65 int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult)
cassyarduino 0:e3fb1267e3c3 66 {
cassyarduino 0:e3fb1267e3c3 67 // See if we've been given a valid IP address
cassyarduino 0:e3fb1267e3c3 68 const char* p =aIPAddrString;
cassyarduino 0:e3fb1267e3c3 69 while (*p && ( (*p == '.') || ((*p >= '0') && (*p <= '9')) ))
cassyarduino 0:e3fb1267e3c3 70 {
cassyarduino 0:e3fb1267e3c3 71 p++;
cassyarduino 0:e3fb1267e3c3 72 }
cassyarduino 0:e3fb1267e3c3 73
cassyarduino 0:e3fb1267e3c3 74 if (*p == '\0')
cassyarduino 0:e3fb1267e3c3 75 {
cassyarduino 0:e3fb1267e3c3 76 // It's looking promising, we haven't found any invalid characters
cassyarduino 0:e3fb1267e3c3 77 p = aIPAddrString;
cassyarduino 0:e3fb1267e3c3 78 int segment =0;
cassyarduino 0:e3fb1267e3c3 79 int segmentValue =0;
cassyarduino 0:e3fb1267e3c3 80 while (*p && (segment < 4))
cassyarduino 0:e3fb1267e3c3 81 {
cassyarduino 0:e3fb1267e3c3 82 if (*p == '.')
cassyarduino 0:e3fb1267e3c3 83 {
cassyarduino 0:e3fb1267e3c3 84 // We've reached the end of a segment
cassyarduino 0:e3fb1267e3c3 85 if (segmentValue > 255)
cassyarduino 0:e3fb1267e3c3 86 {
cassyarduino 0:e3fb1267e3c3 87 // You can't have IP address segments that don't fit in a byte
cassyarduino 0:e3fb1267e3c3 88 return 0;
cassyarduino 0:e3fb1267e3c3 89 }
cassyarduino 0:e3fb1267e3c3 90 else
cassyarduino 0:e3fb1267e3c3 91 {
cassyarduino 0:e3fb1267e3c3 92 aResult[segment] = (uint8_t)segmentValue;
cassyarduino 0:e3fb1267e3c3 93 segment++;
cassyarduino 0:e3fb1267e3c3 94 segmentValue = 0;
cassyarduino 0:e3fb1267e3c3 95 }
cassyarduino 0:e3fb1267e3c3 96 }
cassyarduino 0:e3fb1267e3c3 97 else
cassyarduino 0:e3fb1267e3c3 98 {
cassyarduino 0:e3fb1267e3c3 99 // Next digit
cassyarduino 0:e3fb1267e3c3 100 segmentValue = (segmentValue*10)+(*p - '0');
cassyarduino 0:e3fb1267e3c3 101 }
cassyarduino 0:e3fb1267e3c3 102 p++;
cassyarduino 0:e3fb1267e3c3 103 }
cassyarduino 0:e3fb1267e3c3 104 // We've reached the end of address, but there'll still be the last
cassyarduino 0:e3fb1267e3c3 105 // segment to deal with
cassyarduino 0:e3fb1267e3c3 106 if ((segmentValue > 255) || (segment > 3))
cassyarduino 0:e3fb1267e3c3 107 {
cassyarduino 0:e3fb1267e3c3 108 // You can't have IP address segments that don't fit in a byte,
cassyarduino 0:e3fb1267e3c3 109 // or more than four segments
cassyarduino 0:e3fb1267e3c3 110 return 0;
cassyarduino 0:e3fb1267e3c3 111 }
cassyarduino 0:e3fb1267e3c3 112 else
cassyarduino 0:e3fb1267e3c3 113 {
cassyarduino 0:e3fb1267e3c3 114 aResult[segment] = (uint8_t)segmentValue;
cassyarduino 0:e3fb1267e3c3 115 return 1;
cassyarduino 0:e3fb1267e3c3 116 }
cassyarduino 0:e3fb1267e3c3 117 }
cassyarduino 0:e3fb1267e3c3 118 else
cassyarduino 0:e3fb1267e3c3 119 {
cassyarduino 0:e3fb1267e3c3 120 return 0;
cassyarduino 0:e3fb1267e3c3 121 }
cassyarduino 0:e3fb1267e3c3 122 }
cassyarduino 0:e3fb1267e3c3 123
cassyarduino 0:e3fb1267e3c3 124 int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult)
cassyarduino 0:e3fb1267e3c3 125 {
cassyarduino 0:e3fb1267e3c3 126 int ret =0;
cassyarduino 0:e3fb1267e3c3 127
cassyarduino 0:e3fb1267e3c3 128 // See if it's a numeric IP address
cassyarduino 0:e3fb1267e3c3 129 if (inet_aton(aHostname, aResult))
cassyarduino 0:e3fb1267e3c3 130 {
cassyarduino 0:e3fb1267e3c3 131 // It is, our work here is done
cassyarduino 0:e3fb1267e3c3 132 return 1;
cassyarduino 0:e3fb1267e3c3 133 }
cassyarduino 0:e3fb1267e3c3 134
cassyarduino 0:e3fb1267e3c3 135 // Check we've got a valid DNS server to use
cassyarduino 0:e3fb1267e3c3 136 if (iDNSServer == INADDR_NONE)
cassyarduino 0:e3fb1267e3c3 137 {
cassyarduino 0:e3fb1267e3c3 138 return INVALID_SERVER;
cassyarduino 0:e3fb1267e3c3 139 }
cassyarduino 0:e3fb1267e3c3 140
cassyarduino 0:e3fb1267e3c3 141 // Find a socket to use
cassyarduino 0:e3fb1267e3c3 142 if (iUdp.begin(1024+(millis() & 0xF)) == 1)
cassyarduino 0:e3fb1267e3c3 143 {
cassyarduino 0:e3fb1267e3c3 144 // Try up to three times
cassyarduino 0:e3fb1267e3c3 145 int retries = 0;
cassyarduino 0:e3fb1267e3c3 146 // while ((retries < 3) && (ret <= 0))
cassyarduino 0:e3fb1267e3c3 147 {
cassyarduino 0:e3fb1267e3c3 148 // Send DNS request
cassyarduino 0:e3fb1267e3c3 149 ret = iUdp.beginPacket(iDNSServer, DNS_PORT);
cassyarduino 0:e3fb1267e3c3 150 if (ret != 0)
cassyarduino 0:e3fb1267e3c3 151 {
cassyarduino 0:e3fb1267e3c3 152 // Now output the request data
cassyarduino 0:e3fb1267e3c3 153 ret = BuildRequest(aHostname);
cassyarduino 0:e3fb1267e3c3 154 if (ret != 0)
cassyarduino 0:e3fb1267e3c3 155 {
cassyarduino 0:e3fb1267e3c3 156 // And finally send the request
cassyarduino 0:e3fb1267e3c3 157 ret = iUdp.endPacket();
cassyarduino 0:e3fb1267e3c3 158 if (ret != 0)
cassyarduino 0:e3fb1267e3c3 159 {
cassyarduino 0:e3fb1267e3c3 160 // Now wait for a response
cassyarduino 0:e3fb1267e3c3 161 int wait_retries = 0;
cassyarduino 0:e3fb1267e3c3 162 ret = TIMED_OUT;
cassyarduino 0:e3fb1267e3c3 163 while ((wait_retries < 3) && (ret == TIMED_OUT))
cassyarduino 0:e3fb1267e3c3 164 {
cassyarduino 0:e3fb1267e3c3 165 ret = ProcessResponse(5000, aResult);
cassyarduino 0:e3fb1267e3c3 166 wait_retries++;
cassyarduino 0:e3fb1267e3c3 167 }
cassyarduino 0:e3fb1267e3c3 168 }
cassyarduino 0:e3fb1267e3c3 169 }
cassyarduino 0:e3fb1267e3c3 170 }
cassyarduino 0:e3fb1267e3c3 171 retries++;
cassyarduino 0:e3fb1267e3c3 172 }
cassyarduino 0:e3fb1267e3c3 173
cassyarduino 0:e3fb1267e3c3 174 // We're done with the socket now
cassyarduino 0:e3fb1267e3c3 175 iUdp.stop();
cassyarduino 0:e3fb1267e3c3 176 }
cassyarduino 0:e3fb1267e3c3 177
cassyarduino 0:e3fb1267e3c3 178 return ret;
cassyarduino 0:e3fb1267e3c3 179 }
cassyarduino 0:e3fb1267e3c3 180
cassyarduino 0:e3fb1267e3c3 181 uint16_t DNSClient::BuildRequest(const char* aName)
cassyarduino 0:e3fb1267e3c3 182 {
cassyarduino 0:e3fb1267e3c3 183 // Build header
cassyarduino 0:e3fb1267e3c3 184 // 1 1 1 1 1 1
cassyarduino 0:e3fb1267e3c3 185 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
cassyarduino 0:e3fb1267e3c3 186 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 187 // | ID |
cassyarduino 0:e3fb1267e3c3 188 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 189 // |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
cassyarduino 0:e3fb1267e3c3 190 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 191 // | QDCOUNT |
cassyarduino 0:e3fb1267e3c3 192 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 193 // | ANCOUNT |
cassyarduino 0:e3fb1267e3c3 194 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 195 // | NSCOUNT |
cassyarduino 0:e3fb1267e3c3 196 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 197 // | ARCOUNT |
cassyarduino 0:e3fb1267e3c3 198 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
cassyarduino 0:e3fb1267e3c3 199 // As we only support one request at a time at present, we can simplify
cassyarduino 0:e3fb1267e3c3 200 // some of this header
cassyarduino 0:e3fb1267e3c3 201 iRequestId = millis(); // generate a random ID
cassyarduino 0:e3fb1267e3c3 202 uint16_t twoByteBuffer;
cassyarduino 0:e3fb1267e3c3 203
cassyarduino 0:e3fb1267e3c3 204 // FIXME We should also check that there's enough space available to write to, rather
cassyarduino 0:e3fb1267e3c3 205 // FIXME than assume there's enough space (as the code does at present)
cassyarduino 0:e3fb1267e3c3 206 iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId));
cassyarduino 0:e3fb1267e3c3 207
cassyarduino 0:e3fb1267e3c3 208 twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
cassyarduino 0:e3fb1267e3c3 209 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 210
cassyarduino 0:e3fb1267e3c3 211 twoByteBuffer = htons(1); // One question record
cassyarduino 0:e3fb1267e3c3 212 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 213
cassyarduino 0:e3fb1267e3c3 214 twoByteBuffer = 0; // Zero answer records
cassyarduino 0:e3fb1267e3c3 215 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 216
cassyarduino 0:e3fb1267e3c3 217 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 218 // and zero additional records
cassyarduino 0:e3fb1267e3c3 219 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 220
cassyarduino 0:e3fb1267e3c3 221 // Build question
cassyarduino 0:e3fb1267e3c3 222 const char* start =aName;
cassyarduino 0:e3fb1267e3c3 223 const char* end =start;
cassyarduino 0:e3fb1267e3c3 224 uint8_t len;
cassyarduino 0:e3fb1267e3c3 225 // Run through the name being requested
cassyarduino 0:e3fb1267e3c3 226 while (*end)
cassyarduino 0:e3fb1267e3c3 227 {
cassyarduino 0:e3fb1267e3c3 228 // Find out how long this section of the name is
cassyarduino 0:e3fb1267e3c3 229 end = start;
cassyarduino 0:e3fb1267e3c3 230 while (*end && (*end != '.') )
cassyarduino 0:e3fb1267e3c3 231 {
cassyarduino 0:e3fb1267e3c3 232 end++;
cassyarduino 0:e3fb1267e3c3 233 }
cassyarduino 0:e3fb1267e3c3 234
cassyarduino 0:e3fb1267e3c3 235 if (end-start > 0)
cassyarduino 0:e3fb1267e3c3 236 {
cassyarduino 0:e3fb1267e3c3 237 // Write out the size of this section
cassyarduino 0:e3fb1267e3c3 238 len = end-start;
cassyarduino 0:e3fb1267e3c3 239 iUdp.write(&len, sizeof(len));
cassyarduino 0:e3fb1267e3c3 240 // And then write out the section
cassyarduino 0:e3fb1267e3c3 241 iUdp.write((uint8_t*)start, end-start);
cassyarduino 0:e3fb1267e3c3 242 }
cassyarduino 0:e3fb1267e3c3 243 start = end+1;
cassyarduino 0:e3fb1267e3c3 244 }
cassyarduino 0:e3fb1267e3c3 245
cassyarduino 0:e3fb1267e3c3 246 // We've got to the end of the question name, so
cassyarduino 0:e3fb1267e3c3 247 // terminate it with a zero-length section
cassyarduino 0:e3fb1267e3c3 248 len = 0;
cassyarduino 0:e3fb1267e3c3 249 iUdp.write(&len, sizeof(len));
cassyarduino 0:e3fb1267e3c3 250 // Finally the type and class of question
cassyarduino 0:e3fb1267e3c3 251 twoByteBuffer = htons(TYPE_A);
cassyarduino 0:e3fb1267e3c3 252 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 253
cassyarduino 0:e3fb1267e3c3 254 twoByteBuffer = htons(CLASS_IN); // Internet class of question
cassyarduino 0:e3fb1267e3c3 255 iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
cassyarduino 0:e3fb1267e3c3 256 // Success! Everything buffered okay
cassyarduino 0:e3fb1267e3c3 257 return 1;
cassyarduino 0:e3fb1267e3c3 258 }
cassyarduino 0:e3fb1267e3c3 259
cassyarduino 0:e3fb1267e3c3 260
cassyarduino 9:312e0937630f 261 int16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)
cassyarduino 0:e3fb1267e3c3 262 {
cassyarduino 0:e3fb1267e3c3 263 uint32_t startTime = millis();
cassyarduino 0:e3fb1267e3c3 264
cassyarduino 0:e3fb1267e3c3 265 // Wait for a response packet
cassyarduino 0:e3fb1267e3c3 266 while(iUdp.parsePacket() <= 0)
cassyarduino 0:e3fb1267e3c3 267 {
cassyarduino 0:e3fb1267e3c3 268 if((millis() - startTime) > aTimeout)
cassyarduino 0:e3fb1267e3c3 269 return TIMED_OUT;
cassyarduino 0:e3fb1267e3c3 270 delay(50);
cassyarduino 0:e3fb1267e3c3 271 }
cassyarduino 0:e3fb1267e3c3 272
cassyarduino 0:e3fb1267e3c3 273 // We've had a reply!
cassyarduino 0:e3fb1267e3c3 274 // Read the UDP header
cassyarduino 0:e3fb1267e3c3 275 uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header
cassyarduino 0:e3fb1267e3c3 276 // Check that it's a response from the right server and the right port
cassyarduino 0:e3fb1267e3c3 277 if ( (iDNSServer != iUdp.remoteIP()) ||
cassyarduino 0:e3fb1267e3c3 278 (iUdp.remotePort() != DNS_PORT) )
cassyarduino 0:e3fb1267e3c3 279 {
cassyarduino 0:e3fb1267e3c3 280 // It's not from who we expected
cassyarduino 0:e3fb1267e3c3 281 return INVALID_SERVER;
cassyarduino 0:e3fb1267e3c3 282 }
cassyarduino 0:e3fb1267e3c3 283
cassyarduino 0:e3fb1267e3c3 284 // Read through the rest of the response
cassyarduino 0:e3fb1267e3c3 285 if (iUdp.available() < DNS_HEADER_SIZE)
cassyarduino 0:e3fb1267e3c3 286 {
cassyarduino 0:e3fb1267e3c3 287 return TRUNCATED;
cassyarduino 0:e3fb1267e3c3 288 }
cassyarduino 0:e3fb1267e3c3 289 iUdp.read((char*)header, DNS_HEADER_SIZE);
cassyarduino 0:e3fb1267e3c3 290
cassyarduino 0:e3fb1267e3c3 291 uint16_t header_flags = htons(*((uint16_t*)&header[2]));
cassyarduino 0:e3fb1267e3c3 292 // Check that it's a response to this request
cassyarduino 0:e3fb1267e3c3 293 if ( ( iRequestId != (*((uint16_t*)&header[0])) ) ||
cassyarduino 0:e3fb1267e3c3 294 ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) )
cassyarduino 0:e3fb1267e3c3 295 {
cassyarduino 0:e3fb1267e3c3 296 // Mark the entire packet as read
cassyarduino 0:e3fb1267e3c3 297 iUdp.flush();
cassyarduino 0:e3fb1267e3c3 298 return INVALID_RESPONSE;
cassyarduino 0:e3fb1267e3c3 299 }
cassyarduino 0:e3fb1267e3c3 300 // Check for any errors in the response (or in our request)
cassyarduino 0:e3fb1267e3c3 301 // although we don't do anything to get round these
cassyarduino 0:e3fb1267e3c3 302 if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) )
cassyarduino 0:e3fb1267e3c3 303 {
cassyarduino 0:e3fb1267e3c3 304 // Mark the entire packet as read
cassyarduino 0:e3fb1267e3c3 305 iUdp.flush();
cassyarduino 0:e3fb1267e3c3 306 return -5; //INVALID_RESPONSE;
cassyarduino 0:e3fb1267e3c3 307 }
cassyarduino 0:e3fb1267e3c3 308
cassyarduino 0:e3fb1267e3c3 309 // And make sure we've got (at least) one answer
cassyarduino 0:e3fb1267e3c3 310 uint16_t answerCount = htons(*((uint16_t*)&header[6]));
cassyarduino 0:e3fb1267e3c3 311 if (answerCount == 0 )
cassyarduino 0:e3fb1267e3c3 312 {
cassyarduino 0:e3fb1267e3c3 313 // Mark the entire packet as read
cassyarduino 0:e3fb1267e3c3 314 iUdp.flush();
cassyarduino 0:e3fb1267e3c3 315 return -6; //INVALID_RESPONSE;
cassyarduino 0:e3fb1267e3c3 316 }
cassyarduino 0:e3fb1267e3c3 317
cassyarduino 0:e3fb1267e3c3 318 // Skip over any questions
cassyarduino 0:e3fb1267e3c3 319 for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++)
cassyarduino 0:e3fb1267e3c3 320 {
cassyarduino 0:e3fb1267e3c3 321 // Skip over the name
cassyarduino 0:e3fb1267e3c3 322 uint8_t len;
cassyarduino 0:e3fb1267e3c3 323 do
cassyarduino 0:e3fb1267e3c3 324 {
cassyarduino 0:e3fb1267e3c3 325 iUdp.read((char*)&len, sizeof(len));
cassyarduino 0:e3fb1267e3c3 326 if (len > 0)
cassyarduino 0:e3fb1267e3c3 327 {
cassyarduino 0:e3fb1267e3c3 328 // Don't need to actually read the data out for the string, just
cassyarduino 0:e3fb1267e3c3 329 // advance ptr to beyond it
cassyarduino 0:e3fb1267e3c3 330 while(len--)
cassyarduino 0:e3fb1267e3c3 331 {
cassyarduino 0:e3fb1267e3c3 332 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 333 }
cassyarduino 0:e3fb1267e3c3 334 }
cassyarduino 0:e3fb1267e3c3 335 } while (len != 0);
cassyarduino 0:e3fb1267e3c3 336
cassyarduino 0:e3fb1267e3c3 337 // Now jump over the type and class
cassyarduino 0:e3fb1267e3c3 338 for (int i =0; i < 4; i++)
cassyarduino 0:e3fb1267e3c3 339 {
cassyarduino 0:e3fb1267e3c3 340 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 341 }
cassyarduino 0:e3fb1267e3c3 342 }
cassyarduino 0:e3fb1267e3c3 343
cassyarduino 0:e3fb1267e3c3 344 // Now we're up to the bit we're interested in, the answer
cassyarduino 0:e3fb1267e3c3 345 // There might be more than one answer (although we'll just use the first
cassyarduino 0:e3fb1267e3c3 346 // type A answer) and some authority and additional resource records but
cassyarduino 0:e3fb1267e3c3 347 // we're going to ignore all of them.
cassyarduino 0:e3fb1267e3c3 348
cassyarduino 0:e3fb1267e3c3 349 for (uint16_t i =0; i < answerCount; i++)
cassyarduino 0:e3fb1267e3c3 350 {
cassyarduino 0:e3fb1267e3c3 351 // Skip the name
cassyarduino 0:e3fb1267e3c3 352 uint8_t len;
cassyarduino 0:e3fb1267e3c3 353 do
cassyarduino 0:e3fb1267e3c3 354 {
cassyarduino 0:e3fb1267e3c3 355 iUdp.read((char*)&len, sizeof(len));
cassyarduino 0:e3fb1267e3c3 356 if ((len & LABEL_COMPRESSION_MASK) == 0)
cassyarduino 0:e3fb1267e3c3 357 {
cassyarduino 0:e3fb1267e3c3 358 // It's just a normal label
cassyarduino 0:e3fb1267e3c3 359 if (len > 0)
cassyarduino 0:e3fb1267e3c3 360 {
cassyarduino 0:e3fb1267e3c3 361 // And it's got a length
cassyarduino 0:e3fb1267e3c3 362 // Don't need to actually read the data out for the string,
cassyarduino 0:e3fb1267e3c3 363 // just advance ptr to beyond it
cassyarduino 0:e3fb1267e3c3 364 while(len--)
cassyarduino 0:e3fb1267e3c3 365 {
cassyarduino 0:e3fb1267e3c3 366 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 367 }
cassyarduino 0:e3fb1267e3c3 368 }
cassyarduino 0:e3fb1267e3c3 369 }
cassyarduino 0:e3fb1267e3c3 370 else
cassyarduino 0:e3fb1267e3c3 371 {
cassyarduino 0:e3fb1267e3c3 372 // This is a pointer to a somewhere else in the message for the
cassyarduino 0:e3fb1267e3c3 373 // rest of the name. We don't care about the name, and RFC1035
cassyarduino 0:e3fb1267e3c3 374 // says that a name is either a sequence of labels ended with a
cassyarduino 0:e3fb1267e3c3 375 // 0 length octet or a pointer or a sequence of labels ending in
cassyarduino 0:e3fb1267e3c3 376 // a pointer. Either way, when we get here we're at the end of
cassyarduino 0:e3fb1267e3c3 377 // the name
cassyarduino 0:e3fb1267e3c3 378 // Skip over the pointer
cassyarduino 0:e3fb1267e3c3 379 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 380 // And set len so that we drop out of the name loop
cassyarduino 0:e3fb1267e3c3 381 len = 0;
cassyarduino 0:e3fb1267e3c3 382 }
cassyarduino 0:e3fb1267e3c3 383 } while (len != 0);
cassyarduino 0:e3fb1267e3c3 384
cassyarduino 0:e3fb1267e3c3 385 // Check the type and class
cassyarduino 0:e3fb1267e3c3 386 uint16_t answerType;
cassyarduino 0:e3fb1267e3c3 387 uint16_t answerClass;
cassyarduino 0:e3fb1267e3c3 388 iUdp.read((char*)&answerType, sizeof(answerType));
cassyarduino 0:e3fb1267e3c3 389 iUdp.read((char*)&answerClass, sizeof(answerClass));
cassyarduino 0:e3fb1267e3c3 390
cassyarduino 0:e3fb1267e3c3 391 // Ignore the Time-To-Live as we don't do any caching
cassyarduino 0:e3fb1267e3c3 392 for (int i =0; i < TTL_SIZE; i++)
cassyarduino 0:e3fb1267e3c3 393 {
cassyarduino 0:e3fb1267e3c3 394 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 395 }
cassyarduino 0:e3fb1267e3c3 396
cassyarduino 0:e3fb1267e3c3 397 // And read out the length of this answer
cassyarduino 0:e3fb1267e3c3 398 // Don't need header_flags anymore, so we can reuse it here
cassyarduino 0:e3fb1267e3c3 399 iUdp.read((char*)&header_flags, sizeof(header_flags));
cassyarduino 0:e3fb1267e3c3 400
cassyarduino 0:e3fb1267e3c3 401 if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) )
cassyarduino 0:e3fb1267e3c3 402 {
cassyarduino 0:e3fb1267e3c3 403 if (htons(header_flags) != 4)
cassyarduino 0:e3fb1267e3c3 404 {
cassyarduino 0:e3fb1267e3c3 405 // It's a weird size
cassyarduino 0:e3fb1267e3c3 406 // Mark the entire packet as read
cassyarduino 0:e3fb1267e3c3 407 iUdp.flush();
cassyarduino 0:e3fb1267e3c3 408 return -9;//INVALID_RESPONSE;
cassyarduino 0:e3fb1267e3c3 409 }
cassyarduino 0:e3fb1267e3c3 410 iUdp.read((char*)aAddress.raw_address(), 4);
cassyarduino 0:e3fb1267e3c3 411 return SUCCESS;
cassyarduino 0:e3fb1267e3c3 412 }
cassyarduino 0:e3fb1267e3c3 413 else
cassyarduino 0:e3fb1267e3c3 414 {
cassyarduino 0:e3fb1267e3c3 415 // This isn't an answer type we're after, move onto the next one
cassyarduino 0:e3fb1267e3c3 416 for (uint16_t i =0; i < htons(header_flags); i++)
cassyarduino 0:e3fb1267e3c3 417 {
cassyarduino 0:e3fb1267e3c3 418 iUdp.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 419 }
cassyarduino 0:e3fb1267e3c3 420 }
cassyarduino 0:e3fb1267e3c3 421 }
cassyarduino 0:e3fb1267e3c3 422
cassyarduino 0:e3fb1267e3c3 423 // Mark the entire packet as read
cassyarduino 0:e3fb1267e3c3 424 iUdp.flush();
cassyarduino 0:e3fb1267e3c3 425
cassyarduino 0:e3fb1267e3c3 426 // If we get here then we haven't found an answer
cassyarduino 0:e3fb1267e3c3 427 return -10;//INVALID_RESPONSE;
cassyarduino 0:e3fb1267e3c3 428 }
cassyarduino 0:e3fb1267e3c3 429