forked from andresarmento/modbus-esp8266
-
Notifications
You must be signed in to change notification settings - Fork 209
Closed
Description
Lets say the Slave receives a packet like this, with a faulty length field
packet = (
#Request - modbus_read_coil
#Block - modbus_head
b'\x01\x00' # Word - transId
b'\x00\x00' # Word - protoId
+ b'\x00' * 2 + # Word -length
b'\xff' # Byte - unit Identifier
#Block - pdu
b'\x01' # Byte - funcCode read coil memory
b'\x00\x01' # Word - start_address
b'\x00\x00' # Word - quantity
)After correcty registering that the request is faulty, the slave will response with a malformed modbus packet with only
8 bytes length, since:
_len first gets set to 2 here:
Lines 454 to 457 in 2996663
| void Modbus::exceptionResponse(FunctionCode fn, ResultCode excode) { | |
| free(_frame); | |
| _len = 2; | |
| _frame = (uint8_t*) malloc(_len); |
then substracted by 1 here:
modbus-esp8266/src/ModbusTCPTemplate.h
Lines 272 to 276 in 2996663
| if (_len > MODBUSIP_MAXFRAME) { // Length is over MODBUSIP_MAXFRAME | |
| exceptionResponse((FunctionCode)tcpclient[n]->read(), EX_SLAVE_FAILURE); | |
| _len--; // Subtract for read byte | |
| for (uint8_t i = 0; tcpclient[n]->available() && i < _len; i++) // Drop rest of packet | |
| tcpclient[n]->read(); |
and reused for calculating the size of the response packet:
modbus-esp8266/src/ModbusTCPTemplate.h
Lines 336 to 343 in 2996663
| if (_reply != REPLY_OFF) { | |
| _MBAP.length = __swap_16(_len+1); // _len+1 for last byte from MBAP | |
| size_t send_len = (uint16_t)_len + sizeof(_MBAP.raw); | |
| uint8_t sbuf[send_len]; | |
| memcpy(sbuf, _MBAP.raw, sizeof(_MBAP.raw)); | |
| memcpy(sbuf + sizeof(_MBAP.raw), _frame, _len); | |
| tcpclient[n]->write(sbuf, send_len); | |
| //tcpclient[n]->flush(); |
The exception code gets lost in that process.
Also
modbus-esp8266/src/ModbusTCPTemplate.h
Line 275 in 2996663
| for (uint8_t i = 0; tcpclient[n]->available() && i < _len; i++) // Drop rest of packet |
is only dropping 1 byte because of
_len always being 1 at this point