Coverage Report

Created: 2026-10-17 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/VrrpLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "Layer.h"
4
#include "IpAddress.h"
5
#include <vector>
6
7
/// @file
8
9
/// @namespace pcpp
10
/// @brief The main namespace for the PcapPlusPlus lib
11
namespace pcpp
12
{
13
  /// For more info see:
14
  ///     https://datatracker.ietf.org/doc/html/rfc2338
15
  ///     https://datatracker.ietf.org/doc/html/rfc3768
16
  ///     https://datatracker.ietf.org/doc/html/rfc5798
17
18
  /// VRRPv2 Packet Format
19
  ///    0                   1                   2                   3
20
  ///    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
21
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
  ///   |Version| Type  | Virtual Rtr ID|   Priority    | Count IP Addrs|
23
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24
  ///   |   Auth Type   |   Adver Int   |          Checksum             |
25
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
  ///   |                         IP Address (1)                        |
27
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
  ///   |                            .                                  |
29
  ///   |                            .                                  |
30
  ///   |                            .                                  |
31
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32
  ///   |                         IP Address (n)                        |
33
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34
  ///   |                     Authentication Data (1)                   |
35
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36
  ///   |                     Authentication Data (2)                   |
37
  ///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38
39
  /// VRRPv3 Packet Format
40
  ///     0                   1                   2                   3
41
  ///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
42
  ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
  ///    |                    IPv4 Fields or IPv6 Fields                 |
44
  ///   ...                                                             ...
45
  ///    |                                                               |
46
  ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
  ///    |Version| Type  | Virtual Rtr ID|   Priority    |Count IPvX Addr|
48
  ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
  ///    |(rsvd) |     Max Adver Int     |          Checksum             |
50
  ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51
  ///    |                                                               |
52
  ///    +                                                               +
53
  ///    |                       IPvX Address(es)                        |
54
  ///    +                                                               +
55
  ///    +                                                               +
56
  ///    +                                                               +
57
  ///    +                                                               +
58
  ///    |                                                               |
59
  ///    +                                                               +
60
  ///    |                                                               |
61
  ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
63
  /// @struct vrrp_header
64
  /// VRRP generic header
65
  struct vrrp_header
66
  {
67
#if (BYTE_ORDER == LITTLE_ENDIAN)
68
    /// Type
69
    uint8_t type : 4;
70
71
    /// Version bits
72
    uint8_t version : 4;
73
#else
74
    /// Version bits
75
    uint8_t version : 4;
76
77
    /// Type
78
    uint8_t type : 4;
79
#endif
80
    /// The Virtual Router Identifier (VRID) field identifies the virtual router this packet is reporting status
81
    /// for
82
    uint8_t vrId;
83
84
    /// This specifies the sending VRRP router's priority for the virtual router
85
    uint8_t priority;
86
87
    /// Specifies how many IPvX addresses are present in this Packet
88
    uint8_t ipAddrCount;
89
90
    /// This specifies authentication type(v2) or (Max) Advertisement interval (in seconds(v2) or
91
    /// centi-seconds(v3)).
92
    uint16_t authTypeAdvInt;
93
94
    /// This specifies checksum field that is used to detect data corruption in the VRRP message.
95
    /// VRRPv2 uses normal checksum algorithm, while VRRPv3 uses "pseudo-header" checksum algorithm.
96
    uint16_t checksum;
97
98
    /// This specifies one or more IPvX addresses that are associated with the virtual router.
99
    uint8_t* ipAddresses[];
100
  };
101
  static_assert(sizeof(vrrp_header) == 8, "vrrp_header size is not 8 bytes");
102
103
  /// @class VrrpLayer
104
  /// A base class for all VRRP (Virtual Router Redundancy Protocol) protocol classes. This is an abstract class and
105
  /// cannot be instantiated, only its child classes can be instantiated. The inherited classes represent the
106
  /// different versions of the protocol: VRRPv2 and VRRPv3
107
  class VrrpLayer : public Layer
108
  {
109
  private:
110
    bool addIPAddressesAt(const std::vector<IPAddress>& ipAddresses, int offset);
111
112
    uint8_t getIPAddressLen() const;
113
114
    bool isIPAddressValid(IPAddress& ipAddress) const;
115
116
    uint8_t* getFirstIPAddressPtr() const;
117
118
    uint8_t* getNextIPAddressPtr(uint8_t* ipAddressPtr) const;
119
120
    IPAddress getIPAddressFromData(uint8_t* data) const;
121
122
    void copyIPAddressToData(uint8_t* data, const IPAddress& ipAddress) const;
123
124
    IPAddress::AddressType m_AddressType;
125
126
  protected:
127
    VrrpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType vrrpVer,
128
              IPAddress::AddressType addressType)
129
14.1k
        : Layer(data, dataLen, prevLayer, packet, vrrpVer), m_AddressType(addressType)
130
14.1k
    {}
131
132
    explicit VrrpLayer(ProtocolType subProtocol, uint8_t virtualRouterId, uint8_t priority);
133
134
    vrrp_header* getVrrpHeader() const
135
50.1k
    {
136
50.1k
      return reinterpret_cast<vrrp_header*>(m_Data);
137
50.1k
    }
138
139
    void setAddressType(IPAddress::AddressType addressType);
140
141
    void serializeLayer(ObjectScope& serializer) const override;
142
143
    virtual void serializeVrrpLayer(ObjectScope& serializer) const = 0;
144
145
  public:
146
    /// VRRP message types
147
    enum VrrpType
148
    {
149
      /// Unknown VRRP message
150
      VrrpType_Unknown = 0,
151
152
      /// VRRP advertisement message
153
      VrrpType_Advertisement = 1
154
    };
155
156
    /// An enum describing VRRP special priority values
157
    enum VrrpPriority
158
    {
159
      /// Default priority for a backup VRRP router (value of 100)
160
      Default,
161
      /// Current Master has stopped participating in VRRP (value of 0)
162
      Stop,
163
      /// This VRRP router owns the virtual router's IP address(es) (value of 255)
164
      Owner,
165
      /// Other priority
166
      Other
167
    };
168
169
    ~VrrpLayer() override = default;
170
171
    /// @return The VRRP IP Address type
172
    IPAddress::AddressType getAddressType() const;
173
174
    /// A static method that validates the input data
175
    /// @param[in] data VRRP raw data (byte stream)
176
    /// @param[in] dataLen The length of the byte stream
177
    /// @return One of the values ::VRRPv2, ::VRRPv3 according to detected VRRP version or ::UnknownProtocol if
178
    /// couldn't detect VRRP version
179
    static ProtocolType getVersionFromData(uint8_t* data, size_t dataLen);
180
181
    /// @return VRRP version of this message
182
    uint8_t getVersion() const;
183
184
    /// @return VRRP type set in vrrp_header#type as VrrpLayer::VrrpType enum.
185
    VrrpType getType() const;
186
187
    /// @return The virtual router id (vrId) in this message
188
    uint8_t getVirtualRouterID() const;
189
190
    /// Set the virtual router ID
191
    /// @param virtualRouterID new ID to set
192
    void setVirtualRouterID(uint8_t virtualRouterID);
193
194
    /// @return The priority in this message
195
196
    uint8_t getPriority() const;
197
198
    /// @return An enum describing VRRP priority
199
    VrrpPriority getPriorityAsEnum() const;
200
201
    /// Set the priority
202
    /// @param priority new priority to set
203
    void setPriority(uint8_t priority);
204
205
    /// @return VRRP checksum of this message
206
    uint16_t getChecksum() const;
207
208
    /// Fill the checksum from header and data and write the result to @ref vrrp_header#checksum
209
    void calculateAndSetChecksum();
210
211
    /// Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum
212
    /// @return The checksum result
213
    virtual uint16_t calculateChecksum() const = 0;
214
215
    /// @return True if VRRP checksum is correct
216
    bool isChecksumCorrect() const;
217
218
    /// @return The count of VRRP virtual IP addresses in this message
219
    uint8_t getIPAddressesCount() const;
220
221
    /// @return A list of the virtual IP addresses in this message
222
    std::vector<IPAddress> getIPAddresses() const;
223
224
    /// Add a list of virtual IP addresses at a the end of the virtual IP address list. The
225
    /// vrrp_header#ipAddressCount field will be incremented accordingly
226
    /// @param[in] ipAddresses A vector containing all the virtual IP address
227
    /// @return true if added successfully, false otherwise
228
    bool addIPAddresses(const std::vector<IPAddress>& ipAddresses);
229
230
    /// Add a virtual IP address at a the end of the virtual IP address list. The vrrp_header#ipAddressCount field
231
    /// will be incremented accordingly
232
    /// @param[in] ipAddress Virtual IP address to add
233
    /// @return true if add successfully, false otherwise
234
    bool addIPAddress(const IPAddress& ipAddress);
235
236
    /// Remove a virtual IP address at a certain index. The vrrp_header#ipAddressCount field will be decremented
237
    /// accordingly
238
    /// @param[in] index The index of the virtual IP address to be removed
239
    /// @return True if virtual IP address was removed successfully or false otherwise. If false is returned an
240
    /// appropriate error message will be printed to log
241
    bool removeIPAddressAtIndex(int index);
242
243
    /// Remove all virtual IP addresses in the message. The vrrp_header#ipAddressCount field will be set to 0
244
    /// @return True if virtual IP addresses were cleared successfully or false otherwise. If false is returned an
245
    /// appropriate error message will be printed to log
246
    bool removeAllIPAddresses();
247
248
    // implement abstract methods
249
250
    /// Does nothing for this layer (VRRP layer is always last)
251
    void parseNextLayer() override
252
14.1k
    {}
253
254
    /// Calculate the VRRP checksum
255
    void computeCalculateFields() override;
256
257
    /// @return The message size in bytes which include the size of the basic header + the size of the IP
258
    /// address(es)
259
    size_t getHeaderLen() const override
260
21.9k
    {
261
21.9k
      return m_DataLen;
262
21.9k
    }
263
264
    std::string toString() const override;
265
266
    OsiModelLayer getOsiModelLayer() const override
267
3.25k
    {
268
3.25k
      return OsiModelNetworkLayer;
269
3.25k
    }
270
271
    /// @struct SerializedFields
272
    /// Fields written by VrrpLayer's serializeLayer(), in addition to
273
    /// Layer::SerializedFields.
274
    struct SerializedFields : Layer::SerializedFields
275
    {
276
      /// @return All field descriptors for VrrpLayer
277
      static std::vector<FieldDescriptor> all()
278
0
      {
279
0
        auto result = Layer::SerializedFields::all();
280
0
        std::initializer_list<FieldDescriptor> extra{ Type, VirtualRouterID, Priority, Checksum, IPAddresses };
281
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
282
0
        return result;
283
0
      }
284
285
      /// @brief Field descriptor for the VRRP message type, written as a string.
286
      static const FieldDescriptor Type;
287
288
      /// @brief Field descriptor for the virtual router ID (VRID), written as a number.
289
      static const FieldDescriptor VirtualRouterID;
290
291
      /// @brief Field descriptor for the priority category, written as a string: "Default", "Stop",
292
      /// "Owner" or "Other".
293
      static const FieldDescriptor Priority;
294
295
      /// @brief Field descriptor for the raw priority value, written as a number.
296
      static const FieldDescriptor PriorityValue;
297
298
      /// @brief Field descriptor for the VRRP checksum, written as a hex value.
299
      static const FieldDescriptor Checksum;
300
301
      /// @brief Field descriptor for the array of virtual router IP addresses.
302
      static const FieldDescriptor IPAddresses;
303
304
      /// @brief Field descriptor for a single entry of the IPAddresses array, written as an IP address string.
305
      static const FieldDescriptor IPAddress;
306
307
      /// Maximum field ID used by the layer.
308
      static constexpr uint16_t MaxID = Layer::SerializedFields::MaxID + 5;
309
    };
310
  };
311
312
  /// @class VrrpV2Layer
313
  /// Represents VRRPv2 (Virtual Router Redundancy Protocol ver 2) layer. This class represents all the different
314
  /// messages of VRRPv2
315
  class VrrpV2Layer : public VrrpLayer
316
  {
317
  private:
318
    struct vrrpv2_auth_adv
319
    {
320
      uint8_t authType;
321
      uint8_t advInt;
322
    };
323
324
  public:
325
    /// VRRP v2 authentication types
326
    enum class VrrpAuthType : uint8_t
327
    {
328
      /// No Authentication
329
      NoAuthentication = 0,
330
      /// Simple Text Password
331
      SimpleTextPassword = 1,
332
      /// IP Authentication Header
333
      IPAuthenticationHeader = 2,
334
      /// Cisco VRRP MD5 Authentication
335
      MD5 = 3,
336
      /// Other/Unknown Authentication Type
337
      Other = 4
338
    };
339
340
    /// A constructor that creates the layer from an existing packet raw data
341
    /// @param[in] data A pointer to the raw data
342
    /// @param[in] dataLen Size of the data in bytes
343
    /// @param[in] prevLayer A pointer to the previous layer
344
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
345
    VrrpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
346
6.42k
        : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv2, IPAddress::IPv4AddressType)
347
6.42k
    {}
348
349
    /// A constructor that allocates a new VRRP v2 layer
350
    /// @param virtualRouterId Virtual router ID
351
    /// @param priority Priority
352
    /// @param advInt Advertisement interval
353
    /// @param authType Authentication type (default value is 0)
354
    explicit VrrpV2Layer(uint8_t virtualRouterId, uint8_t priority, uint8_t advInt, uint8_t authType = 0);
355
356
    /// A destructor for this layer (does nothing)
357
    ~VrrpV2Layer() override = default;
358
359
    /// @return The VRRP advertisement interval in this message
360
    uint8_t getAdvInt() const;
361
362
    /// Set advertisement interval value in this message
363
    /// @param advInt value to set
364
    void setAdvInt(uint8_t advInt);
365
366
    /// @return The authentication type in this message
367
    uint8_t getAuthType() const;
368
369
    /// @return The VRRP authentication type as enum
370
    VrrpAuthType getAuthTypeAsEnum() const;
371
372
    /// Set VRRP authentication type
373
    /// @param authType value to set
374
    void setAuthType(uint8_t authType);
375
376
    // implement abstract methods
377
378
    /// Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum
379
    /// @return The checksum result
380
    uint16_t calculateChecksum() const override;
381
382
    /// A static method that validates the input data
383
    /// @param[in] data The pointer to the beginning of a byte stream of an VRRPv2 layer
384
    /// @param[in] dataLen The length of the byte stream
385
    /// @return True if the data is valid and can represent an VRRPv2 layer
386
    static bool isDataValid(uint8_t const* data, size_t dataLen)
387
6.42k
    {
388
6.42k
      return canReinterpretAs<vrrp_header>(data, dataLen);
389
6.42k
    }
390
391
    /// @struct SerializedFields
392
    /// Fields written by VrrpV2Layer's serializeLayer(), in addition to
393
    /// VrrpLayer::SerializedFields.
394
    struct SerializedFields : VrrpLayer::SerializedFields
395
    {
396
      /// @return All field descriptors for VrrpV2Layer
397
      static std::vector<FieldDescriptor> all()
398
0
      {
399
0
        auto result = VrrpLayer::SerializedFields::all();
400
0
        std::initializer_list<FieldDescriptor> extra{ AdvInt, AuthType };
401
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
402
0
        return result;
403
0
      }
404
405
      /// @brief Field descriptor for the advertisement interval (in seconds), written as a number.
406
      static const FieldDescriptor AdvInt;
407
408
      /// @brief Field descriptor for the authentication type, written as a string
409
      /// (see VrrpV2Layer::VrrpAuthType).
410
      static const FieldDescriptor AuthType;
411
    };
412
413
  protected:
414
    void serializeVrrpLayer(ObjectScope& serializer) const override;
415
  };
416
417
  /// @class VrrpV3Layer
418
  /// Represents VRRPv3 (Virtual Router Redundancy Protocol ver 3) layer. This class represents all the different
419
  /// messages of VRRP
420
  class VrrpV3Layer : public VrrpLayer
421
  {
422
  private:
423
    struct vrrpv3_rsvd_adv
424
    {
425
      uint16_t maxAdvInt;
426
    };
427
428
  public:
429
    /// A constructor that creates the layer from an existing packet raw data
430
    /// @param[in] data A pointer to the raw data
431
    /// @param[in] dataLen Size of the data in bytes
432
    /// @param[in] prevLayer A pointer to the previous layer
433
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
434
    /// @param[in] addressType The IP address type to set for this layer
435
    VrrpV3Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, IPAddress::AddressType addressType)
436
7.72k
        : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv3, addressType)
437
7.72k
    {}
438
439
    /// A constructor that allocates a new VRRPv3
440
    /// @param addressType The IP address type to set for this layer
441
    /// @param virtualRouterId Virtual router ID
442
    /// @param priority Priority
443
    /// @param maxAdvInt Max advertisement interval
444
    explicit VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority,
445
                         uint16_t maxAdvInt);
446
447
    /// A destructor for this layer (does nothing)
448
    ~VrrpV3Layer() override = default;
449
450
    /// @return The maximum advertisement interval in this message
451
    uint16_t getMaxAdvInt() const;
452
453
    /// Set the maximum advertisement interval value
454
    /// @param maxAdvInt Value to set
455
    void setMaxAdvInt(uint16_t maxAdvInt);
456
457
    // implement abstract methods
458
459
    /// Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum
460
    /// @return The checksum result
461
    uint16_t calculateChecksum() const override;
462
463
    /// A static method that validates the input data
464
    /// @param[in] data The pointer to the beginning of a byte stream of an VRRPv3 layer
465
    /// @param[in] dataLen The length of the byte stream
466
    /// @return True if the data is valid and can represent an VRRPv3 layer
467
    static bool isDataValid(uint8_t const* data, size_t dataLen)
468
3.07k
    {
469
3.07k
      return canReinterpretAs<vrrp_header>(data, dataLen);
470
3.07k
    }
471
472
    /// @struct SerializedFields
473
    /// Fields written by VrrpV3Layer's serializeLayer(), in addition to
474
    /// VrrpLayer::SerializedFields.
475
    struct SerializedFields : VrrpLayer::SerializedFields
476
    {
477
      /// @return All field descriptors for VrrpV3Layer
478
      static std::vector<FieldDescriptor> all()
479
0
      {
480
0
        auto result = VrrpLayer::SerializedFields::all();
481
0
        std::initializer_list<FieldDescriptor> extra{ MaxAdvInt };
482
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
483
0
        return result;
484
0
      }
485
486
      /// @brief Field descriptor for the maximum advertisement interval (in centiseconds), written as a number.
487
      static const FieldDescriptor MaxAdvInt;
488
    };
489
490
  protected:
491
    void serializeVrrpLayer(ObjectScope& serializer) const override;
492
  };
493
}  // namespace pcpp