Skip to content

Commit 60b1166

Browse files
author
Laurent Louf
committed
Add a structure for the DNS question, use it DNS server to store the question data and to create the DNS answer from scratch.
1 parent 63541cf commit 60b1166

File tree

2 files changed

+56
-24
lines changed

2 files changed

+56
-24
lines changed

libraries/DNSServer/src/DNSServer.cpp

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ DNSServer::DNSServer()
77
{
88
_ttl = htonl(DNS_DEFAULT_TTL);
99
_errorReplyCode = DNSReplyCode::NonExistentDomain;
10-
_dnsHeader = NULL;
10+
_dnsHeader = (DNSHeader*) malloc( sizeof(DNSHeader) ) ;
11+
_dnsQuestion = (DNSQuestion*) malloc( sizeof(DNSQuestion) ) ;
1112
_buffer = NULL;
1213
_currentPacketSize = 0;
1314
_port = 0;
@@ -62,12 +63,30 @@ void DNSServer::processNextRequest()
6263
if (_buffer == NULL)
6364
return;
6465

65-
// Put the packet received in the buffer and get DNS header (beginning of message),
66-
// type and class (last 4 bytes of the message)
66+
// Put the packet received in the buffer and get DNS header (beginning of message)
67+
// and the question
6768
_udp.read(_buffer, _currentPacketSize);
68-
_dnsHeader = (DNSHeader*) _buffer;
69-
_type = (uint16_t) ( (_buffer[_currentPacketSize - 4] << 8) + _buffer[_currentPacketSize - 3] ) ;
70-
_class = (uint16_t) ( (_buffer[_currentPacketSize - 2] << 8) + _buffer[_currentPacketSize - 1] ) ;
69+
memcpy( _dnsHeader, _buffer, DNS_HEADER_SIZE ) ;
70+
if ( requestIncludesOnlyOneQuestion() )
71+
{
72+
// The QName has a variable length, maximum 255 bytes and is comprised of multiple labels.
73+
// Each label contains a byte to describe its length and the label itself. The list of
74+
// labels terminates with a zero-valued byte. In "github.com", we have two labels "github" & "com"
75+
// Iterate through the labels and copy them as they come into a single buffer (for simplicity's sake)
76+
_dnsQuestion->QNameLength = 0 ;
77+
while ( _buffer[ DNS_HEADER_SIZE + _dnsQuestion->QNameLength ] != 0 )
78+
{
79+
memcpy( (void*) &_dnsQuestion->QName[_dnsQuestion->QNameLength], (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength], _buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength] + 1 ) ;
80+
_dnsQuestion->QNameLength += _buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength] + 1 ;
81+
}
82+
_dnsQuestion->QName[_dnsQuestion->QNameLength] = 0 ;
83+
_dnsQuestion->QNameLength++ ;
84+
85+
// Copy the QType and QClass
86+
memcpy( &_dnsQuestion->QType, (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength], sizeof(_dnsQuestion->QType) ) ;
87+
memcpy( &_dnsQuestion->QClass, (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength + sizeof(_dnsQuestion->QType)], sizeof(_dnsQuestion->QClass) ) ;
88+
}
89+
7190

7291
if (_dnsHeader->QR == DNS_QR_QUERY &&
7392
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
@@ -135,31 +154,35 @@ String DNSServer::getDomainNameWithoutWwwPrefix()
135154
void DNSServer::replyWithIP()
136155
{
137156
if (_buffer == NULL) return;
138-
_dnsHeader->QR = DNS_QR_RESPONSE;
157+
158+
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
159+
160+
// Change the type of message to a response and set the number of answers equal to
161+
// the number of questions in the header
162+
_dnsHeader->QR = DNS_QR_RESPONSE;
139163
_dnsHeader->ANCount = _dnsHeader->QDCount;
140-
//_dnsHeader->QDCount = 0;
164+
_udp.write( (unsigned char*) _dnsHeader, DNS_HEADER_SIZE ) ;
141165

142-
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
143-
_udp.write(_buffer, _currentPacketSize);
166+
// Write the question
167+
_udp.write(_dnsQuestion->QName, _dnsQuestion->QNameLength) ;
168+
_udp.write( (unsigned char*) &_dnsQuestion->QType, 2 ) ;
169+
_udp.write( (unsigned char*) &_dnsQuestion->QClass, 2 ) ;
144170

171+
// Write the answer
145172
// Use DNS name compression : instead of repeating the name in this RNAME occurence,
146173
// set the two MSB of the byte corresponding normally to the length to 1. The following
147174
// 14 bits must be used to specify the offset of the domain name in the message
148175
// (<255 here so the first byte has the 6 LSB at 0)
149176
_udp.write((uint8_t) 0xC0);
150177
_udp.write((uint8_t) DNS_OFFSET_DOMAIN_NAME);
151-
// DNS type A : host address
152-
_udp.write((uint8_t) (DNS_TYPE_A >> 8) );
153-
_udp.write((uint8_t) (DNS_TYPE_A & 0xFF) );
154-
// DNS class IN for INternet
155-
_udp.write((uint8_t) (DNS_CLASS_IN >> 8) );
156-
_udp.write((uint8_t) (DNS_CLASS_IN & 0xFF) );
157-
// DNS Time To Live
158-
_udp.write((unsigned char*)&_ttl, 4);
159-
// Returning an IPv4 address
160-
_udp.write((uint8_t) (DNS_RDLENGTH_IPV4 >> 8) );
161-
_udp.write((uint8_t) (DNS_RDLENGTH_IPV4 & 0xFF) );
162-
_udp.write(_resolvedIP, sizeof(_resolvedIP));
178+
179+
// DNS type A : host address, DNS class IN for INternet, returning an IPv4 address
180+
uint16_t answerType = htons(DNS_TYPE_A), answerClass = htons(DNS_CLASS_IN), answerIPv4 = htons(DNS_RDLENGTH_IPV4) ;
181+
_udp.write((unsigned char*) &answerType, 2 );
182+
_udp.write((unsigned char*) &answerClass, 2 );
183+
_udp.write((unsigned char*) &_ttl, 4); // DNS Time To Live
184+
_udp.write((unsigned char*) &answerIPv4, 2 );
185+
_udp.write(_resolvedIP, sizeof(_resolvedIP)); // The IP address to return
163186
_udp.endPacket();
164187
}
165188

libraries/DNSServer/src/DNSServer.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define DNS_OPCODE_QUERY 0
88
#define DNS_DEFAULT_TTL 60 // Default Time To Live : time interval in seconds that the resource record should be cached before being discarded
99
#define DNS_OFFSET_DOMAIN_NAME 12 // Offset in bytes to reach the domain name in the DNS message
10+
#define DNS_HEADER_SIZE 12
1011

1112
enum class DNSReplyCode
1213
{
@@ -63,6 +64,14 @@ struct DNSHeader
6364
uint16_t ARCount; // number of resource entries
6465
};
6566

67+
struct DNSQuestion
68+
{
69+
uint8_t QName[255] ;
70+
int8_t QNameLength ;
71+
uint16_t QType ;
72+
uint16_t QClass ;
73+
} ;
74+
6675
class DNSServer
6776
{
6877
public:
@@ -88,8 +97,8 @@ class DNSServer
8897
DNSHeader* _dnsHeader;
8998
uint32_t _ttl;
9099
DNSReplyCode _errorReplyCode;
91-
uint16_t _type ;
92-
uint16_t _class ;
100+
DNSQuestion* _dnsQuestion ;
101+
93102

94103
void downcaseAndRemoveWwwPrefix(String &domainName);
95104
String getDomainNameWithoutWwwPrefix();

0 commit comments

Comments
 (0)