Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/header/IPv6Layer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "Layer.h"
4
#include "IPLayer.h"
5
#include "IPv6Extensions.h"
6
#include "IpAddress.h"
7
8
/// @file
9
10
/// @namespace pcpp
11
/// @brief The main namespace for the PcapPlusPlus lib
12
namespace pcpp
13
{
14
15
  /// @struct ip6_hdr
16
  /// Represents IPv6 protocol header
17
#pragma pack(push, 1)
18
  struct ip6_hdr
19
  {
20
#if (BYTE_ORDER == LITTLE_ENDIAN)
21
    /// Traffic class
22
    uint8_t trafficClass : 4,
23
        /// IP version number, has the value of 6 for IPv6
24
        ipVersion : 4;
25
#else
26
    /// IP version number, has the value of 6 for IPv6
27
    uint8_t ipVersion : 4,
28
        /// Traffic class
29
        trafficClass : 4;
30
#endif
31
    /// Flow label
32
    uint8_t flowLabel[3];
33
    /// The size of the payload in octets, including any extension headers
34
    uint16_t payloadLength;
35
    /// Specifies the type of the next header (protocol). Must be one of ::IPProtocolTypes
36
    uint8_t nextHeader;
37
    /// Replaces the time to live field of IPv4
38
    uint8_t hopLimit;
39
    /// Source address
40
    uint8_t ipSrc[16];
41
    /// Destination address
42
    uint8_t ipDst[16];
43
  };
44
#pragma pack(pop)
45
  static_assert(sizeof(ip6_hdr) == 40, "ip6_hdr size is not 40 bytes");
46
47
  /// @class IPv6Layer
48
  /// Represents an IPv6 protocol layer
49
  class IPv6Layer : public Layer, public IPLayer
50
  {
51
  public:
52
    /// A constructor that creates the layer from an existing packet raw data
53
    /// @param[in] data A pointer to the raw data (will be casted to @ref ip6_hdr)
54
    /// @param[in] dataLen Size of the data in bytes
55
    /// @param[in] prevLayer A pointer to the previous layer
56
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
57
    IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
58
59
    /// A constructor that allocates a new IPv6 header with empty fields
60
    IPv6Layer();
61
62
    /// A constructor that allocates a new IPv6 header with source and destination IPv6 addresses
63
    /// @param[in] srcIP Source IPv6 address
64
    /// @param[in] dstIP Destination IPv6 address
65
    IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP);
66
67
    /// A copy constructor that copies the entire header from the other IPv6Layer (including IPv6 extensions)
68
    IPv6Layer(const IPv6Layer& other);
69
70
    /// A destructor for this layer
71
    ~IPv6Layer() override;
72
73
    /// An assignment operator that first delete all data from current layer and then copy the entire header from
74
    /// the other IPv6Layer (including IPv6 extensions)
75
    IPv6Layer& operator=(const IPv6Layer& other);
76
77
    /// Get a pointer to the IPv6 header. Notice this points directly to the data, so every change will change the
78
    /// actual packet data
79
    /// @return A pointer to the @ref ip6_hdr
80
    ip6_hdr* getIPv6Header() const
81
213k
    {
82
213k
      return reinterpret_cast<ip6_hdr*>(m_Data);
83
213k
    }
84
85
    /// Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv6Address(),
86
    /// but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
87
    /// @return An IPAddress containing the source address
88
    IPAddress getSrcIPAddress() const override
89
72
    {
90
72
      return getSrcIPv6Address();
91
72
    }
92
93
    /// Get the source IP address in the form of IPv6Address
94
    /// @return An IPv6Address containing the source address
95
    IPv6Address getSrcIPv6Address() const
96
26.8k
    {
97
26.8k
      return getIPv6Header()->ipSrc;
98
26.8k
    }
99
100
    /// Set the source IP address
101
    /// @param[in] ipAddr The IP address to set
102
    void setSrcIPv6Address(const IPv6Address& ipAddr)
103
0
    {
104
0
      ipAddr.copyTo(getIPv6Header()->ipSrc);
105
0
    }
106
107
    /// Set the dest IP address
108
    /// @param[in] ipAddr The IP address to set
109
    void setDstIPv6Address(const IPv6Address& ipAddr)
110
0
    {
111
0
      ipAddr.copyTo(getIPv6Header()->ipDst);
112
0
    }
113
114
    /// Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv6Address(),
115
    /// but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
116
    /// @return An IPAddress containing the destination address
117
    IPAddress getDstIPAddress() const override
118
72
    {
119
72
      return getDstIPv6Address();
120
72
    }
121
122
    /// Get the destination IP address in the form of IPv6Address
123
    /// @return An IPv6Address containing the destination address
124
    IPv6Address getDstIPv6Address() const
125
26.8k
    {
126
26.8k
      return getIPv6Header()->ipDst;
127
26.8k
    }
128
129
    /// @return Number of IPv6 extensions in this layer
130
    size_t getExtensionCount() const;
131
132
    /// A templated getter for an IPv6 extension of a type TIPv6Extension. TIPv6Extension has to be one of the
133
    /// supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the requested extension type
134
    /// isn't found nullptr is returned
135
    /// @return A pointer to the extension instance or nullptr if the requested extension type isn't found
136
    template <class TIPv6Extension> TIPv6Extension* getExtensionOfType() const;
137
138
    /// Add a new extension of type TIPv6Extension to the layer. This is a templated method and TIPv6Extension has
139
    /// to be one of the supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the extension is
140
    /// added successfully a pointer to the newly added extension object is returned, otherwise nullptr is returned
141
    /// @param[in] extensionHeader The extension object to add. Notice the object passed here is read-only, meaning
142
    /// its data is copied but the object itself isn't modified
143
    /// @return If the extension is added successfully a pointer to the newly added extension object is returned.
144
    /// Otherwise nullptr is returned
145
    template <class TIPv6Extension> TIPv6Extension* addExtension(const TIPv6Extension& extensionHeader);
146
147
    /// Remove all IPv6 extensions in this layer
148
    void removeAllExtensions();
149
150
    /// @return True if this packet is an IPv6 fragment, meaning if it has an IPv6FragmentationHeader extension
151
    bool isFragment() const;
152
153
    /// The static method makes validation of input data
154
    /// @param[in] data The pointer to the beginning of byte stream of IP packet
155
    /// @param[in] dataLen The length of byte stream
156
    /// @return True if the data is valid and can represent the IPv6 packet
157
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
158
159
    // implement abstract methods
160
161
    /// Currently identifies the following next layers:
162
    /// - UdpLayer
163
    /// - TcpLayer
164
    /// - IPv4Layer (IP-in-IP)
165
    /// - IPv6Layer (IP-in-IP)
166
    /// - GreLayer
167
    /// - AuthenticationHeaderLayer (IPSec)
168
    /// - ESPLayer (IPSec)
169
    ///
170
    /// Otherwise sets PayloadLayer
171
    void parseNextLayer() override;
172
173
    /// @return Size of @ref ip6_hdr
174
    size_t getHeaderLen() const override
175
124k
    {
176
124k
      return sizeof(ip6_hdr) + m_ExtensionsLen;
177
124k
    }
178
179
    /// Calculate the following fields:
180
    /// - ip6_hdr#payloadLength = size of payload (all data minus header size)
181
    /// - ip6_hdr#ipVersion = 6
182
    /// - ip6_hdr#nextHeader = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP,
183
    /// ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP
184
    void computeCalculateFields() override;
185
186
    std::string toString() const override;
187
188
    OsiModelLayer getOsiModelLayer() const override
189
9.59k
    {
190
9.59k
      return OsiModelNetworkLayer;
191
9.59k
    }
192
193
  private:
194
    void initLayer();
195
    void parseExtensions();
196
    void deleteExtensions();
197
198
    IPv6Extension* m_FirstExtension;
199
    IPv6Extension* m_LastExtension;
200
    size_t m_ExtensionsLen;
201
  };
202
203
  template <class TIPv6Extension> TIPv6Extension* IPv6Layer::getExtensionOfType() const
204
0
  {
205
0
    IPv6Extension* curExt = m_FirstExtension;
206
0
    while (curExt != nullptr && dynamic_cast<TIPv6Extension*>(curExt) == nullptr)
207
0
      curExt = curExt->getNextHeader();
208
209
0
    return static_cast<TIPv6Extension*>(curExt);
210
0
  }
211
212
  template <class TIPv6Extension> TIPv6Extension* IPv6Layer::addExtension(const TIPv6Extension& extensionHeader)
213
  {
214
    int offsetToAddHeader = static_cast<int>(getHeaderLen());
215
    if (!extendLayer(offsetToAddHeader, extensionHeader.getExtensionLen()))
216
    {
217
      return nullptr;
218
    }
219
220
    TIPv6Extension* newHeader = new TIPv6Extension(this, static_cast<size_t>(offsetToAddHeader));
221
    (*newHeader) = extensionHeader;
222
223
    if (m_FirstExtension != nullptr)
224
    {
225
      newHeader->getBaseHeader()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader;
226
      m_LastExtension->getBaseHeader()->nextHeader = newHeader->getExtensionType();
227
      m_LastExtension->setNextHeader(newHeader);
228
      m_LastExtension = newHeader;
229
    }
230
    else
231
    {
232
      m_FirstExtension = newHeader;
233
      m_LastExtension = newHeader;
234
      newHeader->getBaseHeader()->nextHeader = getIPv6Header()->nextHeader;
235
      getIPv6Header()->nextHeader = newHeader->getExtensionType();
236
    }
237
238
    m_ExtensionsLen += newHeader->getExtensionLen();
239
240
    return newHeader;
241
  }
242
243
  // implementation of inline methods
244
245
  bool IPv6Layer::isDataValid(const uint8_t* data, size_t dataLen)
246
52.5k
  {
247
52.5k
    auto ip6Header = reinterpret_cast<const ip6_hdr*>(data);
248
52.5k
    return canReinterpretAs<ip6_hdr>(data, dataLen) && ip6Header->ipVersion == 6;
249
52.5k
  }
250
251
}  // namespace pcpp