@@ -13,7 +13,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName,
13
13
const IPAddress &resolvedIP)
14
14
{
15
15
_port = port;
16
- _buffer = NULL ;
16
+
17
17
_domainName = domainName;
18
18
_resolvedIP[0 ] = resolvedIP[0 ];
19
19
_resolvedIP[1 ] = resolvedIP[1 ];
@@ -36,8 +36,6 @@ void DNSServer::setTTL(const uint32_t &ttl)
36
36
void DNSServer::stop ()
37
37
{
38
38
_udp.stop ();
39
- free (_buffer);
40
- _buffer = NULL ;
41
39
}
42
40
43
41
void DNSServer::downcaseAndRemoveWwwPrefix (String &domainName)
@@ -48,82 +46,106 @@ void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
48
46
49
47
void DNSServer::processNextRequest ()
50
48
{
51
- _currentPacketSize = _udp.parsePacket ();
52
- if (_currentPacketSize)
49
+ size_t packetSize = _udp.parsePacket ();
50
+
51
+ if (packetSize >= sizeof (DNSHeader))
53
52
{
54
- if (_buffer != NULL ) free (_buffer);
55
- _buffer = (unsigned char *)malloc (_currentPacketSize * sizeof (char ));
56
- if (_buffer == NULL ) return ;
57
- _udp.read (_buffer, _currentPacketSize);
58
- _dnsHeader = (DNSHeader*) _buffer;
59
-
60
- if (_dnsHeader->QR == DNS_QR_QUERY &&
61
- _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
62
- requestIncludesOnlyOneQuestion () &&
63
- (_domainName == " *" || getDomainNameWithoutWwwPrefix () == _domainName)
53
+ uint8_t * buffer = reinterpret_cast <uint8_t *>(malloc (packetSize));
54
+ if (buffer == NULL ) return ;
55
+
56
+ _udp.read (buffer, packetSize);
57
+
58
+ DNSHeader* dnsHeader = reinterpret_cast <DNSHeader*>(buffer);
59
+
60
+ if (dnsHeader->QR == DNS_QR_QUERY &&
61
+ dnsHeader->OPCode == DNS_OPCODE_QUERY &&
62
+ requestIncludesOnlyOneQuestion (dnsHeader) &&
63
+ (_domainName == " *" || getDomainNameWithoutWwwPrefix (buffer, packetSize) == _domainName)
64
64
)
65
65
{
66
- replyWithIP ();
66
+ replyWithIP (buffer, packetSize );
67
67
}
68
- else if (_dnsHeader ->QR == DNS_QR_QUERY)
68
+ else if (dnsHeader ->QR == DNS_QR_QUERY)
69
69
{
70
- replyWithCustomCode ();
70
+ replyWithCustomCode (buffer, packetSize );
71
71
}
72
72
73
- free (_buffer);
74
- _buffer = NULL ;
73
+ free (buffer);
75
74
}
76
75
}
77
76
78
- bool DNSServer::requestIncludesOnlyOneQuestion ()
77
+ bool DNSServer::requestIncludesOnlyOneQuestion (const DNSHeader* dnsHeader )
79
78
{
80
- return ntohs (_dnsHeader ->QDCount ) == 1 &&
81
- _dnsHeader ->ANCount == 0 &&
82
- _dnsHeader ->NSCount == 0 &&
83
- _dnsHeader ->ARCount == 0 ;
79
+ return ntohs (dnsHeader ->QDCount ) == 1 &&
80
+ dnsHeader ->ANCount == 0 &&
81
+ dnsHeader ->NSCount == 0 &&
82
+ dnsHeader ->ARCount == 0 ;
84
83
}
85
84
86
- String DNSServer::getDomainNameWithoutWwwPrefix ()
85
+ String DNSServer::getDomainNameWithoutWwwPrefix (const uint8_t * buffer, size_t packetSize )
87
86
{
88
- String parsedDomainName = " " ;
89
- if (_buffer == NULL ) return parsedDomainName;
90
- unsigned char *start = _buffer + 12 ;
91
- if (*start == 0 )
92
- {
93
- return parsedDomainName;
94
- }
95
- int pos = 0 ;
96
- while (true )
87
+ String parsedDomainName;
88
+
89
+ const uint8_t * pos = buffer + sizeof (DNSHeader);
90
+ const uint8_t * end = buffer + packetSize;
91
+
92
+ // to minimize reallocations due to concats below
93
+ // we reserve enough space that a median or average domain
94
+ // name size cold be easily contained without a reallocation
95
+ // - max size would be 253, in 2013, average is 11 and max was 42
96
+ //
97
+ parsedDomainName.reserve (32 );
98
+
99
+ uint8_t labelLength = *pos;
100
+
101
+ while (true )
97
102
{
98
- unsigned char labelLength = *(start + pos);
99
- for (int i = 0 ; i < labelLength; i++)
103
+ if (labelLength == 0 )
104
+ {
105
+ // no more labels
106
+ downcaseAndRemoveWwwPrefix (parsedDomainName);
107
+ return parsedDomainName;
108
+ }
109
+
110
+ // append next label
111
+ for (int i = 0 ; i < labelLength && pos < end; i++)
100
112
{
101
113
pos++;
102
- parsedDomainName += ( char )*(start + pos);
114
+ parsedDomainName += static_cast < char >(* pos);
103
115
}
104
- pos++;
105
- if (*(start + pos) == 0 )
116
+
117
+ if (pos >= end )
106
118
{
107
- downcaseAndRemoveWwwPrefix (parsedDomainName);
108
- return parsedDomainName;
119
+ // malformed packet, return an empty domain name
120
+ parsedDomainName = " " ;
121
+ return parsedDomainName;
109
122
}
110
123
else
111
124
{
112
- parsedDomainName += " ." ;
125
+ // next label
126
+ pos++;
127
+ labelLength = *pos;
128
+
129
+ // if there is another label, add delimiter
130
+ if (labelLength != 0 )
131
+ {
132
+ parsedDomainName += " ." ;
133
+ }
113
134
}
114
135
}
115
136
}
116
137
117
- void DNSServer::replyWithIP ()
138
+ void DNSServer::replyWithIP (uint8_t * buffer, size_t packetSize )
118
139
{
119
- if (_buffer == NULL ) return ;
120
- _dnsHeader->QR = DNS_QR_RESPONSE;
121
- _dnsHeader->ANCount = _dnsHeader->QDCount ;
122
- _dnsHeader->QDCount = _dnsHeader->QDCount ;
123
- // _dnsHeader->RA = 1;
140
+ DNSHeader* dnsHeader = reinterpret_cast <DNSHeader*>(buffer);
141
+
142
+ dnsHeader->QR = DNS_QR_RESPONSE;
143
+ dnsHeader->ANCount = dnsHeader->QDCount ;
144
+ dnsHeader->QDCount = dnsHeader->QDCount ;
145
+ // dnsHeader->RA = 1;
124
146
125
147
_udp.beginPacket (_udp.remoteIP (), _udp.remotePort ());
126
- _udp.write (_buffer, _currentPacketSize );
148
+ _udp.write (buffer, packetSize );
127
149
128
150
_udp.write ((uint8_t )192 ); // answer name is a pointer
129
151
_udp.write ((uint8_t )12 ); // pointer to offset at 0x00c
@@ -142,22 +164,26 @@ void DNSServer::replyWithIP()
142
164
_udp.write (_resolvedIP, sizeof (_resolvedIP));
143
165
_udp.endPacket ();
144
166
145
-
146
-
147
167
#ifdef DEBUG_ESP_DNS
148
168
DEBUG_ESP_PORT.printf (" DNS responds: %s for %s\n " ,
149
- IPAddress (_resolvedIP).toString ().c_str (), getDomainNameWithoutWwwPrefix ().c_str () );
169
+ IPAddress (_resolvedIP).toString ().c_str (), getDomainNameWithoutWwwPrefix (buffer, packetSize ).c_str () );
150
170
#endif
151
171
}
152
172
153
- void DNSServer::replyWithCustomCode ()
173
+ void DNSServer::replyWithCustomCode (uint8_t * buffer, size_t packetSize )
154
174
{
155
- if (_buffer == NULL ) return ;
156
- _dnsHeader->QR = DNS_QR_RESPONSE;
157
- _dnsHeader->RCode = (unsigned char )_errorReplyCode;
158
- _dnsHeader->QDCount = 0 ;
175
+ if (packetSize < sizeof (DNSHeader))
176
+ {
177
+ return ;
178
+ }
179
+
180
+ DNSHeader* dnsHeader = reinterpret_cast <DNSHeader*>(buffer);
181
+
182
+ dnsHeader->QR = DNS_QR_RESPONSE;
183
+ dnsHeader->RCode = (unsigned char )_errorReplyCode;
184
+ dnsHeader->QDCount = 0 ;
159
185
160
186
_udp.beginPacket (_udp.remoteIP (), _udp.remotePort ());
161
- _udp.write (_buffer , sizeof (DNSHeader));
187
+ _udp.write (buffer , sizeof (DNSHeader));
162
188
_udp.endPacket ();
163
189
}
0 commit comments