Coverage Report

Created: 2023-01-17 06:15

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