Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Dist/header/IPv4Layer.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_IPV4_LAYER
2
#define PACKETPP_IPV4_LAYER
3
4
#include "Layer.h"
5
#include "TLVData.h"
6
#include "IpAddress.h"
7
#include "IPLayer.h"
8
#include <string.h>
9
#include <vector>
10
11
/// @file
12
13
/**
14
 * \namespace pcpp
15
 * \brief The main namespace for the PcapPlusPlus lib
16
 */
17
namespace pcpp
18
{
19
20
  /**
21
   * @struct iphdr
22
   * Represents an IPv4 protocol header
23
   */
24
#pragma pack(push, 1)
25
  struct iphdr
26
  {
27
#if (BYTE_ORDER == LITTLE_ENDIAN)
28
    /** IP header length, has the value of 5 for IPv4 */
29
    uint8_t internetHeaderLength:4,
30
    /** IP version number, has the value of 4 for IPv4 */
31
    ipVersion:4;
32
#else
33
    /** IP version number, has the value of 4 for IPv4 */
34
    uint8_t ipVersion:4,
35
    /** IP header length, has the value of 5 for IPv4 */
36
    internetHeaderLength:4;
37
#endif
38
    /** type of service, same as Differentiated Services Code Point (DSCP)*/
39
    uint8_t typeOfService;
40
    /** Entire packet (fragment) size, including header and data, in bytes */
41
    uint16_t totalLength;
42
    /** Identification field. Primarily used for uniquely identifying the group of fragments of a single IP datagram*/
43
    uint16_t ipId;
44
     /** Fragment offset field, measured in units of eight-byte blocks (64 bits) */
45
    uint16_t fragmentOffset;
46
    /** An eight-bit time to live field helps prevent datagrams from persisting (e.g. going in circles) on an internet.  In practice, the field has become a hop count */
47
    uint8_t timeToLive;
48
    /** Defines the protocol used in the data portion of the IP datagram. Must be one of ::IPProtocolTypes */
49
    uint8_t protocol;
50
    /** Error-checking of the header */
51
    uint16_t headerChecksum;
52
    /** IPv4 address of the sender of the packet */
53
    uint32_t ipSrc;
54
    /** IPv4 address of the receiver of the packet */
55
    uint32_t ipDst;
56
    /*The options start here. */
57
  };
58
#pragma pack(pop)
59
60
  /**
61
   * An enum for all possible IPv4 and IPv6 protocol types
62
   */
63
  enum IPProtocolTypes
64
  {
65
    /** Dummy protocol for TCP    */
66
    PACKETPP_IPPROTO_IP = 0,
67
    /** IPv6 Hop-by-Hop options   */
68
    PACKETPP_IPPROTO_HOPOPTS = 0,
69
    /** Internet Control Message Protocol */
70
    PACKETPP_IPPROTO_ICMP = 1,
71
    /** Internet Gateway Management Protocol */
72
    PACKETPP_IPPROTO_IGMP = 2,
73
    /** IPIP tunnels (older KA9Q tunnels use 94) */
74
    PACKETPP_IPPROTO_IPIP = 4,
75
    /** Transmission Control Protocol */
76
    PACKETPP_IPPROTO_TCP = 6,
77
    /** Exterior Gateway Protocol   */
78
    PACKETPP_IPPROTO_EGP = 8,
79
    /** PUP protocol        */
80
    PACKETPP_IPPROTO_PUP = 12,
81
    /** User Datagram Protocol    */
82
    PACKETPP_IPPROTO_UDP = 17,
83
    /** XNS IDP protocol      */
84
    PACKETPP_IPPROTO_IDP = 22,
85
    /** IPv6 header       */
86
    PACKETPP_IPPROTO_IPV6 = 41,
87
    /** IPv6 Routing header     */
88
    PACKETPP_IPPROTO_ROUTING = 43,
89
    /** IPv6 fragmentation header   */
90
    PACKETPP_IPPROTO_FRAGMENT = 44,
91
    /** GRE protocol */
92
    PACKETPP_IPPROTO_GRE = 47,
93
    /** encapsulating security payload  */
94
    PACKETPP_IPPROTO_ESP = 50,
95
    /** authentication header   */
96
    PACKETPP_IPPROTO_AH = 51,
97
    /** ICMPv6        */
98
    PACKETPP_IPPROTO_ICMPV6 = 58,
99
    /** IPv6 no next header     */
100
    PACKETPP_IPPROTO_NONE = 59,
101
    /** IPv6 Destination options    */
102
    PACKETPP_IPPROTO_DSTOPTS = 60,
103
    /** Raw IP packets      */
104
    PACKETPP_IPPROTO_RAW = 255,
105
    /** Maximum value */
106
    PACKETPP_IPPROTO_MAX
107
  };
108
109
110
  /**
111
   * An enum for supported IPv4 option types
112
   */
113
  enum IPv4OptionTypes
114
  {
115
    /** End of Options List */
116
    IPV4OPT_EndOfOptionsList = 0,
117
    /** No Operation */
118
    IPV4OPT_NOP = 1,
119
    /** Record Route */
120
    IPV4OPT_RecordRoute = 7,
121
    /** MTU Probe */
122
    IPV4OPT_MTUProbe = 11,
123
    /** MTU Reply */
124
    IPV4OPT_MTUReply = 12,
125
    /** Quick-Start */
126
    IPV4OPT_QuickStart = 25,
127
    /** Timestamp */
128
    IPV4OPT_Timestamp = 68,
129
    /** Traceroute */
130
    IPV4OPT_Traceroute = 82,
131
    /** Security */
132
    IPV4OPT_Security = 130,
133
    /** Loose Source Route */
134
    IPV4OPT_LooseSourceRoute = 131,
135
    /** Extended Security */
136
    IPV4OPT_ExtendedSecurity = 133,
137
    /** Commercial Security */
138
    IPV4OPT_CommercialSecurity = 134,
139
    /** Stream ID */
140
    IPV4OPT_StreamID = 136,
141
    /** Strict Source Route */
142
    IPV4OPT_StrictSourceRoute = 137,
143
    /** Extended Internet Protocol */
144
    IPV4OPT_ExtendedInternetProtocol = 145,
145
    /** Address Extension */
146
    IPV4OPT_AddressExtension = 147,
147
    /** Router Alert */
148
    IPV4OPT_RouterAlert = 148,
149
    /** Selective Directed Broadcast */
150
    IPV4OPT_SelectiveDirectedBroadcast = 149,
151
    /** Dynamic Packet State */
152
    IPV4OPT_DynamicPacketState = 151,
153
    /** Upstream Multicast Pkt. */
154
    IPV4OPT_UpstreamMulticastPkt = 152,
155
    /** Unknown IPv4 option */
156
    IPV4OPT_Unknown
157
  };
158
159
#define PCPP_IP_DONT_FRAGMENT  0x40
160
#define PCPP_IP_MORE_FRAGMENTS 0x20
161
162
  /**
163
   * @struct IPv4TimestampOptionValue
164
   * A struct representing a parsed value of the IPv4 timestamp option. This struct is used returned in IPv4OptionData#getTimestampOptionValue() method
165
   */
166
  struct IPv4TimestampOptionValue
167
  {
168
    /**
169
     * An enum for IPv4 timestamp option types
170
     */
171
    enum TimestampType
172
    {
173
      /** Value containing only timestamps */
174
      TimestampOnly = 0,
175
      /** Value containing both timestamps and IPv4 addresses */
176
      TimestampAndIP = 1,
177
      /** The IPv4 addresses are prespecified */
178
      TimestampsForPrespecifiedIPs = 2,
179
      /** Invalid or unknown value type */
180
      Unknown = 3
181
    };
182
183
    /** The timestamp value type */
184
    TimestampType type;
185
186
    /** A list of timestamps parsed from the IPv4 timestamp option value */
187
    std::vector<uint32_t> timestamps;
188
189
    /** A list of IPv4 addresses parsed from the IPv4 timestamp option value */
190
    std::vector<IPv4Address> ipAddresses;
191
192
    /** The default constructor */
193
0
    IPv4TimestampOptionValue() : type(IPv4TimestampOptionValue::Unknown) {}
194
195
    /**
196
     * Clear the structure. Clean the timestamps and IP addresses vectors and set the type as IPv4TimestampOptionValue#Unknown
197
     */
198
    void clear()
199
0
    {
200
0
      type = IPv4TimestampOptionValue::Unknown;
201
0
      timestamps.clear();
202
0
      ipAddresses.clear();
203
0
    }
204
  };
205
206
207
  /**
208
   * @class IPv4Option
209
   * A wrapper class for IPv4 options. This class does not create or modify IPv4 option records, but rather
210
   * serves as a wrapper and provides useful methods for retrieving data from them
211
   */
212
  class IPv4Option : public TLVRecord<uint8_t, uint8_t>
213
  {
214
  public:
215
216
    /**
217
     * A c'tor for this class that gets a pointer to the option raw data (byte array)
218
     * @param[in] optionRawData A pointer to the IPv4 option raw data
219
     */
220
    explicit IPv4Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
221
222
    /**
223
     * A d'tor for this class, currently does nothing
224
     */
225
0
    ~IPv4Option() { }
226
227
    /**
228
     * A method for parsing the IPv4 option value as a list of IPv4 addresses. This method is relevant only for certain types of IPv4 options which their value is a list of IPv4 addresses
229
     * such as ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute, etc. This method returns a vector of the IPv4 addresses. Blank IP addresses
230
     * (meaning zeroed addresses - 0.0.0.0) will not be added to the returned list. If some error occurs during the parsing or the value is invalid an empty vector is returned
231
     * @return A vector of IPv4 addresses parsed from the IPv4 option value
232
     */
233
    std::vector<IPv4Address> getValueAsIpList() const
234
0
    {
235
0
      std::vector<IPv4Address> res;
236
0
237
0
      if (m_Data == NULL)
238
0
        return res;
239
0
240
0
      size_t dataSize = getDataSize();
241
0
      if (dataSize < 2)
242
0
        return res;
243
0
244
0
      uint8_t valueOffset = (uint8_t)(1);
245
0
246
0
      while ((size_t)valueOffset < dataSize)
247
0
      {
248
0
        uint32_t curValue;
249
0
        memcpy(&curValue, m_Data->recordValue + valueOffset, sizeof(uint32_t));
250
0
        if (curValue == 0)
251
0
          break;
252
0
253
0
        res.push_back(IPv4Address(curValue));
254
0
255
0
        valueOffset += (uint8_t)(4);
256
0
      }
257
0
258
0
      return res;
259
0
    }
260
261
    /**
262
     * A method for parsing the IPv4 timestamp option value. This method is relevant only for IPv4 timestamp option. For other option types an empty result will be returned.
263
     * The returned structure contains the timestamp value type (timestamp only, timestamp + IP addresses, etc.) as well as 2 vectors containing the list of timestamps and the list
264
     * of IP addresses (if applicable for the timestamp value type). Blank timestamps or IP addresses (meaning zeroed values - timestamp=0 or IP address=0.0.0.0) will not be added to
265
     * the lists. If some error occurs during the parsing or the value is invalid an empty result is returned
266
     * @return A structured containing the IPv4 timestamp value
267
     */
268
    IPv4TimestampOptionValue getTimestampOptionValue() const
269
0
    {
270
0
      IPv4TimestampOptionValue res;
271
0
      res.clear();
272
0
273
0
      if (m_Data == NULL)
274
0
        return res;
275
0
276
0
      if (getIPv4OptionType() != IPV4OPT_Timestamp)
277
0
        return res;
278
0
279
0
      size_t dataSize =  getDataSize();
280
0
      if (dataSize < 2)
281
0
        return res;
282
0
283
0
      res.type = (IPv4TimestampOptionValue::TimestampType)m_Data->recordValue[1];
284
0
285
0
      uint8_t valueOffset = (uint8_t)(2);
286
0
      bool readIPAddr = (res.type == IPv4TimestampOptionValue::TimestampAndIP);
287
0
288
0
      while ((size_t)valueOffset < dataSize)
289
0
      {
290
0
        uint32_t curValue;
291
0
        memcpy(&curValue, m_Data->recordValue + valueOffset, sizeof(uint32_t));
292
0
        if (curValue == 0)
293
0
          break;
294
0
295
0
        if (readIPAddr)
296
0
          res.ipAddresses.push_back(IPv4Address(curValue));
297
0
        else
298
0
          res.timestamps.push_back(curValue);
299
0
300
0
        if (res.type == IPv4TimestampOptionValue::TimestampAndIP)
301
0
          readIPAddr = !readIPAddr;
302
0
303
0
        valueOffset += (uint8_t)(4);
304
0
      }
305
0
306
0
      return res;
307
0
    }
308
309
    /**
310
     * @return IPv4 option type casted as pcpp::IPv4OptionTypes enum
311
     */
312
    IPv4OptionTypes getIPv4OptionType() const
313
    {
314
      if (m_Data == NULL)
315
        return IPV4OPT_Unknown;
316
317
      return (IPv4OptionTypes)m_Data->recordType;
318
    }
319
320
321
    // implement abstract methods
322
323
    size_t getTotalSize() const
324
    {
325
      if (m_Data == NULL)
326
        return 0;
327
328
      if (getIPv4OptionType() == (uint8_t)IPV4OPT_EndOfOptionsList || m_Data->recordType == (uint8_t)IPV4OPT_NOP)
329
        return sizeof(uint8_t);
330
331
      return (size_t)m_Data->recordLen;
332
    }
333
334
    size_t getDataSize() const
335
    {
336
      if (m_Data == NULL)
337
        return 0;
338
339
      if (getIPv4OptionType() == (uint8_t)IPV4OPT_EndOfOptionsList || m_Data->recordType == (uint8_t)IPV4OPT_NOP)
340
        return (size_t)0;
341
342
      return (size_t)m_Data->recordLen - (2*sizeof(uint8_t));
343
    }
344
  };
345
346
347
  /**
348
   * @class IPv4OptionBuilder
349
   * A class for building IPv4 option records. This builder receives the IPv4 option parameters in its c'tor,
350
   * builds the IPv4 option raw buffer and provides a build() method to get a IPv4Option object out of it
351
   */
352
  class IPv4OptionBuilder : public TLVRecordBuilder
353
  {
354
  private:
355
    bool m_BuilderParamsValid;
356
357
  public:
358
359
    /**
360
     * A c'tor for building IPv4 options which their value is a byte array. The IPv4Option object can be later
361
     * retrieved by calling build()
362
     * @param[in] optionType IPv4 option type
363
     * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way.
364
     * For option types ::IPV4OPT_NOP and ::IPV4OPT_EndOfOptionsList this parameter is ignored (expected to be NULL) as these
365
     * option types don't contain any data
366
     * @param[in] optionValueLen Option value length in bytes
367
     */
368
    IPv4OptionBuilder(IPv4OptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
369
0
      TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) { m_BuilderParamsValid = true; }
370
371
    /**
372
     * A c'tor for building IPv4 options which have a 2-byte value. The IPv4Option object can be later retrieved
373
     * by calling build()
374
     * @param[in] optionType IPv4 option type
375
     * @param[in] optionValue A 2-byte option value
376
     */
377
    IPv4OptionBuilder(IPv4OptionTypes optionType, uint16_t optionValue) :
378
0
      TLVRecordBuilder((uint8_t)optionType, optionValue) { m_BuilderParamsValid = true; }
379
380
    /**
381
     * A c'tor for building IPv4 options which their value is a list of IPv4 addresses, for example:
382
     * ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute. The IPv4Option object can be later retrieved
383
     * by calling build()
384
     * @param[in] optionType IPv4 option type
385
     * @param[in] ipList A vector of IPv4 addresses that will be used as the option value
386
     */
387
    IPv4OptionBuilder(IPv4OptionTypes optionType, const std::vector<IPv4Address>& ipList);
388
389
    /**
390
     * A c'tor for building IPv4 timestamp option (::IPV4OPT_Timestamp). The IPv4Option object can be later retrieved by calling build()
391
     * @param[in] timestampValue The timestamp value to build the IPv4 option with
392
     */
393
    explicit IPv4OptionBuilder(const IPv4TimestampOptionValue& timestampValue);
394
395
    /**
396
     * Build the IPv4Option object out of the parameters defined in the c'tor
397
     * @return The IPv4Option object
398
     */
399
    IPv4Option build() const;
400
  };
401
402
403
  /**
404
   * @class IPv4Layer
405
   * Represents an IPv4 protocol layer
406
   */
407
  class IPv4Layer : public Layer, public IPLayer
408
  {
409
  public:
410
    /**
411
     * A constructor that creates the layer from an existing packet raw data
412
     * @param[in] data A pointer to the raw data (will be casted to @ref iphdr)
413
     * @param[in] dataLen Size of the data in bytes
414
     * @param[in] prevLayer A pointer to the previous layer
415
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
416
     */
417
    IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
418
419
    /**
420
     * A constructor that creates the layer from an existing packet raw data
421
     * @param[in] data A pointer to the raw data (will be casted to @ref iphdr)
422
     * @param[in] dataLen Size of the data in bytes
423
     * @param[in] prevLayer A pointer to the previous layer
424
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
425
     * @param[in] setTotalLenAsDataLen When setting this value to "true" or when using the other c'tor, the layer data length is calculated
426
     * from iphdr#totalLength field. When setting to "false" the data length is set as the value of dataLen parameter. Please notice that
427
     * if iphdr#totalLength is equal to zero (which can happen in TCP Segmentation Offloading), this flag is ignored and the layer data
428
     * length is calculated by the actual data captured on the wire
429
     */
430
    IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen);
431
432
433
    /**
434
     * A constructor that allocates a new IPv4 header with empty fields
435
     */
436
    IPv4Layer();
437
438
    /**
439
     * A constructor that allocates a new IPv4 header with source and destination IPv4 addresses
440
     * @param[in] srcIP Source IPv4 address
441
     * @param[in] dstIP Destination IPv4 address
442
     */
443
    IPv4Layer(const IPv4Address& srcIP, const IPv4Address& dstIP);
444
445
    /**
446
     * A copy constructor that copy the entire header from the other IPv4Layer (including IPv4 options)
447
     */
448
    IPv4Layer(const IPv4Layer& other);
449
450
    /**
451
     * An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv4Layer (including IPv4 options)
452
     */
453
    IPv4Layer& operator=(const IPv4Layer& other);
454
455
    /**
456
     * Get a pointer to the IPv4 header. Notice this points directly to the data, so every change will change the actual packet data
457
     * @return A pointer to the @ref iphdr
458
     */
459
2.40M
    iphdr* getIPv4Header() const { return (iphdr*)m_Data; }
460
461
    /**
462
     * Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv4Address(),
463
     * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
464
     * @return An IPAddress containing the source address
465
     */
466
    IPAddress getSrcIPAddress() const { return getSrcIPv4Address(); }
467
468
    /**
469
     * Get the source IP address in the form of IPv4Address
470
     * @return An IPv4Address containing the source address
471
     */
472
341k
    IPv4Address getSrcIPv4Address() const { return getIPv4Header()->ipSrc; }
473
474
    /**
475
     * Set the source IP address
476
     * @param[in] ipAddr The IP address to set
477
     */
478
0
    void setSrcIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipSrc = ipAddr.toInt(); }
479
480
    /**
481
     * Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv4Address(),
482
     * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses
483
     * @return An IPAddress containing the destination address
484
     */
485
    IPAddress getDstIPAddress() const { return getDstIPv4Address(); }
486
487
    /**
488
     * Get the destination IP address in the form of IPv4Address
489
     * @return An IPv4Address containing the destination address
490
     */
491
341k
    IPv4Address getDstIPv4Address() const { return getIPv4Header()->ipDst; }
492
493
    /**
494
     * Set the dest IP address
495
     * @param[in] ipAddr The IP address to set
496
     */
497
0
    void setDstIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipDst = ipAddr.toInt(); }
498
499
    /**
500
     * @return True if this packet is a fragment (in sense of IP fragmentation), false otherwise
501
     */
502
    bool isFragment() const;
503
504
    /**
505
     * @return True if this packet is a fragment (in sense of IP fragmentation) and is the first fragment
506
     * (which usually contains the L4 header). Return false otherwise (not a fragment or not the first fragment)
507
     */
508
    bool isFirstFragment() const;
509
510
    /**
511
     * @return True if this packet is a fragment (in sense of IP fragmentation) and is the last fragment.
512
     * Return false otherwise (not a fragment or not the last fragment)
513
     */
514
    bool isLastFragment() const;
515
516
    /**
517
     * @return A bitmask containing the fragmentation flags (e.g IP_DONT_FRAGMENT or IP_MORE_FRAGMENTS)
518
     */
519
    uint8_t getFragmentFlags() const;
520
521
    /**
522
     * @return The fragment offset in case this packet is a fragment, 0 otherwise
523
     */
524
    uint16_t getFragmentOffset() const;
525
526
    /**
527
     * Get an IPv4 option by type.
528
     * @param[in] option IPv4 option type
529
     * @return An IPv4Option object that contains the first option that matches this type, or logical NULL
530
     * (IPv4Option#isNull() == true) if no such option found
531
     */
532
    IPv4Option getOption(IPv4OptionTypes option) const;
533
534
    /**
535
     * @return The first IPv4 option in the packet. If the current layer contains no options the returned value will contain
536
     * a logical NULL (IPv4Option#isNull() == true)
537
     */
538
    IPv4Option getFirstOption() const;
539
540
    /**
541
     * Get the IPv4 option that comes after a given option. If the given option was the last one, the
542
     * returned value will contain a logical NULL (IPv4Option#isNull() == true)
543
     * @param[in] option An IPv4 option object that exists in the current layer
544
     * @return A IPv4Option object that contains the IPv4 option data that comes next, or logical NULL if the given
545
     * IPv4 option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet
546
     */
547
    IPv4Option getNextOption(IPv4Option& option) const;
548
549
    /**
550
     * @return The number of IPv4 options in this layer
551
     */
552
    size_t getOptionCount() const;
553
554
    /**
555
     * Add a new IPv4 option at the end of the layer (after the last IPv4 option)
556
     * @param[in] optionBuilder An IPv4OptionBuilder object that contains the IPv4 option data to be added
557
     * @return A IPv4Option object that contains the newly added IPv4 option data or logical NULL
558
     * (IPv4Option#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
559
     * printed to log
560
     */
561
    IPv4Option addOption(const IPv4OptionBuilder& optionBuilder);
562
563
    /**
564
     * Add a new IPv4 option after an existing one
565
     * @param[in] optionBuilder An IPv4OptionBuilder object that contains the requested IPv4 option data to be added
566
     * @param[in] prevOptionType The IPv4 option which the newly added option should come after. This is an optional parameter which
567
     * gets a default value of ::IPV4OPT_Unknown if omitted, which means the new option will be added as the first option in the layer
568
     * @return A IPv4Option object containing the newly added IPv4 option data or logical NULL
569
     * (IPv4Option#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
570
     * printed to log
571
     */
572
    IPv4Option addOptionAfter(const IPv4OptionBuilder& optionBuilder, IPv4OptionTypes prevOptionType = IPV4OPT_Unknown);
573
574
    /**
575
     * Remove an IPv4 option
576
     * @param[in] option The option type to remove
577
     * @return True if option was removed successfully or false if option type wasn't found or failed to shorten the layer. If an option appears twice in the layer, its first instance
578
     * will be removed
579
     */
580
    bool removeOption(IPv4OptionTypes option);
581
582
    /**
583
     * Remove all IPv4 options from the layer
584
     * @return True if options removed successfully or false if some error occurred (an appropriate error message will be printed to log)
585
     */
586
    bool removeAllOptions();
587
588
589
    // implement abstract methods
590
591
    /**
592
     * Currently identifies the following next layers:
593
     * - UdpLayer
594
     * - TcpLayer
595
     * - IcmpLayer
596
     * - IPv4Layer (IP-in-IP)
597
     * - IPv6Layer (IP-in-IP)
598
     * - GreLayer
599
     * - IgmpLayer
600
     * - AuthenticationHeaderLayer (IPSec)
601
     * - ESPLayer (IPSec)
602
     *
603
     * Otherwise sets PayloadLayer
604
     */
605
    void parseNextLayer();
606
607
    /**
608
     * @return Size of IPv4 header (including IPv4 options if exist)
609
     */
610
    size_t getHeaderLen() const { return (size_t)((uint16_t)(getIPv4Header()->internetHeaderLength) * 4) + m_TempHeaderExtension; }
611
612
    /**
613
     * Calculate the following fields:
614
     * - iphdr#ipVersion = 4;
615
     * - iphdr#totalLength = total packet length
616
     * - iphdr#headerChecksum = calculated
617
     * - iphdr#protocol = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP
618
     */
619
    void computeCalculateFields();
620
621
    std::string toString() const;
622
623
    OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
624
625
    /**
626
     * A static method that validates the input data
627
     * @param[in] data The pointer to the beginning of a byte stream of IP packet
628
     * @param[in] dataLen The length of the byte stream
629
     * @return True if the data is valid and can represent an IPv4 packet
630
     */
631
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
632
633
  private:
634
    int m_NumOfTrailingBytes;
635
    int m_TempHeaderExtension;
636
    TLVRecordReader<IPv4Option> m_OptionReader;
637
638
    void copyLayerData(const IPv4Layer& other);
639
    uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(iphdr); }
640
    IPv4Option addOptionAt(const IPv4OptionBuilder& optionBuilder, int offset);
641
    void adjustOptionsTrailer(size_t totalOptSize);
642
    void initLayer();
643
    void initLayerInPacket(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen);
644
  };
645
646
647
  // implementation of inline methods
648
649
  bool IPv4Layer::isDataValid(const uint8_t* data, size_t dataLen)
650
  {
651
    const iphdr* hdr = reinterpret_cast<const iphdr*>(data);
652
    return dataLen >= sizeof(iphdr) && hdr->ipVersion == 4 && hdr->internetHeaderLength >= 5;
653
  }
654
655
} // namespace pcpp
656
657
#endif /* PACKETPP_IPV4_LAYER */