| 1 | initial version |
There doesn't seem to be a protocol spec for Modbus UDP on the Modbus site:
Specifications and Implementation Guides
Modbus Technical Resources - other sites lists several libraries that have implemented Modbus UDP. They are all different languages and it hasn't been verified if they all agree on what the UDP PDU should look like.
Thank you for providing the sample captures.
At this point it's worth opening a Wireshark enhancement request to add this to the Modbus UDP dissector.
It is a bit more than I want to tackle and also not sure about corner cases like trailer bytes after the Modus PDU or if the PDU is large and is split into IP fragments.
Enhancement requests are added as a Feature Request in the Wireshark Issues on GitLab.
Until it can be added properly, here is a lua script to decode UDP PDUs containing multiple ADUs.
No warranty - Caveat emptor - but seems to work with the sample UDP capture provided.
-- Modbus_ADUs.lua
-- https://ask.wireshark.org/question/37817/modbus-udp-versus-tcp/
--
-- Step 1 - document as you go. See header above and set_plugin_info().
local modbus_adus_info =
{
version = "1.0.0",
author = "Good Coder",
description = "Modbus UDP - multiple ADUs",
repository = "Floppy in top drawer"
}
set_plugin_info(modbus_adus_info)
-- grab the original dissector to call from our loop below
local mbudp_dissector = Dissector.get("mbudp")
-- Step 2 - create a protocol to attach new fields to
local modbus_adus_p = Proto.new("modbus_adus","Modbus/UDP/ADUs")
-- Steps 3 and 4 deleted for readability
-- See https://wiki.wireshark.org/lua/ for original EASYPOST.lua with all steps
-- Step 5 - create the dissector function that will run on each frame/packet
function modbus_adus_p.dissector(tvb,pinfo,tree)
local subtree = nil
local tvb_len =tvb:captured_len()
local offset = 0
if not subtree then
subtree = tree:add(modbus_adus_p)
end
while offset < tvb_len do
new_tvb = tvb:range(offset):tvb()
mbudp_len = new_tvb:range(4,2):int() + 6
mbudp_dissector:call(new_tvb, pinfo, tree)
offset = offset + mbudp_len
end
end
-- Step 6 - replace original mbudp dissector with modbus_adus dissector
local udp_port_table = DissectorTable.get("udp.port")
udp_port_table:set(502, modbus_adus_p)
Frame 2: Packet, 504 bytes on wire (4032 bits), 504 bytes captured (4032 bits) on interface xxx Ethernet II, Src: xxx, Dst: xxx Internet Protocol Version 4, Src: xxx (xxx), Dst: xxx (xxx) User Datagram Protocol, Src Port: 502, Dst Port: 56014 Modbus/UDP/ADUs Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus
| 2 | No.2 Revision |
There doesn't seem to be a protocol spec for Modbus UDP on the Modbus site:
Specifications and Implementation Guides
Modbus Technical Resources - other sites lists several libraries that have implemented Modbus UDP. They are all different languages and it hasn't been verified if they all agree on what the UDP PDU should look like.
Thank you for providing the sample captures.
At this point it's worth opening a Wireshark enhancement request to add this to the Modbus UDP dissector.
It is a bit more than I want to tackle and also not sure about corner cases like trailer bytes after the Modus PDU or if the PDU is large and is split into IP fragments.
Enhancement requests are added as a Feature Request in the Wireshark Issues on GitLab.
Until it can be added properly, here is a lua script to decode UDP PDUs containing multiple ADUs.
No warranty - Caveat emptor - but seems to work with the sample UDP capture provided.
-- Modbus_ADUs.lua
-- https://ask.wireshark.org/question/37817/modbus-udp-versus-tcp/
--
-- Step 1 - document as you go. See header above and set_plugin_info().
local modbus_adus_info =
{
version = "1.0.0",
author = "Good Coder",
description = "Modbus UDP - multiple ADUs",
repository = "Floppy in top drawer"
}
set_plugin_info(modbus_adus_info)
-- grab the original dissector to call from our loop below
local mbudp_dissector = Dissector.get("mbudp")
-- Step 2 - create a protocol to attach new fields to
local modbus_adus_p = Proto.new("modbus_adus","Modbus/UDP/ADUs")
-- Steps 3 and 4 deleted for readability
-- See https://wiki.wireshark.org/lua/ for original EASYPOST.lua with all steps
-- Step 5 - create the dissector function that will run on each frame/packet
function modbus_adus_p.dissector(tvb,pinfo,tree)
local subtree = nil
local tvb_len =tvb:captured_len()
local offset = 0
if not subtree then
subtree = tree:add(modbus_adus_p)
end
while offset < tvb_len do
new_tvb = tvb:range(offset):tvb()
mbudp_len = new_tvb:range(4,2):int() + 6
mbudp_dissector:call(new_tvb, pinfo, tree)
offset = offset + mbudp_len
end
end
-- Step 6 - replace original mbudp dissector with modbus_adus dissector
local udp_port_table = DissectorTable.get("udp.port")
udp_port_table:set(502, modbus_adus_p)
Frame 2: Packet, 504 bytes on wire (4032 bits), 504 bytes captured (4032 bits) on interface xxx Ethernet II, Src: xxx, Dst: xxx Internet Protocol Version 4, Src: xxx (xxx), Dst: xxx (xxx) User Datagram Protocol, Src Port: 502, Dst Port: 56014 Modbus/UDP/ADUs Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus
| 3 | No.3 Revision |
There doesn't seem to be a protocol spec for Modbus UDP on the Modbus site:
Specifications and Implementation Guides
Modbus Technical Resources - other sites lists several libraries that have implemented Modbus UDP. They are all different languages and it hasn't been verified if they all agree on what the UDP PDU data should look like.
Thank you for providing the sample captures.
At this point it's worth opening a Wireshark enhancement request to add this to the Modbus UDP dissector.
It is a bit more than I want to tackle and also not sure about corner cases like trailer bytes after the Modus PDU data or if the PDU data is large and is split into IP fragments.
Enhancement requests are added as a Feature Request in the Wireshark Issues on GitLab.
Until it can be added properly, here is a lua script to decode UDP PDUs data containing multiple ADUs.
No warranty - Caveat emptor - but seems to work with the sample UDP capture provided.
-- Modbus_ADUs.lua
-- https://ask.wireshark.org/question/37817/modbus-udp-versus-tcp/
--
-- Step 1 - document as you go. See header above and set_plugin_info().
local modbus_adus_info =
{
version = "1.0.0",
author = "Good Coder",
description = "Modbus UDP - multiple ADUs",
repository = "Floppy in top drawer"
}
set_plugin_info(modbus_adus_info)
-- grab the original dissector to call from our loop below
local mbudp_dissector = Dissector.get("mbudp")
-- Step 2 - create a protocol to attach new fields to
local modbus_adus_p = Proto.new("modbus_adus","Modbus/UDP/ADUs")
-- Steps 3 and 4 deleted for readability
-- See https://wiki.wireshark.org/lua/ for original EASYPOST.lua with all steps
-- Step 5 - create the dissector function that will run on each frame/packet
function modbus_adus_p.dissector(tvb,pinfo,tree)
local subtree = nil
local tvb_len =tvb:captured_len()
local offset = 0
if not subtree then
subtree = tree:add(modbus_adus_p)
end
while offset < tvb_len do
new_tvb = tvb:range(offset):tvb()
mbudp_len = new_tvb:range(4,2):int() + 6
mbudp_dissector:call(new_tvb, pinfo, tree)
offset = offset + mbudp_len
end
end
-- Step 6 - replace original mbudp dissector with modbus_adus dissector
local udp_port_table = DissectorTable.get("udp.port")
udp_port_table:set(502, modbus_adus_p)
Frame 2: Packet, 504 bytes on wire (4032 bits), 504 bytes captured (4032 bits) on interface xxx Ethernet II, Src: xxx, Dst: xxx Internet Protocol Version 4, Src: xxx (xxx), Dst: xxx (xxx) User Datagram Protocol, Src Port: 502, Dst Port: 56014 Modbus/UDP/ADUs Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus Modbus/UDP Modbus