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:
Tue Jan 23 15:08:43 2018 +0100
Revision:
39:deeb00b81cc9
Parent:
33:7ba5d53df0f2
Release: 2.0.4

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