Skip to content

Commit 461c922

Browse files
jonatanolofssondevyte
authored andcommitted
Compressed dns (esp8266#3769)
* Add UdpContext seek and tell * Add support for DNS compressed messages * mDNS compressed pointer: Validate offset before jumping
1 parent 836c7da commit 461c922

File tree

3 files changed

+89
-21
lines changed

3 files changed

+89
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ boards.local.txt
1919
*.gcno
2020
*.gcda
2121
*.o
22+
*.a

libraries/ESP8266WiFi/src/include/UdpContext.h

+20-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern "C" {
2727
void esp_yield();
2828
void esp_schedule();
2929
#include "lwip/init.h" // LWIP_VERSION_
30+
#include <assert.h>
3031
}
3132

3233

@@ -143,6 +144,21 @@ class UdpContext
143144
return _rx_buf->len - _rx_buf_offset;
144145
}
145146

147+
size_t tell() const
148+
{
149+
return _rx_buf_offset;
150+
}
151+
152+
void seek(const size_t pos)
153+
{
154+
assert(isValidOffset(pos));
155+
_rx_buf_offset = pos;
156+
}
157+
158+
bool isValidOffset(const size_t pos) const {
159+
return (pos <= _rx_buf->len);
160+
}
161+
146162
uint32_t getRemoteAddress()
147163
{
148164
if (!_rx_buf)
@@ -203,7 +219,7 @@ class UdpContext
203219

204220
int read()
205221
{
206-
if (!_rx_buf || _rx_buf_offset == _rx_buf->len)
222+
if (!_rx_buf || _rx_buf_offset >= _rx_buf->len)
207223
return -1;
208224

209225
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
@@ -361,6 +377,9 @@ class UdpContext
361377
void _consume(size_t size)
362378
{
363379
_rx_buf_offset += size;
380+
if (_rx_buf_offset > _rx_buf->len) {
381+
_rx_buf_offset = _rx_buf->len;
382+
}
364383
}
365384

366385
void _recv(udp_pcb *upcb, pbuf *pb,

libraries/ESP8266mDNS/ESP8266mDNS.cpp

+68-20
Original file line numberDiff line numberDiff line change
@@ -542,15 +542,33 @@ void MDNSResponder::_parsePacket(){
542542
while (numAnswers--) {
543543
// Read name
544544
stringsRead = 0;
545+
size_t last_bufferpos = 0;
545546
do {
546547
tmp8 = _conn_read8();
547-
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
548-
tmp8 = _conn_read8();
549-
break;
550-
}
551548
if (tmp8 == 0x00) { // End of name
552549
break;
553550
}
551+
if (tmp8 & 0xC0) { // Compressed pointer
552+
uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8();
553+
if (_conn->isValidOffset(offset)) {
554+
last_bufferpos = _conn->tell();
555+
#ifdef DEBUG_ESP_MDNS_RX
556+
DEBUG_ESP_PORT.print("Compressed pointer, jumping from ");
557+
DEBUG_ESP_PORT.print(last_bufferpos);
558+
DEBUG_ESP_PORT.print(" to ");
559+
DEBUG_ESP_PORT.println(offset);
560+
#endif
561+
_conn->seek(offset);
562+
tmp8 = _conn_read8();
563+
}
564+
else {
565+
#ifdef DEBUG_ESP_MDNS_RX
566+
DEBUG_ESP_PORT.print("Skipping malformed compressed pointer");
567+
#endif
568+
tmp8 = _conn_read8();
569+
break;
570+
}
571+
}
554572
if(stringsRead > 3){
555573
#ifdef DEBUG_ESP_MDNS_RX
556574
DEBUG_ESP_PORT.println("failed to read the response name");
@@ -577,6 +595,14 @@ void MDNSResponder::_parsePacket(){
577595
}
578596
stringsRead++;
579597
} while (true);
598+
if (last_bufferpos > 0)
599+
{
600+
_conn->seek(last_bufferpos);
601+
#ifdef DEBUG_ESP_MDNS_RX
602+
DEBUG_ESP_PORT.print("Compressed pointer, jumping back to ");
603+
DEBUG_ESP_PORT.println(last_bufferpos);
604+
#endif
605+
}
580606

581607
uint16_t answerType = _conn_read16(); // Read type
582608
uint16_t answerClass = _conn_read16(); // Read class
@@ -635,33 +661,55 @@ void MDNSResponder::_parsePacket(){
635661
uint16_t answerPrio = _conn_read16(); // Read priority
636662
uint16_t answerWeight = _conn_read16(); // Read weight
637663
answerPort = _conn_read16(); // Read port
664+
last_bufferpos = 0;
638665

639666
(void) answerPrio;
640667
(void) answerWeight;
641668

642669
// Read hostname
643670
tmp8 = _conn_read8();
644-
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
671+
if (tmp8 & 0xC0) { // Compressed pointer
672+
uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8();
673+
if (_conn->isValidOffset(offset)) {
674+
last_bufferpos = _conn->tell();
645675
#ifdef DEBUG_ESP_MDNS_RX
646-
DEBUG_ESP_PORT.println("Skipping compressed pointer");
676+
DEBUG_ESP_PORT.print("Compressed pointer, jumping from ");
677+
DEBUG_ESP_PORT.print(last_bufferpos);
678+
DEBUG_ESP_PORT.print(" to ");
679+
DEBUG_ESP_PORT.println(offset);
647680
#endif
648-
tmp8 = _conn_read8();
649-
}
650-
651-
else {
652-
_conn_readS(answerHostName, tmp8);
653-
answerHostName[tmp8] = '\0';
654-
#ifdef DEBUG_ESP_MDNS_RX
655-
DEBUG_ESP_PORT.printf("SRV %d ", tmp8);
656-
for (int n = 0; n < tmp8; n++) {
657-
DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]);
681+
_conn->seek(offset);
682+
tmp8 = _conn_read8();
658683
}
659-
DEBUG_ESP_PORT.printf("\n%s\n", answerHostName);
684+
else {
685+
#ifdef DEBUG_ESP_MDNS_RX
686+
DEBUG_ESP_PORT.print("Skipping malformed compressed pointer");
660687
#endif
661-
if (answerRdlength - (6 + 1 + tmp8) > 0) { // Skip any remaining rdata
662-
_conn_readS(hostName, answerRdlength - (6 + 1 + tmp8));
688+
tmp8 = _conn_read8();
689+
break;
663690
}
664691
}
692+
_conn_readS(answerHostName, tmp8);
693+
answerHostName[tmp8] = '\0';
694+
#ifdef DEBUG_ESP_MDNS_RX
695+
DEBUG_ESP_PORT.printf("SRV %d ", tmp8);
696+
for (int n = 0; n < tmp8; n++) {
697+
DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]);
698+
}
699+
DEBUG_ESP_PORT.printf("\n%s\n", answerHostName);
700+
#endif
701+
if (last_bufferpos > 0)
702+
{
703+
_conn->seek(last_bufferpos);
704+
tmp8 = 2; // Size of compression octets
705+
#ifdef DEBUG_ESP_MDNS_RX
706+
DEBUG_ESP_PORT.print("Compressed pointer, jumping back to ");
707+
DEBUG_ESP_PORT.println(last_bufferpos);
708+
#endif
709+
}
710+
if (answerRdlength - (6 + 1 + tmp8) > 0) { // Skip any remaining rdata
711+
_conn_readS(hostName, answerRdlength - (6 + 1 + tmp8));
712+
}
665713
}
666714

667715
else if (answerType == MDNS_TYPE_A) {
@@ -675,7 +723,7 @@ void MDNSResponder::_parsePacket(){
675723
DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8);
676724
#endif
677725
for (int n = 0; n < answerRdlength; n++)
678-
(void)_conn_read8();
726+
(void)_conn_read8();
679727
}
680728

681729
if ((partsCollected == 0x0F) && serviceMatch) {

0 commit comments

Comments
 (0)