Coverage Report

Created: 2026-07-16 07:15

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
    constexpr int16_t pduSize = sizeof(ModbusReadInputRegisters);  // Currently only supporting Read Input Registers
13
0
    constexpr size_t headerLen = sizeof(modbus_header);
14
15
0
    allocData(headerLen + pduSize);
16
17
    // Initialize the header fields to default values
18
0
    modbus_header* header = getModbusHeader();
19
0
    header->transactionId = htobe16(transactionId);
20
0
    header->protocolId = 0;                 // 0 for Modbus/TCP
21
0
    header->length = htobe16(pduSize + 2);  // Length includes unitId and functionCode
22
0
    header->unitId = unitId;
23
0
    header->functionCode = static_cast<uint8_t>(ModbusFunctionCode::ReadInputRegisters);
24
0
  }
25
26
  modbus_header* ModbusLayer::getModbusHeader() const
27
3.52k
  {
28
3.52k
    return reinterpret_cast<modbus_header*>(m_Data);
29
3.52k
  }
30
31
  uint16_t ModbusLayer::getTransactionId() const
32
704
  {
33
704
    return be16toh(getModbusHeader()->transactionId);
34
704
  }
35
36
  uint16_t ModbusLayer::getProtocolId() const
37
704
  {
38
704
    return be16toh(getModbusHeader()->protocolId);
39
704
  }
40
41
  uint16_t ModbusLayer::getLength() const
42
704
  {
43
704
    return be16toh(getModbusHeader()->length);
44
704
  }
45
46
  uint8_t ModbusLayer::getUnitId() const
47
704
  {
48
704
    return getModbusHeader()->unitId;
49
704
  }
50
51
  ModbusLayer::ModbusFunctionCode ModbusLayer::getFunctionCode() const
52
704
  {
53
704
    switch (getModbusHeader()->functionCode)
54
704
    {
55
104
    case 1:
56
104
      return ModbusFunctionCode::ReadCoils;
57
0
    case 2:
58
0
      return ModbusFunctionCode::ReadDiscreteInputs;
59
290
    case 3:
60
290
      return ModbusFunctionCode::ReadHoldingRegisters;
61
0
    case 4:
62
0
      return ModbusFunctionCode::ReadInputRegisters;
63
0
    case 5:
64
0
      return ModbusFunctionCode::WriteSingleCoil;
65
50
    case 6:
66
50
      return ModbusFunctionCode::WriteSingleHoldingRegister;
67
0
    case 15:
68
0
      return ModbusFunctionCode::WriteMultipleCoils;
69
0
    case 16:
70
0
      return ModbusFunctionCode::WriteMultipleHoldingRegisters;
71
0
    case 17:
72
0
      return ModbusFunctionCode::ReadSlaveId;
73
260
    default:
74
260
      return ModbusFunctionCode::UnknownFunction;
75
704
    }
76
704
  }
77
78
  void ModbusLayer::setTransactionId(uint16_t transactionId)
79
0
  {
80
0
    getModbusHeader()->transactionId = htobe16(transactionId);
81
0
  }
82
83
  void ModbusLayer::setUnitId(uint8_t unitId)
84
0
  {
85
0
    getModbusHeader()->unitId = unitId;
86
0
  }
87
88
  void ModbusLayer::setFunctionCode(ModbusLayer::ModbusFunctionCode functionCode)
89
0
  {
90
0
    getModbusHeader()->functionCode = static_cast<uint8_t>(functionCode);
91
0
  }
92
93
  std::string ModbusLayer::toString() const
94
704
  {
95
704
    return "Modbus Layer, Transaction ID: " + std::to_string(getTransactionId()) +
96
704
           ", Protocol ID: " + std::to_string(getProtocolId()) + ", Length: " + std::to_string(getLength()) +
97
704
           ", Unit ID: " + std::to_string(getUnitId()) +
98
704
           ", Function Code: " + std::to_string(static_cast<uint8_t>(getFunctionCode()));
99
704
  }
100
}  // namespace pcpp