friendev EtherDune TCP/IP library
/home/jander/temp/etherdune/DNS.cpp
Go to the documentation of this file.
1 // EtherDune DNS Service
2 // Author: Javier Peletier <jm@friendev.com>
3 // Summary: Implements the basics of DNS so as to resolve hostnames to IP addresses
4 //
5 // Copyright (c) 2015 All Rights Reserved, http://friendev.com
6 //
7 // This source is subject to the GPLv2 license.
8 // Please see the License.txt file for more information.
9 // All other rights reserved.
10 //
11 // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
12 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
14 // PARTICULAR PURPOSE.
15 
16 #include "DNS.h"
17 #include "Checksum.h"
18 
19 #define AC_LOGLEVEL 3
20 #include <ACLog.h>
21 ACROSS_MODULE("DNS");
22 
23 void DNSClient::onReceive(uint16_t len)
24 {
25  //Cheap hack: usually the last 4 bytes of the DNS response are the IP address we're looking for.
26 
27  IPAddress& resolvedIP = *((IPAddress*)(packet.udpData + len - sizeof(IPAddress)));
28 
29  NetworkService::notifyOnDNSResolve(packet.dns.rcode, packet.dns.identification, resolvedIP);
30  buffer.release();
31  if (!buffer.isEmpty())
32  send();
33 }
34 
35 DNSClient::DNSClient()
36 {
37  remotePort = 53;
38 }
39 
45 uint16_t DNSClient::resolve(const char* name)
46 {
47  remoteIP = dnsIP;
48 
49  timer = DNS_TIMEOUT_QUERY;
50 
51  DNSHeader& header = *(DNSHeader*)packet.raw;
52 
53  uint8_t* queryPtr = packet.raw + sizeof(DNSHeader);
54  uint8_t* b = queryPtr;
55  uint8_t* label = b;
56  b++;
57 
58  for (*label = 0; *name != 0; name++, b++)
59  {
60  if (*name == '.')
61  {
62  label = b;
63 
64  *label = 0;
65  }
66  else
67  {
68  *b = *name;
69  (*label)++;
70  }
71  }
72 
73  *b = 0;
74 
75  uint16_t id = Checksum::calc(b - queryPtr, queryPtr);
76 
77  header.zero();
78  header.identification = id;
79  /*
80  header.QR = 0; // query
81  header.opcode = 0; // standard query;
82  */
83  header.RD = 1; //recursion desired
84  header.numberOfQuestions=1; //only one question
85 
86  //queryType = 1 (A query), queryClass=1 (Internet Address);
87  b++;
88  *((uint32_t*)b) = 0x01000100; //queryType = 1 (A query), queryClass=1 (Internet Address);
89 
90 
91  b += 4;
92 
93  write(sizeof(header) + b - queryPtr, packet.raw);
94 
95  send();
96  return id;
97 }
98 
99 
100 void DNSClient::tick()
101 {
102  if (timer > 0)
103  {
104  timer--;
105 
106  if (timer == 0)
107  {
108  buffer.release();
109  timer = DNS_TIMEOUT_QUERY;
110  }
111  }
112 
113 
114  UDPSocket::tick();
115 }
116 
117 bool DNSClient::sendPacket()
118 {
119  uint16_t dataChecksum = 0;
120  uint16_t dataLength;
121 
122  dataLength = buffer.fillTxBuffer(sizeof(EthernetHeader) + sizeof(IPHeader) + sizeof(UDPHeader),/*out*/ dataChecksum, 1);
123 
124  bool ret;
125  if (dataLength > 0)
126  {
127  prepareUDPPacket(dataLength, dataChecksum);
128  ret = !sendIPPacket(sizeof(IPHeader) + sizeof(UDPHeader));
129  }
130  else
131  ret = false;
132 
133  return ret;
134 
135 }
uint16_t release()
Releases one fragment of data
Structure to represent an UDP header.
Definition: inet.h:388
uint8_t raw[566]
Definition: inet.h:537
uint16_t write(uint16_t len, const byte *data)
In the case of TCP, writes the given data buffer to the socket.
Definition: Socket.cpp:54
static EthBuffer packet
in-memory packet buffer currently being processed.
nint16_t remotePort
remote TCP or UDP port
Definition: Socket.h:53
Represents the header of an Ethernet frame.
Definition: inet.h:457
void tick()
This is a timer function that is called every NETWORK_TIMER_RESOLUTION milliseconds on every service...
Definition: UDPSocket.cpp:99
bool send()
Sends the packet currently in the outgoing buffer
Definition: UDPSocket.cpp:45
static uint16_t calc(uint16_t len, const uint8_t *data)
Calculates the checksum of the specified buffer in memory
Definition: Checksum.cpp:59
byte udpData[566-sizeof(EthernetHeader)-sizeof(IPHeader)-sizeof(UDPHeader)]
Definition: inet.h:515
Structure used to encode part of a DNS query.
Definition: inet.h:397
represents an IP address in memory
Definition: inet.h:181
SharedBuffer buffer
output buffer for this socket
Definition: Socket.h:42
void zero()
Sets the entire header to zero.
Definition: inet.h:423
ACROSS_MODULE("DNS")
IP header.
Definition: inet.h:296
uint16_t identification
A 16-bit identification number chosen by the client.
Definition: inet.h:399
void prepareUDPPacket(uint16_t dataLength, uint16_t dataChecksum)
Fills out the UDP header and calculates the datagram checksum
Definition: UDPSocket.cpp:62
static IPAddress dnsIP
IP address of the DNS server to use.
bool isEmpty()
Determines whether this buffer is empty
uint16_t resolve(const char *name)
Resolves a host name to an IP address
Definition: DNS.cpp:45
static bool sendIPPacket(uint16_t length)
Puts the current in-memory packet in the network
DNSHeader dns
Definition: inet.h:516
IPAddress remoteIP
remote IP address to connect to (TCP) or send the next packet to (UDP)
Definition: Socket.h:55
uint8_t rcode
Response Code.
Definition: inet.h:409
uint8_t RD
Recursion Desired.
Definition: inet.h:404
uint16_t fillTxBuffer(uint16_t dstOffset, uint16_t &checksum, uint16_t count=0xFFFF)
Copies up to count fragments to the transmit buffer via DMA, concatenating them starting at given off...
nint16_t numberOfQuestions
Question Count.
Definition: inet.h:415