Coverage Report

Created: 2026-11-12 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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