Skip to content

Commit 4c1cb6b

Browse files
authored
fix: Responding to bogus frames #61 (#66)
as per @IanAber prevent sending STATUS_ILLEGAL_FUNCTION on a bogus frame: - `validateRequest()`: move CRC and validate address to start of procedure Some extras for extra snappy performance optimalisations: - `relevantAddress()`: keep the check it local in , since we provide the `unitAddress` to check for broadcast. - `validateRequest()`: keep is_Broadcast check local , it's all here i.s.o. calling isBroadcast() => `calling readUnitAddress()` : inline with `createResponse()` - `executeCallback`: remove bool `isbroadcast` and avoid thus extra branch check and memory usage
1 parent 387f713 commit 4c1cb6b

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

src/ModbusSlave.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,9 @@ bool Modbus::readRequest()
588588
*/
589589
bool Modbus::relevantAddress(uint8_t unitAddress)
590590
{
591-
// Every device should listen to broadcast messages.
592-
if (unitAddress==MODBUS_BROADCAST_ADDRESS)
591+
// Every device should listen to broadcast messages,
592+
// keep the check it local, since we provide the unitAddress
593+
if (unitAddress == MODBUS_BROADCAST_ADDRESS)
593594
{
594595
return true;
595596
}
@@ -613,6 +614,17 @@ bool Modbus::relevantAddress(uint8_t unitAddress)
613614
*/
614615
bool Modbus::validateRequest()
615616
{
617+
// Check the crc, and if it isn't correct ignore the request.
618+
uint16_t crc = readCRC(_requestBuffer, _requestBufferLength);
619+
if (Modbus::calculateCRC(_requestBuffer, _requestBufferLength - MODBUS_CRC_LENGTH) != crc)
620+
{
621+
return false;
622+
}
623+
// Check that the message was addressed to us
624+
if (!Modbus::relevantAddress(_requestBuffer[MODBUS_ADDRESS_INDEX]))
625+
{
626+
return false;
627+
}
616628
// The minimum buffer size (1 x Address, 1 x Function, n x Data, 2 x CRC).
617629
uint16_t expected_requestBufferSize = MODBUS_FRAME_SIZE;
618630

@@ -621,7 +633,7 @@ bool Modbus::validateRequest()
621633
{
622634
case FC_READ_EXCEPTION_STATUS:
623635
// Broadcast is not supported, so ignore this request.
624-
if (isBroadcast())
636+
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
625637
{
626638
return false;
627639
}
@@ -632,7 +644,7 @@ bool Modbus::validateRequest()
632644
case FC_READ_HOLDING_REGISTERS: // Read holding registers (analog read).
633645
case FC_READ_INPUT_REGISTERS: // Read input registers (analog read).
634646
// Broadcast is not supported, so ignore this request.
635-
if (isBroadcast())
647+
if (_requestBuffer[MODBUS_ADDRESS_INDEX] == MODBUS_BROADCAST_ADDRESS)
636648
{
637649
return false;
638650
}
@@ -672,13 +684,6 @@ bool Modbus::validateRequest()
672684
// Set the length to be read from the request to the calculated expected length.
673685
_requestBufferLength = expected_requestBufferSize;
674686

675-
// Check the crc, and if it isn't correct ignore the request.
676-
uint16_t crc = readCRC(_requestBuffer, _requestBufferLength);
677-
if (Modbus::calculateCRC(_requestBuffer, _requestBufferLength - MODBUS_CRC_LENGTH) != crc)
678-
{
679-
return false;
680-
}
681-
682687
return true;
683688
}
684689

@@ -812,13 +817,11 @@ uint8_t Modbus::createResponse()
812817
*/
813818
uint8_t Modbus::executeCallback(uint8_t slaveAddress, uint8_t callbackIndex, uint16_t address, uint16_t length)
814819
{
815-
bool isBroadcast = slaveAddress == MODBUS_BROADCAST_ADDRESS;
816-
817820
// Search for the correct slave to execute callback on.
818821
for (uint8_t i = 0; i < _numberOfSlaves; ++i)
819822
{
820823
ModbusCallback callback = _slaves[i].cbVector[callbackIndex];
821-
if (isBroadcast)
824+
if (slaveAddress == MODBUS_BROADCAST_ADDRESS)
822825
{
823826
if (callback)
824827
{
@@ -837,8 +840,9 @@ uint8_t Modbus::executeCallback(uint8_t slaveAddress, uint8_t callbackIndex, uin
837840
}
838841
}
839842
}
843+
// No return in loop for a Broadcast thus return here without error if it's a Broadcast!
844+
return slaveAddress == MODBUS_BROADCAST_ADDRESS ? STATUS_ACKNOWLEDGE : STATUS_ILLEGAL_FUNCTION;
840845

841-
return isBroadcast ? STATUS_OK : STATUS_ILLEGAL_FUNCTION;
842846
}
843847

844848
/**

0 commit comments

Comments
 (0)