/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 |