/src/PcapPlusPlus/Packet++/src/IPv6Layer.cpp
Line | Count | Source |
1 | | #define LOG_MODULE PacketLogModuleIPv6Layer |
2 | | |
3 | | #include <stdexcept> |
4 | | #include "IPv6Layer.h" |
5 | | #include "IPv4Layer.h" |
6 | | #include "PayloadLayer.h" |
7 | | #include "UdpLayer.h" |
8 | | #include "TcpLayer.h" |
9 | | #include "GreLayer.h" |
10 | | #include "IPSecLayer.h" |
11 | | #include "IcmpV6Layer.h" |
12 | | #include "VrrpLayer.h" |
13 | | #include "Packet.h" |
14 | | #include "EndianPortable.h" |
15 | | #include "SystemUtils.h" |
16 | | |
17 | | namespace pcpp |
18 | | { |
19 | | |
20 | | void IPv6Layer::initLayer() |
21 | 0 | { |
22 | 0 | allocData(sizeof(ip6_hdr)); |
23 | 0 | m_Protocol = IPv6; |
24 | 0 | m_FirstExtension = nullptr; |
25 | 0 | m_LastExtension = nullptr; |
26 | 0 | m_ExtensionsLen = 0; |
27 | 0 | } |
28 | | |
29 | | IPv6Layer::IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
30 | 0 | : Layer(data, dataLen, prevLayer, packet, IPv6) |
31 | 0 | { |
32 | 0 | m_FirstExtension = nullptr; |
33 | 0 | m_LastExtension = nullptr; |
34 | 0 | m_ExtensionsLen = 0; |
35 | |
|
36 | 0 | parseExtensions(); |
37 | |
|
38 | 0 | size_t totalLen = be16toh(getIPv6Header()->payloadLength) + getHeaderLen(); |
39 | 0 | if (totalLen < m_DataLen) |
40 | 0 | m_DataLen = totalLen; |
41 | 0 | } |
42 | | |
43 | | IPv6Layer::IPv6Layer() |
44 | 0 | { |
45 | 0 | initLayer(); |
46 | 0 | } |
47 | | |
48 | | IPv6Layer::IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP) |
49 | 0 | { |
50 | 0 | initLayer(); |
51 | 0 | ip6_hdr* ipHdr = getIPv6Header(); |
52 | 0 | srcIP.copyTo(ipHdr->ipSrc); |
53 | 0 | dstIP.copyTo(ipHdr->ipDst); |
54 | 0 | } |
55 | | |
56 | 0 | IPv6Layer::IPv6Layer(const IPv6Layer& other) : Layer(other) |
57 | 0 | { |
58 | 0 | m_FirstExtension = nullptr; |
59 | 0 | m_LastExtension = nullptr; |
60 | 0 | m_ExtensionsLen = 0; |
61 | 0 | parseExtensions(); |
62 | 0 | } |
63 | | |
64 | | IPv6Layer::~IPv6Layer() |
65 | 0 | { |
66 | 0 | deleteExtensions(); |
67 | 0 | } |
68 | | |
69 | | IPv6Layer& IPv6Layer::operator=(const IPv6Layer& other) |
70 | 0 | { |
71 | 0 | Layer::operator=(other); |
72 | |
|
73 | 0 | deleteExtensions(); |
74 | |
|
75 | 0 | parseExtensions(); |
76 | |
|
77 | 0 | return *this; |
78 | 0 | } |
79 | | |
80 | | void IPv6Layer::parseExtensions() |
81 | 0 | { |
82 | 0 | uint8_t nextHdr = getIPv6Header()->nextHeader; |
83 | 0 | IPv6Extension* curExt = nullptr; |
84 | |
|
85 | 0 | size_t offset = sizeof(ip6_hdr); |
86 | |
|
87 | 0 | while (offset <= m_DataLen - 2 * sizeof(uint8_t)) // 2*sizeof(uint8_t) is the min len for IPv6 extensions |
88 | 0 | { |
89 | 0 | IPv6Extension* newExt = nullptr; |
90 | |
|
91 | 0 | switch (nextHdr) |
92 | 0 | { |
93 | 0 | case PACKETPP_IPPROTO_FRAGMENT: |
94 | 0 | { |
95 | 0 | newExt = new IPv6FragmentationHeader(this, offset); |
96 | 0 | break; |
97 | 0 | } |
98 | 0 | case PACKETPP_IPPROTO_HOPOPTS: |
99 | 0 | { |
100 | 0 | newExt = new IPv6HopByHopHeader(this, offset); |
101 | 0 | break; |
102 | 0 | } |
103 | 0 | case PACKETPP_IPPROTO_DSTOPTS: |
104 | 0 | { |
105 | 0 | newExt = new IPv6DestinationHeader(this, offset); |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | case PACKETPP_IPPROTO_ROUTING: |
109 | 0 | { |
110 | 0 | newExt = new IPv6RoutingHeader(this, offset); |
111 | 0 | break; |
112 | 0 | } |
113 | 0 | case PACKETPP_IPPROTO_AH: |
114 | 0 | { |
115 | 0 | newExt = new IPv6AuthenticationHeader(this, offset); |
116 | 0 | break; |
117 | 0 | } |
118 | 0 | default: |
119 | 0 | { |
120 | 0 | break; |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | 0 | if (newExt == nullptr) |
125 | 0 | break; |
126 | | |
127 | 0 | if (m_FirstExtension == nullptr) |
128 | 0 | { |
129 | 0 | m_FirstExtension = newExt; |
130 | 0 | curExt = m_FirstExtension; |
131 | 0 | } |
132 | 0 | else |
133 | 0 | { |
134 | 0 | if (curExt == nullptr) |
135 | 0 | { |
136 | 0 | throw std::logic_error("curExt is nullptr"); |
137 | 0 | } |
138 | 0 | curExt->setNextHeader(newExt); |
139 | 0 | curExt = curExt->getNextHeader(); |
140 | 0 | } |
141 | | |
142 | 0 | offset += newExt->getExtensionLen(); |
143 | 0 | nextHdr = newExt->getBaseHeader()->nextHeader; |
144 | 0 | m_ExtensionsLen += newExt->getExtensionLen(); |
145 | 0 | } |
146 | | |
147 | 0 | m_LastExtension = curExt; |
148 | 0 | } |
149 | | |
150 | | void IPv6Layer::deleteExtensions() |
151 | 0 | { |
152 | 0 | IPv6Extension* curExt = m_FirstExtension; |
153 | 0 | while (curExt != nullptr) |
154 | 0 | { |
155 | 0 | IPv6Extension* tmpExt = curExt->getNextHeader(); |
156 | 0 | delete curExt; |
157 | 0 | curExt = tmpExt; |
158 | 0 | } |
159 | |
|
160 | 0 | m_FirstExtension = nullptr; |
161 | 0 | m_LastExtension = nullptr; |
162 | 0 | m_ExtensionsLen = 0; |
163 | 0 | } |
164 | | |
165 | | size_t IPv6Layer::getExtensionCount() const |
166 | 0 | { |
167 | 0 | size_t extensionCount = 0; |
168 | |
|
169 | 0 | IPv6Extension* curExt = m_FirstExtension; |
170 | |
|
171 | 0 | while (curExt != nullptr) |
172 | 0 | { |
173 | 0 | extensionCount++; |
174 | 0 | curExt = curExt->getNextHeader(); |
175 | 0 | } |
176 | |
|
177 | 0 | return extensionCount; |
178 | 0 | } |
179 | | |
180 | | void IPv6Layer::removeAllExtensions() |
181 | 0 | { |
182 | 0 | if (m_LastExtension != nullptr) |
183 | 0 | getIPv6Header()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader; |
184 | |
|
185 | 0 | shortenLayer((int)sizeof(ip6_hdr), m_ExtensionsLen); |
186 | |
|
187 | 0 | deleteExtensions(); |
188 | 0 | } |
189 | | |
190 | | bool IPv6Layer::isFragment() const |
191 | 0 | { |
192 | 0 | return getExtensionOfType<IPv6FragmentationHeader>() != nullptr; |
193 | 0 | } |
194 | | |
195 | | void IPv6Layer::parseNextLayer() |
196 | 0 | { |
197 | 0 | size_t headerLen = getHeaderLen(); |
198 | |
|
199 | 0 | if (m_DataLen <= headerLen) |
200 | 0 | return; |
201 | | |
202 | 0 | uint8_t* payload = m_Data + headerLen; |
203 | 0 | size_t payloadLen = m_DataLen - headerLen; |
204 | |
|
205 | 0 | uint8_t nextHdr; |
206 | 0 | if (m_LastExtension != nullptr) |
207 | 0 | { |
208 | 0 | if (m_LastExtension->getExtensionType() == IPv6Extension::IPv6Fragmentation) |
209 | 0 | { |
210 | 0 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
211 | 0 | return; |
212 | 0 | } |
213 | | |
214 | 0 | nextHdr = m_LastExtension->getBaseHeader()->nextHeader; |
215 | 0 | } |
216 | 0 | else |
217 | 0 | { |
218 | 0 | nextHdr = getIPv6Header()->nextHeader; |
219 | 0 | } |
220 | | |
221 | 0 | switch (nextHdr) |
222 | 0 | { |
223 | 0 | case PACKETPP_IPPROTO_UDP: |
224 | 0 | { |
225 | 0 | tryConstructNextLayerWithFallback<UdpLayer, PayloadLayer>(payload, payloadLen); |
226 | 0 | break; |
227 | 0 | } |
228 | 0 | case PACKETPP_IPPROTO_TCP: |
229 | 0 | { |
230 | 0 | tryConstructNextLayerWithFallback<TcpLayer, PayloadLayer>(payload, payloadLen); |
231 | 0 | break; |
232 | 0 | } |
233 | 0 | case PACKETPP_IPPROTO_IPIP: |
234 | 0 | { |
235 | 0 | uint8_t ipVersion = *payload >> 4; |
236 | 0 | switch (ipVersion) |
237 | 0 | { |
238 | 0 | case 4: |
239 | 0 | { |
240 | 0 | tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen); |
241 | 0 | break; |
242 | 0 | } |
243 | 0 | case 6: |
244 | 0 | { |
245 | 0 | tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen); |
246 | 0 | break; |
247 | 0 | } |
248 | 0 | default: |
249 | 0 | { |
250 | 0 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | } |
254 | 0 | break; |
255 | 0 | } |
256 | 0 | case PACKETPP_IPPROTO_GRE: |
257 | 0 | { |
258 | 0 | ProtocolType greVer = GreLayer::getGREVersion(payload, payloadLen); |
259 | |
|
260 | 0 | switch (greVer) |
261 | 0 | { |
262 | 0 | case GREv0: |
263 | 0 | { |
264 | 0 | tryConstructNextLayerWithFallback<GREv0Layer, PayloadLayer>(payload, payloadLen); |
265 | 0 | break; |
266 | 0 | } |
267 | 0 | case GREv1: |
268 | 0 | { |
269 | 0 | tryConstructNextLayerWithFallback<GREv1Layer, PayloadLayer>(payload, payloadLen); |
270 | 0 | break; |
271 | 0 | } |
272 | 0 | default: |
273 | 0 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
274 | 0 | break; |
275 | 0 | } |
276 | 0 | break; |
277 | 0 | } |
278 | 0 | case PACKETPP_IPPROTO_AH: |
279 | 0 | { |
280 | 0 | tryConstructNextLayerWithFallback<AuthenticationHeaderLayer, PayloadLayer>(payload, payloadLen); |
281 | 0 | break; |
282 | 0 | } |
283 | 0 | case PACKETPP_IPPROTO_ESP: |
284 | 0 | { |
285 | 0 | tryConstructNextLayerWithFallback<ESPLayer, PayloadLayer>(payload, payloadLen); |
286 | 0 | break; |
287 | 0 | } |
288 | 0 | case PACKETPP_IPPROTO_ICMPV6: |
289 | 0 | { |
290 | 0 | constructNextLayerFromFactory(IcmpV6Layer::parseIcmpV6Layer, payload, payloadLen); |
291 | 0 | break; |
292 | 0 | } |
293 | 0 | case PACKETPP_IPPROTO_VRRP: |
294 | 0 | { |
295 | 0 | auto vrrpVer = VrrpLayer::getVersionFromData(payload, payloadLen); |
296 | |
|
297 | 0 | if (vrrpVer == VRRPv3) |
298 | 0 | { |
299 | 0 | constructNextLayer<VrrpV3Layer>(payload, payloadLen, IPAddress::IPv6AddressType); |
300 | 0 | } |
301 | 0 | else |
302 | 0 | { |
303 | 0 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
304 | 0 | } |
305 | 0 | break; |
306 | 0 | } |
307 | 0 | default: |
308 | 0 | { |
309 | 0 | constructNextLayer<PayloadLayer>(payload, payloadLen); |
310 | 0 | break; |
311 | 0 | } |
312 | 0 | } |
313 | 0 | } |
314 | | |
315 | | void IPv6Layer::computeCalculateFields() |
316 | 0 | { |
317 | 0 | ip6_hdr* ipHdr = getIPv6Header(); |
318 | 0 | ipHdr->payloadLength = htobe16(m_DataLen - sizeof(ip6_hdr)); |
319 | 0 | ipHdr->ipVersion = (6 & 0x0f); |
320 | |
|
321 | 0 | if (m_NextLayer != nullptr) |
322 | 0 | { |
323 | 0 | uint8_t nextHeader = 0; |
324 | 0 | switch (m_NextLayer->getProtocol()) |
325 | 0 | { |
326 | 0 | case TCP: |
327 | 0 | nextHeader = PACKETPP_IPPROTO_TCP; |
328 | 0 | break; |
329 | 0 | case UDP: |
330 | 0 | nextHeader = PACKETPP_IPPROTO_UDP; |
331 | 0 | break; |
332 | 0 | case ICMP: |
333 | 0 | nextHeader = PACKETPP_IPPROTO_ICMP; |
334 | 0 | break; |
335 | 0 | case ICMPv6: |
336 | 0 | nextHeader = PACKETPP_IPPROTO_ICMPV6; |
337 | 0 | break; |
338 | 0 | case GREv0: |
339 | 0 | case GREv1: |
340 | 0 | nextHeader = PACKETPP_IPPROTO_GRE; |
341 | 0 | break; |
342 | 0 | case VRRPv3: |
343 | 0 | nextHeader = PACKETPP_IPPROTO_VRRP; |
344 | 0 | break; |
345 | 0 | default: |
346 | 0 | break; |
347 | 0 | } |
348 | | |
349 | 0 | if (nextHeader != 0) |
350 | 0 | { |
351 | 0 | if (m_LastExtension != nullptr) |
352 | 0 | m_LastExtension->getBaseHeader()->nextHeader = nextHeader; |
353 | 0 | else |
354 | 0 | ipHdr->nextHeader = nextHeader; |
355 | 0 | } |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | | std::string IPv6Layer::toString() const |
360 | 0 | { |
361 | 0 | std::string result = |
362 | 0 | "IPv6 Layer, Src: " + getSrcIPv6Address().toString() + ", Dst: " + getDstIPv6Address().toString(); |
363 | 0 | if (m_ExtensionsLen > 0) |
364 | 0 | { |
365 | 0 | result += ", Options=["; |
366 | 0 | for (auto const* curExt = m_FirstExtension; curExt != nullptr; curExt = curExt->getNextHeader()) |
367 | 0 | { |
368 | 0 | result += curExt->getExtensionTypeAsString(); |
369 | 0 | result += ","; |
370 | 0 | } |
371 | | |
372 | | // replace the last ',' |
373 | 0 | result[result.size() - 1] = ']'; |
374 | 0 | } |
375 | |
|
376 | 0 | return result; |
377 | 0 | } |
378 | | |
379 | | const FieldDescriptor IPv6Layer::SerializedFields::SrcIp{ Layer::SerializedFields::MaxID + 1, "srcIP" }; |
380 | | const FieldDescriptor IPv6Layer::SerializedFields::DstIp{ Layer::SerializedFields::MaxID + 2, "dstIP" }; |
381 | | const FieldDescriptor IPv6Layer::SerializedFields::PayloadLength{ Layer::SerializedFields::MaxID + 3, |
382 | | "payloadLength" }; |
383 | | const FieldDescriptor IPv6Layer::SerializedFields::IsFragment{ Layer::SerializedFields::MaxID + 4, "isFragment" }; |
384 | | const FieldDescriptor IPv6Layer::SerializedFields::NextHeader{ Layer::SerializedFields::MaxID + 5, "nextHeader" }; |
385 | | const FieldDescriptor IPv6Layer::SerializedFields::Extensions{ Layer::SerializedFields::MaxID + 6, "extensions" }; |
386 | | const IPv6Layer::SerializedFields::IPv6ExtensionObject ExtensionObject{ 0, "extension" }; |
387 | | const FieldDescriptor IPv6Layer::SerializedFields::IPv6ExtensionObject::Name{ 0, "name" }; |
388 | | const FieldDescriptor IPv6Layer::SerializedFields::IPv6ExtensionObject::Type{ 1, "type" }; |
389 | | |
390 | | void IPv6Layer::serializeLayer(ObjectScope& serializer) const |
391 | 0 | { |
392 | 0 | serializer.writeField(SerializedFields::SrcIp, getSrcIPAddress().toString()); |
393 | 0 | serializer.writeField(SerializedFields::DstIp, getDstIPAddress().toString()); |
394 | 0 | auto header = getIPv6Header(); |
395 | 0 | serializer.writeField(SerializedFields::PayloadLength, netToHost16(header->payloadLength)); |
396 | 0 | serializer.writeField(SerializedFields::IsFragment, isFragment()); |
397 | 0 | serializer.writeField(SerializedFields::NextHeader, header->nextHeader); |
398 | 0 | auto extensions = serializer.writeArray(SerializedFields::Extensions); |
399 | 0 | for (auto extension = m_FirstExtension; extension != nullptr; extension = extension->getNextHeader()) |
400 | 0 | { |
401 | 0 | auto extensionObject = extensions.writeObject(ExtensionObject); |
402 | 0 | extensionObject.writeField(SerializedFields::IPv6ExtensionObject::Name, |
403 | 0 | extension->getExtensionTypeAsString()); |
404 | 0 | extensionObject.writeField(SerializedFields::IPv6ExtensionObject::Type, |
405 | 0 | static_cast<uint8_t>(extension->getExtensionType())); |
406 | 0 | } |
407 | 0 | } |
408 | | } // namespace pcpp |