Coverage Report

Created: 2025-10-10 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/ModbusLayer.cpp
Line
Count
Source
1
#include "ModbusLayer.h"
2
#include "EndianPortable.h"
3
#include <iostream>
4
#include <iomanip>
5
#include <cstring>
6
#include "Logger.h"
7
8
namespace pcpp
9
{
10
  ModbusLayer::ModbusLayer(uint16_t transactionId, uint8_t unitId)
11
0
  {
12
0
    const int16_t pduSize = sizeof(ModbusReadInputRegisters);  // Currently only supporting Read Input Registers
13
0
    const size_t headerLen = sizeof(modbus_header);
14
15
0
    m_DataLen = headerLen + pduSize;
16
0
    m_Data = new uint8_t[m_DataLen]{};
17
0
    memset(m_Data, 0, m_DataLen);
18
19
    // Initialize the header fields to default values
20
0
    modbus_header* header = getModbusHeader();
21
0
    header->transactionId = htobe16(transactionId);
22
0
    header->protocolId = 0;                 // 0 for Modbus/TCP
23
0
    header->length = htobe16(pduSize + 2);  // Length includes unitId and functionCode
24
0
    header->unitId = unitId;
25
0
    header->functionCode = static_cast<uint8_t>(ModbusFunctionCode::ReadInputRegisters);
26
0
  }
27
28
  modbus_header* ModbusLayer::getModbusHeader() const
29
0
  {
30
0
    return reinterpret_cast<modbus_header*>(m_Data);
31
0
  }
32
33
  uint16_t ModbusLayer::getTransactionId() const
34
0
  {
35
0
    return be16toh(getModbusHeader()->transactionId);
36
0
  }
37
38
  uint16_t ModbusLayer::getProtocolId() const
39
0
  {
40
0
    return be16toh(getModbusHeader()->protocolId);
41
0
  }
42
43
  uint16_t ModbusLayer::getLength() const
44
0
  {
45
0
    return be16toh(getModbusHeader()->length);
46
0
  }
47
48
  uint8_t ModbusLayer::getUnitId() const
49
0
  {
50
0
    return getModbusHeader()->unitId;
51
0
  }
52
53
  ModbusLayer::ModbusFunctionCode ModbusLayer::getFunctionCode() const
54
0
  {
55
0
    switch (getModbusHeader()->functionCode)
56
0
    {
57
0
    case 1:
58
0
      return ModbusFunctionCode::ReadCoils;
59
0
    case 2:
60
0
      return ModbusFunctionCode::ReadDiscreteInputs;
61
0
    case 3:
62
0
      return ModbusFunctionCode::ReadHoldingRegisters;
63
0
    case 4:
64
0
      return ModbusFunctionCode::ReadInputRegisters;
65
0
    case 5:
66
0
      return ModbusFunctionCode::WriteSingleCoil;
67
0
    case 6:
68
0
      return ModbusFunctionCode::WriteSingleHoldingRegister;
69
0
    case 15:
70
0
      return ModbusFunctionCode::WriteMultipleCoils;
71
0
    case 16:
72
0
      return ModbusFunctionCode::WriteMultipleHoldingRegisters;
73
0
    case 17:
74
0
      return ModbusFunctionCode::ReadSlaveId;
75
0
    default:
76
0
      return ModbusFunctionCode::UnknownFunction;
77
0
    }
78
0
  }
79
80
  void ModbusLayer::setTransactionId(uint16_t transactionId)
81
0
  {
82
0
    getModbusHeader()->transactionId = htobe16(transactionId);
83
0
  }
84
85
  void ModbusLayer::setUnitId(uint8_t unitId)
86
0
  {
87
0
    getModbusHeader()->unitId = unitId;
88
0
  }
89
90
  void ModbusLayer::setFunctionCode(ModbusLayer::ModbusFunctionCode functionCode)
91
0
  {
92
0
    getModbusHeader()->functionCode = static_cast<uint8_t>(functionCode);
93
0
  }
94
95
  std::string ModbusLayer::toString() const
96
0
  {
97
0
    return "Modbus Layer, Transaction ID: " + std::to_string(getTransactionId()) +
98
0
           ", Protocol ID: " + std::to_string(getProtocolId()) + ", Length: " + std::to_string(getLength()) +
99
0
           ", Unit ID: " + std::to_string(getUnitId()) +
100
0
           ", Function Code: " + std::to_string(static_cast<uint8_t>(getFunctionCode()));
101
0
  }
102
}  // namespace pcpp