@@ -7,7 +7,8 @@ DNSServer::DNSServer()
7
7
{
8
8
_ttl = htonl (DNS_DEFAULT_TTL);
9
9
_errorReplyCode = DNSReplyCode::NonExistentDomain;
10
- _dnsHeader = NULL ;
10
+ _dnsHeader = (DNSHeader*) malloc ( sizeof (DNSHeader) ) ;
11
+ _dnsQuestion = (DNSQuestion*) malloc ( sizeof (DNSQuestion) ) ;
11
12
_buffer = NULL ;
12
13
_currentPacketSize = 0 ;
13
14
_port = 0 ;
@@ -62,12 +63,30 @@ void DNSServer::processNextRequest()
62
63
if (_buffer == NULL )
63
64
return ;
64
65
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
67
68
_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
+
71
90
72
91
if (_dnsHeader->QR == DNS_QR_QUERY &&
73
92
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
@@ -135,31 +154,35 @@ String DNSServer::getDomainNameWithoutWwwPrefix()
135
154
void DNSServer::replyWithIP ()
136
155
{
137
156
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;
139
163
_dnsHeader->ANCount = _dnsHeader->QDCount ;
140
- // _dnsHeader->QDCount = 0 ;
164
+ _udp. write ( ( unsigned char *) _dnsHeader, DNS_HEADER_SIZE ) ;
141
165
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 ) ;
144
170
171
+ // Write the answer
145
172
// Use DNS name compression : instead of repeating the name in this RNAME occurence,
146
173
// set the two MSB of the byte corresponding normally to the length to 1. The following
147
174
// 14 bits must be used to specify the offset of the domain name in the message
148
175
// (<255 here so the first byte has the 6 LSB at 0)
149
176
_udp.write ((uint8_t ) 0xC0 );
150
177
_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
163
186
_udp.endPacket ();
164
187
}
165
188
0 commit comments