1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-04 18:03:20 +03:00

Compressed dns (#3769)

* Add UdpContext seek and tell

* Add support for DNS compressed messages

* mDNS compressed pointer: Validate offset before jumping
This commit is contained in:
Jonatan Olofsson 2018-03-16 13:46:35 +01:00 committed by Develo
parent 836c7da8cc
commit 461c922586
3 changed files with 89 additions and 21 deletions

1
.gitignore vendored
View File

@ -19,3 +19,4 @@ boards.local.txt
*.gcno
*.gcda
*.o
*.a

View File

@ -27,6 +27,7 @@ extern "C" {
void esp_yield();
void esp_schedule();
#include "lwip/init.h" // LWIP_VERSION_
#include <assert.h>
}
@ -143,6 +144,21 @@ public:
return _rx_buf->len - _rx_buf_offset;
}
size_t tell() const
{
return _rx_buf_offset;
}
void seek(const size_t pos)
{
assert(isValidOffset(pos));
_rx_buf_offset = pos;
}
bool isValidOffset(const size_t pos) const {
return (pos <= _rx_buf->len);
}
uint32_t getRemoteAddress()
{
if (!_rx_buf)
@ -203,7 +219,7 @@ public:
int read()
{
if (!_rx_buf || _rx_buf_offset == _rx_buf->len)
if (!_rx_buf || _rx_buf_offset >= _rx_buf->len)
return -1;
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
@ -361,6 +377,9 @@ private:
void _consume(size_t size)
{
_rx_buf_offset += size;
if (_rx_buf_offset > _rx_buf->len) {
_rx_buf_offset = _rx_buf->len;
}
}
void _recv(udp_pcb *upcb, pbuf *pb,

View File

@ -542,15 +542,33 @@ void MDNSResponder::_parsePacket(){
while (numAnswers--) {
// Read name
stringsRead = 0;
size_t last_bufferpos = 0;
do {
tmp8 = _conn_read8();
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
tmp8 = _conn_read8();
break;
}
if (tmp8 == 0x00) { // End of name
break;
}
if (tmp8 & 0xC0) { // Compressed pointer
uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8();
if (_conn->isValidOffset(offset)) {
last_bufferpos = _conn->tell();
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.print("Compressed pointer, jumping from ");
DEBUG_ESP_PORT.print(last_bufferpos);
DEBUG_ESP_PORT.print(" to ");
DEBUG_ESP_PORT.println(offset);
#endif
_conn->seek(offset);
tmp8 = _conn_read8();
}
else {
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.print("Skipping malformed compressed pointer");
#endif
tmp8 = _conn_read8();
break;
}
}
if(stringsRead > 3){
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.println("failed to read the response name");
@ -577,6 +595,14 @@ void MDNSResponder::_parsePacket(){
}
stringsRead++;
} while (true);
if (last_bufferpos > 0)
{
_conn->seek(last_bufferpos);
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.print("Compressed pointer, jumping back to ");
DEBUG_ESP_PORT.println(last_bufferpos);
#endif
}
uint16_t answerType = _conn_read16(); // Read type
uint16_t answerClass = _conn_read16(); // Read class
@ -635,32 +661,54 @@ void MDNSResponder::_parsePacket(){
uint16_t answerPrio = _conn_read16(); // Read priority
uint16_t answerWeight = _conn_read16(); // Read weight
answerPort = _conn_read16(); // Read port
last_bufferpos = 0;
(void) answerPrio;
(void) answerWeight;
// Read hostname
tmp8 = _conn_read8();
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
if (tmp8 & 0xC0) { // Compressed pointer
uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8();
if (_conn->isValidOffset(offset)) {
last_bufferpos = _conn->tell();
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.println("Skipping compressed pointer");
DEBUG_ESP_PORT.print("Compressed pointer, jumping from ");
DEBUG_ESP_PORT.print(last_bufferpos);
DEBUG_ESP_PORT.print(" to ");
DEBUG_ESP_PORT.println(offset);
#endif
tmp8 = _conn_read8();
_conn->seek(offset);
tmp8 = _conn_read8();
}
else {
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.print("Skipping malformed compressed pointer");
#endif
tmp8 = _conn_read8();
break;
}
}
else {
_conn_readS(answerHostName, tmp8);
answerHostName[tmp8] = '\0';
_conn_readS(answerHostName, tmp8);
answerHostName[tmp8] = '\0';
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.printf("SRV %d ", tmp8);
for (int n = 0; n < tmp8; n++) {
DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]);
}
DEBUG_ESP_PORT.printf("\n%s\n", answerHostName);
DEBUG_ESP_PORT.printf("SRV %d ", tmp8);
for (int n = 0; n < tmp8; n++) {
DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]);
}
DEBUG_ESP_PORT.printf("\n%s\n", answerHostName);
#endif
if (answerRdlength - (6 + 1 + tmp8) > 0) { // Skip any remaining rdata
_conn_readS(hostName, answerRdlength - (6 + 1 + tmp8));
}
if (last_bufferpos > 0)
{
_conn->seek(last_bufferpos);
tmp8 = 2; // Size of compression octets
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.print("Compressed pointer, jumping back to ");
DEBUG_ESP_PORT.println(last_bufferpos);
#endif
}
if (answerRdlength - (6 + 1 + tmp8) > 0) { // Skip any remaining rdata
_conn_readS(hostName, answerRdlength - (6 + 1 + tmp8));
}
}
@ -675,7 +723,7 @@ void MDNSResponder::_parsePacket(){
DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8);
#endif
for (int n = 0; n < answerRdlength; n++)
(void)_conn_read8();
(void)_conn_read8();
}
if ((partsCollected == 0x0F) && serviceMatch) {