Skip to content
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

create S7COMM protocol and tests #1185

Merged
merged 32 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6791f63
create S7COMM protocol and tests
wivien19 Aug 21, 2023
17c1e4e
add missing override to toString
wivien19 Aug 21, 2023
0bdb8d3
change null to nullptr
wivien19 Aug 21, 2023
4482c6a
systemutils
wivien19 Aug 21, 2023
2ba6f6d
imports in test
wivien19 Aug 21, 2023
d85e738
edit the value of the S7COMM
wivien19 Aug 22, 2023
81d4434
modify toString and add test
wivien19 Aug 22, 2023
f34c2cf
Merge branch 'dev' into S7COMM
wivien19 Sep 5, 2023
46706e9
modify small changes
wivien19 Sep 5, 2023
c8d14f8
Merge remote-tracking branch 'origin/S7COMM' into S7COMM
wivien19 Sep 16, 2023
d9efe40
S7COMM Ack-data header modify and test
wivien19 Sep 18, 2023
32c7558
Merge branch 'dev' into S7COMM
seladb Sep 22, 2023
75238d4
Modify GetHeaderLen
wivien19 Sep 22, 2023
c2f1f2c
Parameter
wivien19 Sep 22, 2023
aed4a41
Parameter length
wivien19 Sep 25, 2023
a5f1533
Parameter length
wivien19 Sep 25, 2023
9ffc140
Merge remote-tracking branch 'origin/S7COMM' into S7COMM
wivien19 Sep 26, 2023
6502dcb
Fix `getParameter()`
seladb Oct 3, 2023
9b76c38
Merge branch 'dev' into S7COMM
seladb Oct 3, 2023
4cd7d02
add error pcap and small modify
wivien19 Oct 11, 2023
0dc3f4d
Merge branch 'dev' into S7COMM
wivien19 Oct 15, 2023
89e04f4
renaming, remove unneccessary elements
wivien19 Oct 18, 2023
a4a30d5
Few fixes
seladb Oct 20, 2023
8e2636f
Few more fixes
seladb Oct 20, 2023
2f01981
Merge branch 'dev' into S7COMM
seladb Oct 20, 2023
43ecad1
renaming, small fixes
wivien19 Oct 24, 2023
f1153d3
Remove spaces
seladb Oct 31, 2023
f702af7
renaming, remove unneccessary element
wivien19 Oct 31, 2023
50640bb
modify the header length and the toString method
wivien19 Nov 3, 2023
e738133
Few more fixes
seladb Nov 6, 2023
3972220
Merge branch 'dev' into S7COMM
seladb Nov 6, 2023
9564367
Add to README
seladb Nov 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Packet++/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_library(
src/PPPoELayer.cpp
src/RadiusLayer.cpp
src/RawPacket.cpp
src/S7commLayer.cpp
src/SdpLayer.cpp
src/SingleCommandTextProtocol.cpp
src/SipLayer.cpp
Expand Down Expand Up @@ -103,6 +104,7 @@ set(public_headers
header/ProtocolType.h
header/RadiusLayer.h
header/RawPacket.h
header/S7commLayer.h
header/SdpLayer.h
header/SingleCommandTextProtocol.h
header/SipLayer.h
Expand Down
2 changes: 1 addition & 1 deletion Packet++/header/CotpLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace pcpp
void computeCalculateFields() override {}

/**
* Currently parses the rest of the packet as a generic payload (PayloadLayer)
* Currently parses the rest of the packet as a S7COMM or generic payload (PayloadLayer)
*/
void parseNextLayer() override;

Expand Down
5 changes: 5 additions & 0 deletions Packet++/header/ProtocolType.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ namespace pcpp
*/
const ProtocolType SLL2 = 0x8000000000000;

/**
* S7COMM protocol
*/
const ProtocolType S7COMM = 0x9000000000000;
seladb marked this conversation as resolved.
Show resolved Hide resolved

/**
* An enum representing OSI model layers
*/
Expand Down
149 changes: 149 additions & 0 deletions Packet++/header/S7commLayer.h
seladb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#ifndef PCAPPLUSPLUS_S7COMMLAYER_H
#define PCAPPLUSPLUS_S7COMMLAYER_H

#include "EthLayer.h"
#include "Layer.h"

namespace pcpp
{
/**
* @struct s7commhdr
* Represents a S7COMM protocol header
*/
#pragma pack(push, 1)
typedef struct
{
/** protocol id */
uint8_t protocol_id;
/** message type */
uint8_t msg_type;
/** redundancy identification (reserved) */
uint16_t reserved;
/** protocol data unit reference */
uint16_t pdu_ref;
/** parameter length */
uint16_t param_length;
/** data length */
uint16_t data_length;
} s7commhdr;
#pragma pack(pop)

/**
* @class S7commLayer
* Represents a S7COMM (S7 Communication7) protocol
*/
class S7commLayer : public Layer
seladb marked this conversation as resolved.
Show resolved Hide resolved
{
public:
/**
* A constructor that allocates a new S7comm header
* @param[in] msg_type The general type of the message
* @param[in] pdu_ref Link responses to their requests
* @param[in] param_length The length of the parameter field
* @param[in] data_length The length of the data field
*/
S7commLayer(uint8_t msg_type, uint16_t pdu_ref, uint16_t param_length, uint16_t data_length);

/**
* A constructor that creates the layer from an existing packet raw data
* @param[in] data A pointer to the raw data (will be casted to @ref s7commhdr)
* @param[in] dataLen Size of the data in bytes
* @param[in] prevLayer A pointer to the previous layer
* @param[in] packet A pointer to the Packet instance where layer will be stored in
*/
S7commLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
: Layer(data, dataLen, prevLayer, packet)
{
m_Protocol = S7COMM;
}

virtual ~S7commLayer() {}

/**
* @return S7comm protocol id
*/
uint8_t getProtocolId() const;

/**
* @return S7comm message type
*/
uint8_t getMsgType() const;

/**
* @return S7comm reserved
*/
uint16_t getReserved() const;
seladb marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return S7comm PDU ref
*/
uint16_t getPduRef() const;

/**
* @return S7comm parameter length
*/
uint16_t getParamLength() const;

/**
* @return S7comm data length
*/
uint16_t getDataLength() const;

/**
* Set the value of the message type
* @param[in] msg_type The value of the message type
*/
void setMsgType(uint8_t msg_type) const;

/**
* Set the value of the PDU ref
* @param[in] pdu_ref The value of the PDU ref
*/
void setPduRef(uint16_t pdu_ref) const;

/**
* Set the value of the parameter length
* @param[in] param_length The value of the parameter length
*/
void setParamLength(uint16_t param_length) const;

/**
* Set the value of the data length
* @param[in] data_length The value of the data length
*/
void setDataLength(uint16_t data_length) const;

/**
* @return Size of @ref s7commhdr
seladb marked this conversation as resolved.
Show resolved Hide resolved
*/
size_t getHeaderLen() const override { return sizeof(s7commhdr); }

/**
* Does nothing for this layer
*/
void computeCalculateFields() override {}

/**
* Does nothing for this layer
seladb marked this conversation as resolved.
Show resolved Hide resolved
*/
void parseNextLayer() override {}

/**
* A static method that takes a byte array and detects whether it is a S7COMM
* @param[in] data A byte array
* @param[in] dataSize The byte array size (in bytes)
* @return True if the data looks like a valid S7COMM layer
*/
static bool isDataValid(const uint8_t *data, size_t dataSize);

std::string toString() const override;

OsiModelLayer getOsiModelLayer() const override { return OsiModelApplicationLayer; }


private:
s7commhdr *getS7commHeader() const { return (s7commhdr *)m_Data; }
};

} // namespace pcpp
#endif // PCAPPLUSPLUS_S7COMMLAYER_H
13 changes: 7 additions & 6 deletions Packet++/src/CotpLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cstring>
#include <iostream>
#include <sstream>
#include "S7commLayer.h"

namespace pcpp
{
Expand All @@ -21,10 +22,7 @@ namespace pcpp
m_Protocol = COTP;
}

std::string CotpLayer::toString() const
{
return "Cotp Layer";
}
std::string CotpLayer::toString() const { return "Cotp Layer"; }

uint8_t CotpLayer::getLength() const { return getCotpHeader()->length; }

Expand All @@ -43,7 +41,7 @@ namespace pcpp
if (!data || dataSize < sizeof(cotphdr))
return false;

return data[1] == 0xf0 && data[0] == 2;
return data[1] == 0xf0 && data[0] == 2;
}

void CotpLayer::parseNextLayer()
Expand All @@ -55,6 +53,9 @@ namespace pcpp
uint8_t *payload = m_Data + headerLen;
size_t payloadLen = m_DataLen - headerLen;

m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
if (S7commLayer::isDataValid(payload, payloadLen))
m_NextLayer = new S7commLayer(payload, payloadLen, this, m_Packet);
else
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
}
} // namespace pcpp
93 changes: 93 additions & 0 deletions Packet++/src/S7commLayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "EndianPortable.h"
#include "TpktLayer.h"

#include <iostream>
#include "TcpLayer.h"
#include "S7commLayer.h"

#include <cstring>
#include <sstream>

namespace pcpp {

S7commLayer::S7commLayer(uint8_t msg_type, uint16_t pdu_ref,
uint16_t param_length, uint16_t data_length) {
const size_t headerLen = sizeof(s7commhdr);
m_DataLen = headerLen;
m_Data = new uint8_t[headerLen];
memset(m_Data, 0, headerLen);
s7commhdr *s7commHdr = (s7commhdr *) m_Data;
s7commHdr->protocol_id = 0x32;
s7commHdr->msg_type = msg_type;
s7commHdr->reserved = 0x0000;
s7commHdr->pdu_ref = htobe16(pdu_ref);
s7commHdr->param_length = htobe16(param_length);
s7commHdr->data_length = htobe16(data_length);
m_Protocol = S7COMM;
}

std::string S7commLayer::toString() const {
std::ostringstream msgTypeStream;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have only one ostringstream, there is no need to have four here.

msgTypeStream << getMsgType();
std::ostringstream pduRefStream;
pduRefStream << getPduRef();
std::ostringstream paramLengthStream;
paramLengthStream << getParamLength();
std::ostringstream dataLengthStream;
dataLengthStream << getDataLength();

return "S7comm Layer, msg_type: " + msgTypeStream.str() +
", pdu_ref: " + pduRefStream.str() +
", param_length: " + paramLengthStream.str() +
", data_length: " + dataLengthStream.str();

}

bool S7commLayer::isDataValid(const uint8_t *data, size_t dataSize)
{
if (!data || dataSize < sizeof(s7commhdr))
return false;

return data[0] == 0x32;
}

uint8_t S7commLayer::getProtocolId() const {
return getS7commHeader()->protocol_id;
}

uint8_t S7commLayer::getMsgType() const {
return getS7commHeader()->msg_type;
}

uint16_t S7commLayer::getReserved() const {
return htobe16(getS7commHeader()->reserved);
}

uint16_t S7commLayer::getParamLength() const {
return htobe16(getS7commHeader()->param_length);
}

uint16_t S7commLayer::getPduRef() const {
return htobe16(getS7commHeader()->pdu_ref);;
}

uint16_t S7commLayer::getDataLength() const {
return htobe16(getS7commHeader()->data_length);
}

void S7commLayer::setMsgType(uint8_t msg_type) const {
getS7commHeader()->msg_type = msg_type;
}

void S7commLayer::setParamLength(uint16_t param_length) const {
getS7commHeader()->param_length = htobe16(param_length);
}

void S7commLayer::setPduRef(uint16_t pdu_ref) const {
getS7commHeader()->pdu_ref = htobe16(pdu_ref);
}

void S7commLayer::setDataLength(uint16_t data_length) const {
getS7commHeader()->data_length = htobe16(data_length);
}
} // namespace pcpp
1 change: 1 addition & 0 deletions Tests/Packet++Test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ add_executable(
Tests/PacketUtilsTests.cpp
Tests/PPPoETests.cpp
Tests/RadiusTests.cpp
Tests/S7commTests.cpp
Tests/SipSdpTests.cpp
Tests/Sll2Tests.cpp
Tests/SllNullLoopbackTests.cpp
Expand Down
1 change: 1 addition & 0 deletions Tests/Packet++Test/PacketExamples/S7comm.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
005056b837d1000e8cd0f9cb0800450001190fc400001e0676970a4900d30a4900200066f0480072171153f0fa9950181000bc050000030000f102f08032070000fd0b000c00d4000112081284010100000000ff0900d000a000000014000a4302ff68c70000000814771421090815333765641381fe64c77200000814771421090815333765544301ff46c7720000081477142109081533375274430eff23000000000000000021073117382880074546ff32c0c08ffe0000000021073117382409174300fff3000000000000000021073117382409176522ff030000000100018ffe21073117382409174580fff200000002000000002107302334535946494eff8fc00000000000000021073023345359264302ff68c7000000001477142104271604011663
Binary file added Tests/Packet++Test/PacketExamples/s7comm.pcap
Binary file not shown.
3 changes: 3 additions & 0 deletions Tests/Packet++Test/TestDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,6 @@ PTF_TEST_CASE(VrrpCreateAndEditTest);

//Implemented in CotpTests.cpp
PTF_TEST_CASE(CotpLayerTest);

//Implemented in S7commTests.cpp
PTF_TEST_CASE(S7commLayerTest);
44 changes: 44 additions & 0 deletions Tests/Packet++Test/Tests/S7commTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "../TestDefinition.h"
#include "../Utils/TestUtils.h"
#include "EndianPortable.h"
#include "Packet.h"
#include "S7commLayer.h"
#include "SystemUtils.h"
#include <stdio.h>

PTF_TEST_CASE(S7commLayerTest) {
timeval time;
gettimeofday(&time, nullptr);
READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/S7comm.dat");

pcpp::Packet S7commLayerTest(&rawPacket1);
PTF_ASSERT_TRUE(S7commLayerTest.isPacketOfType(pcpp::S7COMM));
auto *s7commLayer = S7commLayerTest.getLayerOfType<pcpp::S7commLayer>();
PTF_ASSERT_NOT_NULL(s7commLayer);

PTF_ASSERT_EQUAL(s7commLayer->getProtocolId(), 0x32);
PTF_ASSERT_EQUAL(s7commLayer->getMsgType(), 0x07);
PTF_ASSERT_EQUAL(s7commLayer->getReserved(), htobe16(0));
PTF_ASSERT_EQUAL(s7commLayer->getPduRef(), 0xfd0b);
PTF_ASSERT_EQUAL(s7commLayer->getParamLength(), 12);
PTF_ASSERT_EQUAL(s7commLayer->getDataLength(), 212);

pcpp::S7commLayer newS7commPacket(0x09, 0xfd0c, 13, 213);

PTF_ASSERT_EQUAL(newS7commPacket.getMsgType(), 0x09);
PTF_ASSERT_EQUAL(newS7commPacket.getPduRef(), 0xfd0c);
PTF_ASSERT_EQUAL(newS7commPacket.getParamLength(), 13);
PTF_ASSERT_EQUAL(newS7commPacket.getDataLength(), 213);


newS7commPacket.setMsgType(0x06);
newS7commPacket.setPduRef(0xfd0a);
newS7commPacket.setParamLength(15);
newS7commPacket.setDataLength(215);

PTF_ASSERT_EQUAL(newS7commPacket.getMsgType(), 0x06);
PTF_ASSERT_EQUAL(newS7commPacket.getPduRef(), 0xfd0a);
PTF_ASSERT_EQUAL(newS7commPacket.getParamLength(), 15);
PTF_ASSERT_EQUAL(newS7commPacket.getDataLength(), 215);

} // S7commLayerTest
2 changes: 2 additions & 0 deletions Tests/Packet++Test/main.cpp
seladb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,7 @@ int main(int argc, char* argv[])

PTF_RUN_TEST(CotpLayerTest, "cotp");

PTF_RUN_TEST(S7commLayerTest, "s7comm");

PTF_END_RUNNING_TESTS;
}