@@ -13,7 +13,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName,
1313 const IPAddress &resolvedIP)
1414{
1515 _port = port;
16- _buffer = NULL ;
16+
1717 _domainName = domainName;
1818 _resolvedIP[0 ] = resolvedIP[0 ];
1919 _resolvedIP[1 ] = resolvedIP[1 ];
@@ -36,8 +36,6 @@ void DNSServer::setTTL(const uint32_t &ttl)
3636void DNSServer::stop ()
3737{
3838 _udp.stop ();
39- free (_buffer);
40- _buffer = NULL ;
4139}
4240
4341void DNSServer::downcaseAndRemoveWwwPrefix (String &domainName)
@@ -48,82 +46,106 @@ void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
4846
4947void DNSServer::processNextRequest ()
5048{
51- _currentPacketSize = _udp.parsePacket ();
52- if (_currentPacketSize)
49+ size_t packetSize = _udp.parsePacket ();
50+
51+ if (packetSize >= sizeof (DNSHeader))
5352 {
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)
6464 )
6565 {
66- replyWithIP ();
66+ replyWithIP (buffer, packetSize );
6767 }
68- else if (_dnsHeader ->QR == DNS_QR_QUERY)
68+ else if (dnsHeader ->QR == DNS_QR_QUERY)
6969 {
70- replyWithCustomCode ();
70+ replyWithCustomCode (buffer, packetSize );
7171 }
7272
73- free (_buffer);
74- _buffer = NULL ;
73+ free (buffer);
7574 }
7675}
7776
78- bool DNSServer::requestIncludesOnlyOneQuestion ()
77+ bool DNSServer::requestIncludesOnlyOneQuestion (const DNSHeader* dnsHeader )
7978{
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 ;
8483}
8584
86- String DNSServer::getDomainNameWithoutWwwPrefix ()
85+ String DNSServer::getDomainNameWithoutWwwPrefix (const uint8_t * buffer, size_t packetSize )
8786{
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 )
97102 {
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++)
100112 {
101113 pos++;
102- parsedDomainName += ( char )*(start + pos);
114+ parsedDomainName += static_cast < char >(* pos);
103115 }
104- pos++;
105- if (*(start + pos) == 0 )
116+
117+ if (pos >= end )
106118 {
107- downcaseAndRemoveWwwPrefix (parsedDomainName);
108- return parsedDomainName;
119+ // malformed packet, return an empty domain name
120+ parsedDomainName = " " ;
121+ return parsedDomainName;
109122 }
110123 else
111124 {
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+ }
113134 }
114135 }
115136}
116137
117- void DNSServer::replyWithIP ()
138+ void DNSServer::replyWithIP (uint8_t * buffer, size_t packetSize )
118139{
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;
124146
125147 _udp.beginPacket (_udp.remoteIP (), _udp.remotePort ());
126- _udp.write (_buffer, _currentPacketSize );
148+ _udp.write (buffer, packetSize );
127149
128150 _udp.write ((uint8_t )192 ); // answer name is a pointer
129151 _udp.write ((uint8_t )12 ); // pointer to offset at 0x00c
@@ -142,22 +164,26 @@ void DNSServer::replyWithIP()
142164 _udp.write (_resolvedIP, sizeof (_resolvedIP));
143165 _udp.endPacket ();
144166
145-
146-
147167 #ifdef DEBUG_ESP_DNS
148168 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 () );
150170 #endif
151171}
152172
153- void DNSServer::replyWithCustomCode ()
173+ void DNSServer::replyWithCustomCode (uint8_t * buffer, size_t packetSize )
154174{
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 ;
159185
160186 _udp.beginPacket (_udp.remoteIP (), _udp.remotePort ());
161- _udp.write (_buffer , sizeof (DNSHeader));
187+ _udp.write (buffer , sizeof (DNSHeader));
162188 _udp.endPacket ();
163189}
0 commit comments