Coverage Report

Created: 2026-01-09 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/PacketUtils.cpp
Line
Count
Source
1
#include "PacketUtils.h"
2
#include "IPv4Layer.h"
3
#include "IPv6Layer.h"
4
#include "TcpLayer.h"
5
#include "UdpLayer.h"
6
#include "Logger.h"
7
#include "EndianPortable.h"
8
9
namespace pcpp
10
{
11
12
  uint16_t computeChecksum(ScalarBuffer<uint16_t> vec[], size_t vecSize)
13
0
  {
14
0
    uint32_t sum = 0;
15
0
    for (size_t i = 0; i < vecSize; i++)
16
0
    {
17
0
      uint32_t localSum = 0;
18
19
      // vec len is in bytes
20
0
      for (size_t j = 0; j < vec[i].len / 2; j++)
21
0
      {
22
0
        PCPP_LOG_DEBUG("Value to add = 0x" << std::uppercase << std::hex << vec[i].buffer[j]);
23
0
        localSum += vec[i].buffer[j];
24
0
      }
25
0
      PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
26
27
      // check if there is one byte left
28
0
      if (vec[i].len % 2)
29
0
      {
30
        // access to the last byte using an uint8_t pointer
31
0
        uint8_t* vecBytes = reinterpret_cast<uint8_t*>(vec[i].buffer);
32
0
        uint8_t lastByte = vecBytes[vec[i].len - 1];
33
0
        PCPP_LOG_DEBUG("1 byte left, adding value: 0x" << std::uppercase << std::hex << lastByte);
34
        // We have read the latest byte manually but this byte should be properly interpreted
35
        // as a 0xFF on LE and a 0xFF00 on BE to have a proper checksum computation
36
0
        localSum += be16toh(lastByte << 8);
37
38
0
        PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
39
0
      }
40
41
      // carry count is added to the sum
42
0
      while (localSum >> 16)
43
0
      {
44
0
        localSum = (localSum & 0xffff) + (localSum >> 16);
45
0
      }
46
0
      PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
47
0
      sum += localSum;
48
0
    }
49
50
0
    while (sum >> 16)
51
0
    {
52
0
      sum = (sum & 0xffff) + (sum >> 16);
53
0
    }
54
0
    PCPP_LOG_DEBUG("Sum before invert = " << sum << ", 0x" << std::uppercase << std::hex << sum);
55
56
    // To obtain the checksum we take the ones' complement of this result
57
0
    uint16_t result = sum;
58
0
    result = ~result;
59
60
0
    PCPP_LOG_DEBUG("Calculated checksum = " << sum << ", 0x" << std::uppercase << std::hex << result);
61
62
    // We return the result in BigEndian byte order
63
0
    return htobe16(result);
64
0
  }
65
66
  uint16_t computePseudoHdrChecksum(uint8_t* dataPtr, size_t dataLen, IPAddress::AddressType ipAddrType,
67
                                    uint8_t protocolType, IPAddress srcIPAddress, IPAddress dstIPAddress)
68
0
  {
69
0
    PCPP_LOG_DEBUG("Compute pseudo header checksum.\n DataLen = " << dataLen << "IPAddrType = " << ipAddrType
70
0
                                                                  << "ProtocolType = " << protocolType << "SrcIP = "
71
0
                                                                  << srcIPAddress << "DstIP = " << dstIPAddress);
72
73
0
    uint16_t checksumRes = 0;
74
0
    ScalarBuffer<uint16_t> vec[2];
75
0
    vec[0].buffer = reinterpret_cast<uint16_t*>(dataPtr);
76
0
    vec[0].len = dataLen;
77
78
0
    if (ipAddrType == IPAddress::IPv4AddressType)
79
0
    {
80
0
      uint32_t srcIP = srcIPAddress.getIPv4().toInt();
81
0
      uint32_t dstIP = dstIPAddress.getIPv4().toInt();
82
0
      uint16_t pseudoHeader[6];
83
0
      pseudoHeader[0] = srcIP >> 16;
84
0
      pseudoHeader[1] = srcIP & 0xFFFF;
85
0
      pseudoHeader[2] = dstIP >> 16;
86
0
      pseudoHeader[3] = dstIP & 0xFFFF;
87
0
      pseudoHeader[4] = 0xffff & htobe16(dataLen);
88
0
      pseudoHeader[5] = htobe16(0x00ff & protocolType);
89
0
      vec[1].buffer = pseudoHeader;
90
0
      vec[1].len = 12;
91
0
      checksumRes = computeChecksum(vec, 2);
92
0
    }
93
0
    else if (ipAddrType == IPAddress::IPv6AddressType)
94
0
    {
95
0
      uint16_t pseudoHeader[18];
96
0
      srcIPAddress.getIPv6().copyTo(reinterpret_cast<uint8_t*>(pseudoHeader));
97
0
      dstIPAddress.getIPv6().copyTo(reinterpret_cast<uint8_t*>(pseudoHeader + 8));
98
0
      pseudoHeader[16] = 0xffff & htobe16(dataLen);
99
0
      pseudoHeader[17] = htobe16(0x00ff & protocolType);
100
0
      vec[1].buffer = pseudoHeader;
101
0
      vec[1].len = 36;
102
0
      checksumRes = computeChecksum(vec, 2);
103
0
    }
104
0
    else
105
0
    {
106
0
      PCPP_LOG_ERROR("Compute pseudo header checksum failed, for unknown IPAddrType = " << ipAddrType);
107
0
    }
108
109
0
    PCPP_LOG_DEBUG("Pseudo header checksum = 0xX" << std::uppercase << std::hex << checksumRes);
110
111
0
    return checksumRes;
112
0
  }
113
114
  static const uint32_t FNV_PRIME = 16777619u;
115
  static const uint32_t OFFSET_BASIS = 2166136261u;
116
117
  uint32_t fnvHash(ScalarBuffer<uint8_t> vec[], size_t vecSize)
118
0
  {
119
0
    uint32_t hash = OFFSET_BASIS;
120
0
    for (size_t i = 0; i < vecSize; ++i)
121
0
    {
122
0
      for (size_t j = 0; j < vec[i].len; ++j)
123
0
      {
124
0
        hash *= FNV_PRIME;
125
0
        hash ^= vec[i].buffer[j];
126
0
      }
127
0
    }
128
0
    return hash;
129
0
  }
130
131
  uint32_t fnvHash(uint8_t* buffer, size_t bufSize)
132
0
  {
133
0
    ScalarBuffer<uint8_t> scalarBuf;
134
0
    scalarBuf.buffer = buffer;
135
0
    scalarBuf.len = bufSize;
136
0
    return fnvHash(&scalarBuf, 1);
137
0
  }
138
139
  uint32_t hash5Tuple(Packet* packet, bool const& directionUnique)
140
0
  {
141
0
    if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6))
142
0
      return 0;
143
144
0
    if (packet->isPacketOfType(ICMP))
145
0
      return 0;
146
147
0
    if (!(packet->isPacketOfType(TCP)) && (!packet->isPacketOfType(UDP)))
148
0
      return 0;
149
150
0
    ScalarBuffer<uint8_t> vec[5];
151
152
0
    uint16_t portSrc = 0;
153
0
    uint16_t portDst = 0;
154
0
    int srcPosition = 0;
155
156
0
    TcpLayer* tcpLayer = packet->getLayerOfType<TcpLayer>(true);  // lookup in reverse order
157
0
    if (tcpLayer != nullptr)
158
0
    {
159
0
      portSrc = tcpLayer->getTcpHeader()->portSrc;
160
0
      portDst = tcpLayer->getTcpHeader()->portDst;
161
0
    }
162
0
    else
163
0
    {
164
0
      UdpLayer* udpLayer = packet->getLayerOfType<UdpLayer>(true);
165
0
      portSrc = udpLayer->getUdpHeader()->portSrc;
166
0
      portDst = udpLayer->getUdpHeader()->portDst;
167
0
    }
168
169
0
    if (!directionUnique)
170
0
    {
171
0
      if (portDst < portSrc)
172
0
        srcPosition = 1;
173
0
    }
174
175
0
    vec[0 + srcPosition].buffer = reinterpret_cast<uint8_t*>(&portSrc);
176
0
    vec[0 + srcPosition].len = 2;
177
0
    vec[1 - srcPosition].buffer = reinterpret_cast<uint8_t*>(&portDst);
178
0
    vec[1 - srcPosition].len = 2;
179
180
0
    IPv4Layer* ipv4Layer = packet->getLayerOfType<IPv4Layer>();
181
0
    if (ipv4Layer != nullptr)
182
0
    {
183
0
      if (!directionUnique && portSrc == portDst &&
184
0
          ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc)
185
0
        srcPosition = 1;
186
187
0
      vec[2 + srcPosition].buffer = reinterpret_cast<uint8_t*>(&ipv4Layer->getIPv4Header()->ipSrc);
188
0
      vec[2 + srcPosition].len = 4;
189
0
      vec[3 - srcPosition].buffer = reinterpret_cast<uint8_t*>(&ipv4Layer->getIPv4Header()->ipDst);
190
0
      vec[3 - srcPosition].len = 4;
191
0
      vec[4].buffer = &(ipv4Layer->getIPv4Header()->protocol);
192
0
      vec[4].len = 1;
193
0
    }
194
0
    else
195
0
    {
196
0
      IPv6Layer* ipv6Layer = packet->getLayerOfType<IPv6Layer>();
197
0
      if (!directionUnique && portSrc == portDst &&
198
0
          memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0)
199
0
        srcPosition = 1;
200
201
0
      vec[2 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc;
202
0
      vec[2 + srcPosition].len = 16;
203
0
      vec[3 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst;
204
0
      vec[3 - srcPosition].len = 16;
205
0
      vec[4].buffer = &(ipv6Layer->getIPv6Header()->nextHeader);
206
0
      vec[4].len = 1;
207
0
    }
208
209
0
    return pcpp::fnvHash(vec, 5);
210
0
  }
211
212
  uint32_t hash2Tuple(Packet* packet)
213
0
  {
214
0
    if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6))
215
0
      return 0;
216
217
0
    ScalarBuffer<uint8_t> vec[2];
218
219
0
    IPv4Layer* ipv4Layer = packet->getLayerOfType<IPv4Layer>();
220
0
    if (ipv4Layer != nullptr)
221
0
    {
222
0
      int srcPosition = 0;
223
0
      if (ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc)
224
0
        srcPosition = 1;
225
226
0
      vec[0 + srcPosition].buffer = reinterpret_cast<uint8_t*>(&ipv4Layer->getIPv4Header()->ipSrc);
227
0
      vec[0 + srcPosition].len = 4;
228
0
      vec[1 - srcPosition].buffer = reinterpret_cast<uint8_t*>(&ipv4Layer->getIPv4Header()->ipDst);
229
0
      vec[1 - srcPosition].len = 4;
230
0
    }
231
0
    else
232
0
    {
233
0
      IPv6Layer* ipv6Layer = packet->getLayerOfType<IPv6Layer>();
234
0
      int srcPosition = 0;
235
0
      if (memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0)
236
0
        srcPosition = 1;
237
238
0
      vec[0 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc;
239
0
      vec[0 + srcPosition].len = 16;
240
0
      vec[1 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst;
241
0
      vec[1 - srcPosition].len = 16;
242
0
    }
243
244
0
    return pcpp::fnvHash(vec, 2);
245
0
  }
246
247
}  // namespace pcpp