Coverage Report

Created: 2025-07-18 07:14

/src/PcapPlusPlus/Packet++/src/PacketUtils.cpp
Line
Count
Source (jump to first uncovered line)
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
222k
  {
14
222k
    uint32_t sum = 0;
15
552k
    for (size_t i = 0; i < vecSize; i++)
16
330k
    {
17
330k
      uint32_t localSum = 0;
18
19
      // vec len is in bytes
20
13.1M
      for (size_t j = 0; j < vec[i].len / 2; j++)
21
12.8M
      {
22
12.8M
        PCPP_LOG_DEBUG("Value to add = 0x" << std::uppercase << std::hex << vec[i].buffer[j]);
23
12.8M
        localSum += vec[i].buffer[j];
24
12.8M
      }
25
330k
      PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
26
27
      // check if there is one byte left
28
330k
      if (vec[i].len % 2)
29
30.6k
      {
30
        // access to the last byte using an uint8_t pointer
31
30.6k
        uint8_t* vecBytes = (uint8_t*)vec[i].buffer;
32
30.6k
        uint8_t lastByte = vecBytes[vec[i].len - 1];
33
30.6k
        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
30.6k
        localSum += be16toh(lastByte << 8);
37
38
30.6k
        PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
39
30.6k
      }
40
41
      // carry count is added to the sum
42
645k
      while (localSum >> 16)
43
315k
      {
44
315k
        localSum = (localSum & 0xffff) + (localSum >> 16);
45
315k
      }
46
330k
      PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum);
47
330k
      sum += localSum;
48
330k
    }
49
50
269k
    while (sum >> 16)
51
47.4k
    {
52
47.4k
      sum = (sum & 0xffff) + (sum >> 16);
53
47.4k
    }
54
222k
    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
222k
    uint16_t result = sum;
58
222k
    result = ~result;
59
60
222k
    PCPP_LOG_DEBUG("Calculated checksum = " << sum << ", 0x" << std::uppercase << std::hex << result);
61
62
    // We return the result in BigEndian byte order
63
222k
    return htobe16(result);
64
222k
  }
65
66
  uint16_t computePseudoHdrChecksum(uint8_t* dataPtr, size_t dataLen, IPAddress::AddressType ipAddrType,
67
                                    uint8_t protocolType, IPAddress srcIPAddress, IPAddress dstIPAddress)
68
107k
  {
69
107k
    PCPP_LOG_DEBUG("Compute pseudo header checksum.\n DataLen = " << dataLen << "IPAddrType = " << ipAddrType
70
107k
                                                                  << "ProtocolType = " << protocolType << "SrcIP = "
71
107k
                                                                  << srcIPAddress << "DstIP = " << dstIPAddress);
72
73
107k
    uint16_t checksumRes = 0;
74
107k
    ScalarBuffer<uint16_t> vec[2];
75
107k
    vec[0].buffer = (uint16_t*)dataPtr;
76
107k
    vec[0].len = dataLen;
77
78
107k
    if (ipAddrType == IPAddress::IPv4AddressType)
79
86.6k
    {
80
86.6k
      uint32_t srcIP = srcIPAddress.getIPv4().toInt();
81
86.6k
      uint32_t dstIP = dstIPAddress.getIPv4().toInt();
82
86.6k
      uint16_t pseudoHeader[6];
83
86.6k
      pseudoHeader[0] = srcIP >> 16;
84
86.6k
      pseudoHeader[1] = srcIP & 0xFFFF;
85
86.6k
      pseudoHeader[2] = dstIP >> 16;
86
86.6k
      pseudoHeader[3] = dstIP & 0xFFFF;
87
86.6k
      pseudoHeader[4] = 0xffff & htobe16(dataLen);
88
86.6k
      pseudoHeader[5] = htobe16(0x00ff & protocolType);
89
86.6k
      vec[1].buffer = pseudoHeader;
90
86.6k
      vec[1].len = 12;
91
86.6k
      checksumRes = computeChecksum(vec, 2);
92
86.6k
    }
93
20.6k
    else if (ipAddrType == IPAddress::IPv6AddressType)
94
20.6k
    {
95
20.6k
      uint16_t pseudoHeader[18];
96
20.6k
      srcIPAddress.getIPv6().copyTo((uint8_t*)pseudoHeader);
97
20.6k
      dstIPAddress.getIPv6().copyTo((uint8_t*)(pseudoHeader + 8));
98
20.6k
      pseudoHeader[16] = 0xffff & htobe16(dataLen);
99
20.6k
      pseudoHeader[17] = htobe16(0x00ff & protocolType);
100
20.6k
      vec[1].buffer = pseudoHeader;
101
20.6k
      vec[1].len = 36;
102
20.6k
      checksumRes = computeChecksum(vec, 2);
103
20.6k
    }
104
0
    else
105
0
    {
106
0
      PCPP_LOG_ERROR("Compute pseudo header checksum failed, for unknown IPAddrType = " << ipAddrType);
107
0
    }
108
109
107k
    PCPP_LOG_DEBUG("Pseudo header checksum = 0xX" << std::uppercase << std::hex << checksumRes);
110
111
107k
    return checksumRes;
112
107k
  }
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 = (uint8_t*)&portSrc;
176
0
    vec[0 + srcPosition].len = 2;
177
0
    vec[1 - srcPosition].buffer = (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 = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc;
188
0
      vec[2 + srcPosition].len = 4;
189
0
      vec[3 - srcPosition].buffer = (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 = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc;
227
0
      vec[0 + srcPosition].len = 4;
228
0
      vec[1 - srcPosition].buffer = (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