Modbus TCP illegal function exception

I'm using the mobuds TCP packet template in the transmit pane to test reading some holding registers. So default I'm using the "Modbus TCP read" option and fill in all the necassary options. After trying to use the "Modbus TCP read/write multiple" and switched back to "Modbus TCP read" I cant read any register anymore without getting the IllegalFunction Exception. I have tried resetting all the settings back to default, even reinstalled IOninja but with no success.

I can reproduce this issue on another PC. When I'm comparing my settings on a fresh install of IOninja, the issue seems to be the length field of ADU what is updating wrong. When I disable "auto-update length" and fill in the value from the PC that is working correctly, it's working, but when I enable "auto-update length" again its throwing the illegalfunction exceptions again.

Is this is bug or am I missing something?

Succesvol reading with auto-update disabled
Schermafbeelding 2023-11-15 095918.png

Failed to read with auto-update enabled
Schermafbeelding 2023-11-15 095902.png

Not exactly a bug but rather a missing misuse protection.

So, what's happening? The automatic calculation of Modbus TCP frames is done like this:

void updateModbusTcpLength(void* p) {
	size_t size = dynamic sizeof(p);
	if (size < sizeof(io.ModbusTcpAduHdr))
		return;

	((io.ModbusTcpAduHdr*)p).m_length = size - offsetof(io.ModbusTcpAduHdr.m_deviceAddress);
}

Basically, m_length is set to the length of the payload (from m_deviceAddress and to the very end of the packet).

In your case, the packet length is 17, offset of m_deviceAddress is 6, so m_length is set to 11. However, the size of Modbus TCP read should always be 12 (not 17). If you erase the trailing 5 bytes from your packet, it will work as expected.

That should solve the issue; for more relevant details, read on.

By design, packet templates never allow creating a packet shorter than the template itself. However, it's allowed to add any suffix after the templated headers (that would be required for Modbus TCP write, for instance).

In ioninja-5.1.0 we added the fixedSize attribute exactly to prevent unintentional misuse in case of packets that should never grow longer than the template itself.

Modbus TCP read is exactly this kind of packet, but in the current version of IO Ninja, it's missing the fixedSize attribute. We will add it in the next release of IO Ninja, but in the meantime, you can fix it by yourself. To do so, please open ioninja/scripts/packets/ModbusTcp.jnc in any text editor, locate the definition of ModbuTcpReadPacket (in the very beginning), and modify it as such:

[ 
	displayName = "Modbus TCP read",
	fixedSize
]
struct ModbusTcpReadPacket {
// ...

In order to apply it, please reload this template into the Packet Template editor (Edit packet template -> Load stock script -> Modbus TCP).

Let me know if this works for you.

Thanks for the detailed explanation and information Vladimir! This fixes my issue and nice to hear that it will be solved in the next release. Thank you very much! 🙂