Coverage Report

Created: 2024-02-25 06:29

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