Coverage Report

Created: 2025-08-29 07:34

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