-
Notifications
You must be signed in to change notification settings - Fork 715
#1754 Add Modbus Support #1823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
#1754 Add Modbus Support #1823
Conversation
yahyayozo
commented
May 18, 2025
- Add ModbusLayer first implementation with header parsing only (no test included)
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## dev #1823 +/- ##
==========================================
+ Coverage 82.84% 82.88% +0.03%
==========================================
Files 291 294 +3
Lines 51553 51663 +110
Branches 11395 11172 -223
==========================================
+ Hits 42709 42820 +111
+ Misses 8022 8020 -2
- Partials 822 823 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@seladb I've prepared only 1 constructor which initiates the layer with default fields values |
@yahyayozo we usually have at least 2 c'tors, sometimes more:
|
…sPlus into feature/modbus
Hi @seladb can you please guide me briefly on how to add tests for my ModbusLayer for parsing/crafting headers? As I want to pass to function types request/response after testing the header part. |
@yahyayozo sure! You can learn about tests here: https://pcapplusplus.github.io/docs/tests At a high level:
Please look at similar tests that were written for other layers and follow the same patterns. Please let me know if you have any questions. |
@seladb I'll add tests for the headers crafting/parsing implementation and then you can a review before we move to adding the different PDU types |
… instead of raw data
@yahyayozo CI fails, can you please look into it? 🙁 |
|
@seladb I'll check further |
@seladb all the pre-commit checks have passed + the build was successful |
… transaction ID, unit ID, and function code
…sPlus into feature/modbus
@seladb CI passed! can you please make a review of the already done work before moving forward? |
@seladb Hi, can you please check the progress I've reached until now? please leave comments on any part that needs adjustement |
@yahyayozo sure, I'm sorry for the long delay. I'll take a look shortly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the pcap/pcapng file you used also?
It'll also help me understand the protocol better
Packet++/header/ProtocolType.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add this protoclo to README.md
?
} | ||
|
||
/// @return A pointer to the MODBUS header | ||
modbus_common_header* getModbusHeader() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a private method?
#pragma pack(push, 1) | ||
/// @struct modbus_common_header | ||
/// MODBUS Application Protocol header | ||
struct modbus_common_header |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think we can call it just modbus_header
?
|
||
/// @brief Check if a port is a valid MODBUS port | ||
/// @param port | ||
/// @return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: complete the return documentation?
std::string toString() const override | ||
{ | ||
return "Modbus Layer, Transaction ID: " + std::to_string(getTransactionId()) + | ||
", Protocol ID: " + std::to_string(getProtocolId()) + ", Length: " + std::to_string(getLength()) + | ||
", Unit ID: " + std::to_string(getUnitId()) + | ||
", Function Code: " + std::to_string(getFunctionCode()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Maybe move the implementation to the
.cpp
file to keep the.h
file cleaner? - I'm not sure how Modbus packets look in Wireshark, but probably contain less info? 🤔
|
||
pcpp::ModbusLayer* modbusLayer = packet.getLayerOfType<pcpp::ModbusLayer>(); | ||
PTF_ASSERT_NOT_NULL(modbusLayer); | ||
PTF_ASSERT_EQUAL(modbusLayer->getTransactionId(), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you get a packet where transaction ID is not 0?
PTF_ASSERT_EQUAL(modbusLayer.getFunctionCode(), 3); | ||
PTF_ASSERT_EQUAL(modbusLayer.getHeaderLen(), sizeof(pcpp::modbus_common_header)); | ||
|
||
PTF_ASSERT_EQUAL(modbusLayer.toString(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd test toString()
in ModbusLayerParsingTest
instead of here
#include "EndianPortable.h" | ||
#include "SystemUtils.h" | ||
|
||
PTF_TEST_CASE(ModbusLayerCreationTest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The best way to test layer creation is to compare it to a real packet. You can load ModbusRequest.dat
, extract the modbus layer and compare it to the created packet in this test