Coverage Report

Created: 2026-09-01 08:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/VrrpLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleVrrpLayer
2
3
#include <SystemUtils.h>
4
#include "PacketUtils.h"
5
#include "Logger.h"
6
#include "EndianPortable.h"
7
#include "IPv4Layer.h"
8
#include "PayloadLayer.h"
9
#include "VrrpLayer.h"
10
11
namespace pcpp
12
{
13
14
  constexpr uint8_t VrrpPriorityStop = 0;       ///< priority to stop
15
  constexpr uint8_t VrrpPriorityDefault = 100;  ///< default priority
16
  constexpr uint8_t VrrpPriorityOwner = 255;    ///< priority of the IP owner
17
18
  constexpr uint8_t VrrpPacketFixedLength = 8;
19
  constexpr uint8_t VrrpPacketMaxIpAddressCount = 255;
20
21
  constexpr uint8_t VrrpVersion2 = 2;
22
  constexpr uint8_t VrrpVersion3 = 3;
23
24
  // -------- Class VrrpLayer -----------------
25
26
  VrrpLayer::VrrpLayer(ProtocolType subProtocol, uint8_t virtualRouterId, uint8_t priority)
27
0
  {
28
0
    allocData(VrrpPacketFixedLength);
29
0
    m_Protocol = subProtocol;
30
0
    m_AddressType = IPAddress::IPv4AddressType;
31
0
    auto vrrpHeader = getVrrpHeader();
32
0
    if (subProtocol == VRRPv2)
33
0
    {
34
0
      vrrpHeader->version = VrrpVersion2;
35
0
    }
36
0
    else if (subProtocol == VRRPv3)
37
0
    {
38
0
      vrrpHeader->version = VrrpVersion3;
39
0
    }
40
0
    vrrpHeader->type = static_cast<uint8_t>(VrrpType::VrrpType_Advertisement);
41
0
    setVirtualRouterID(virtualRouterId);
42
0
    setPriority(priority);
43
0
  }
44
45
  ProtocolType VrrpLayer::getVersionFromData(uint8_t* data, size_t dataLen)
46
10.8k
  {
47
10.8k
    if (!data || dataLen <= VrrpPacketFixedLength)
48
9
    {
49
9
      return UnknownProtocol;
50
9
    }
51
52
10.8k
    auto* vrrpPacketCommon = (vrrp_header*)data;
53
10.8k
    uint8_t version = vrrpPacketCommon->version;
54
10.8k
    switch (version)
55
10.8k
    {
56
3.30k
    case VrrpVersion2:
57
3.30k
      return VRRPv2;
58
7.07k
    case VrrpVersion3:
59
7.07k
      return VRRPv3;
60
459
    default:
61
459
      return UnknownProtocol;
62
10.8k
    }
63
10.8k
  }
64
65
  void VrrpLayer::computeCalculateFields()
66
2.24k
  {
67
    // calculate and fill the checksum to packet
68
2.24k
    calculateAndSetChecksum();
69
2.24k
  }
70
71
  uint8_t VrrpLayer::getIPAddressLen() const
72
29.5k
  {
73
29.5k
    if (getAddressType() == IPAddress::IPv4AddressType)
74
28.6k
    {
75
28.6k
      return 4;
76
28.6k
    }
77
78
846
    return 16;
79
29.5k
  }
80
81
  bool VrrpLayer::isChecksumCorrect() const
82
2.24k
  {
83
2.24k
    auto vrrpHeader = getVrrpHeader();
84
2.24k
    if (vrrpHeader == nullptr)
85
0
    {
86
0
      return false;
87
0
    }
88
89
2.24k
    return (calculateChecksum() == be16toh(vrrpHeader->checksum));
90
2.24k
  }
91
92
  VrrpLayer::VrrpPriority VrrpLayer::getPriorityAsEnum() const
93
2.24k
  {
94
2.24k
    switch (getVrrpHeader()->priority)
95
2.24k
    {
96
169
    case VrrpPriorityDefault:
97
169
      return VrrpLayer::VrrpPriority::Default;
98
99
678
    case VrrpPriorityStop:
100
678
      return VrrpLayer::VrrpPriority::Stop;
101
102
66
    case VrrpPriorityOwner:
103
66
      return VrrpLayer::VrrpPriority::Owner;
104
105
1.33k
    default:
106
1.33k
      return VrrpLayer::VrrpPriority::Other;
107
2.24k
    }
108
2.24k
  }
109
110
  std::string VrrpLayer::toString() const
111
4.48k
  {
112
4.48k
    return "VRRP v" + std::to_string(getVersion()) +
113
4.48k
           " Layer, virtual router ID: " + std::to_string(getVirtualRouterID()) +
114
4.48k
           ", IP address count: " + std::to_string(getIPAddressesCount());
115
4.48k
  }
116
117
  uint8_t VrrpLayer::getVersion() const
118
4.48k
  {
119
4.48k
    return getVrrpHeader()->version;
120
4.48k
  }
121
122
  VrrpLayer::VrrpType VrrpLayer::getType() const
123
2.24k
  {
124
2.24k
    if (getVrrpHeader()->type == VrrpType_Advertisement)
125
701
    {
126
701
      return VrrpType_Advertisement;
127
701
    }
128
129
1.54k
    return VrrpType_Unknown;
130
2.24k
  }
131
132
  uint8_t VrrpLayer::getVirtualRouterID() const
133
4.48k
  {
134
4.48k
    return getVrrpHeader()->vrId;
135
4.48k
  }
136
137
  void VrrpLayer::setVirtualRouterID(uint8_t virtualRouterID)
138
0
  {
139
0
    getVrrpHeader()->vrId = virtualRouterID;
140
0
  }
141
142
  uint8_t VrrpLayer::getPriority() const
143
2.24k
  {
144
2.24k
    return getVrrpHeader()->priority;
145
2.24k
  }
146
147
  void VrrpLayer::setPriority(uint8_t priority)
148
0
  {
149
0
    getVrrpHeader()->priority = priority;
150
0
  }
151
152
  uint16_t VrrpLayer::getChecksum() const
153
2.24k
  {
154
2.24k
    return be16toh(getVrrpHeader()->checksum);
155
2.24k
  }
156
157
  void VrrpLayer::calculateAndSetChecksum()
158
2.24k
  {
159
2.24k
    getVrrpHeader()->checksum = htobe16(calculateChecksum());
160
2.24k
  }
161
162
  uint8_t VrrpLayer::getIPAddressesCount() const
163
4.48k
  {
164
4.48k
    return getVrrpHeader()->ipAddrCount;
165
4.48k
  }
166
167
  std::vector<IPAddress> VrrpLayer::getIPAddresses() const
168
2.24k
  {
169
2.24k
    std::vector<IPAddress> ipAddressesVec;
170
2.24k
    auto ipAddressesPtr = getFirstIPAddressPtr();
171
29.5k
    while (ipAddressesPtr != nullptr)
172
27.2k
    {
173
27.2k
      IPAddress ipAddress = getIPAddressFromData(ipAddressesPtr);
174
27.2k
      ipAddressesVec.push_back(ipAddress);
175
27.2k
      ipAddressesPtr = getNextIPAddressPtr(ipAddressesPtr);
176
27.2k
    }
177
178
2.24k
    return ipAddressesVec;
179
2.24k
  }
180
181
  uint8_t* VrrpLayer::getFirstIPAddressPtr() const
182
2.24k
  {
183
2.24k
    size_t ipAddressLen = getIPAddressLen();
184
185
    // check if there are virtual IP address at all
186
2.24k
    if (getHeaderLen() <= VrrpPacketFixedLength + ipAddressLen)
187
806
    {
188
806
      return nullptr;
189
806
    }
190
191
1.43k
    return (m_Data + VrrpPacketFixedLength);
192
2.24k
  }
193
194
  uint8_t* VrrpLayer::getNextIPAddressPtr(uint8_t* ipAddressPtr) const
195
27.2k
  {
196
27.2k
    if (ipAddressPtr == nullptr)
197
0
    {
198
0
      return nullptr;
199
0
    }
200
201
27.2k
    size_t ipAddressLen = getIPAddressLen();
202
27.2k
    size_t nextOffset = static_cast<size_t>(ipAddressPtr - m_Data) + ipAddressLen;
203
204
    // The next virtual IP address must fit entirely inside the layer. Checking only that the current
205
    // address ends inside it leaves a trailing partial address reachable, which the caller then reads
206
    // in full and runs past the end of the buffer.
207
27.2k
    if (nextOffset + ipAddressLen > getHeaderLen())
208
1.43k
    {
209
1.43k
      return nullptr;
210
1.43k
    }
211
212
25.8k
    return (m_Data + nextOffset);
213
27.2k
  }
214
215
  bool VrrpLayer::addIPAddressesAt(const std::vector<IPAddress>& ipAddresses, int offset)
216
0
  {
217
0
    if (offset > (int)getHeaderLen())
218
0
    {
219
0
      PCPP_LOG_ERROR("Cannot add virtual IP address offset(" << offset << ") is out of layer bounds");
220
0
      return false;
221
0
    }
222
223
0
    for (auto ipAddress : ipAddresses)
224
0
    {
225
0
      if (!isIPAddressValid(ipAddress))
226
0
      {
227
0
        PCPP_LOG_ERROR("Cannot add virtual IP address, for IP address is invalid.");
228
0
        return false;
229
0
      }
230
0
    }
231
232
0
    if (getIPAddressesCount() + ipAddresses.size() > VrrpPacketMaxIpAddressCount)
233
0
    {
234
0
      PCPP_LOG_ERROR("Cannot add virtual IP address, for virtual IP address has already exceed maximum.");
235
0
      return false;
236
0
    }
237
238
0
    size_t ipAddrLen = getIPAddressLen();
239
0
    size_t ipAddressesLen = ipAddrLen * ipAddresses.size();
240
0
    if (ipAddressesLen == 0)
241
0
    {
242
0
      return true;
243
0
    }
244
245
0
    if (!extendLayer(offset, ipAddressesLen))
246
0
    {
247
0
      PCPP_LOG_ERROR("Cannot add virtual IP address, cannot extend layer");
248
0
      return false;
249
0
    }
250
251
0
    size_t ipAddrOffset = 0;
252
0
    uint8_t* newIpAddresses = getData() + offset;
253
0
    for (auto const& ipAddress : ipAddresses)
254
0
    {
255
0
      copyIPAddressToData(newIpAddresses + ipAddrOffset, ipAddress);
256
0
      ipAddrOffset += ipAddrLen;
257
0
    }
258
259
0
    getVrrpHeader()->ipAddrCount = getIPAddressesCount() + ipAddresses.size();
260
261
0
    return true;
262
0
  }
263
264
  bool VrrpLayer::addIPAddresses(const std::vector<IPAddress>& ipAddresses)
265
0
  {
266
0
    return addIPAddressesAt(ipAddresses, (int)getHeaderLen());
267
0
  }
268
269
  bool VrrpLayer::addIPAddress(const IPAddress& ipAddress)
270
0
  {
271
0
    std::vector<IPAddress> ipAddresses;
272
0
    ipAddresses.push_back(ipAddress);
273
274
0
    return addIPAddressesAt(ipAddresses, (int)getHeaderLen());
275
0
  }
276
277
  bool VrrpLayer::removeIPAddressAtIndex(int index)
278
0
  {
279
0
    int ipAddressCount = (int)getIPAddressesCount();
280
281
0
    if (index < 0 || index >= ipAddressCount)
282
0
    {
283
0
      PCPP_LOG_ERROR("Cannot remove virtual IP address, index " << index << " is out of bounds");
284
0
      return false;
285
0
    }
286
287
0
    size_t ipAddressLen = getIPAddressLen();
288
289
0
    size_t offset = VrrpPacketFixedLength;
290
0
    auto curIpAddressPtr = getFirstIPAddressPtr();
291
0
    for (int i = 0; i < index; i++)
292
0
    {
293
0
      if (curIpAddressPtr == nullptr)
294
0
      {
295
0
        PCPP_LOG_ERROR("Cannot remove virtual IP address at index "
296
0
                       << index << ", cannot find virtual IP address at index " << i);
297
0
        return false;
298
0
      }
299
300
0
      offset += ipAddressLen;
301
0
      curIpAddressPtr = getNextIPAddressPtr(curIpAddressPtr);
302
0
    }
303
304
0
    if (!shortenLayer((int)offset, ipAddressLen))
305
0
    {
306
0
      PCPP_LOG_ERROR("Cannot remove virtual IP address at index " << index << ", cannot shorted layer");
307
0
      return false;
308
0
    }
309
310
0
    getVrrpHeader()->ipAddrCount = ipAddressCount - 1;
311
312
0
    return true;
313
0
  }
314
315
  bool VrrpLayer::removeAllIPAddresses()
316
0
  {
317
0
    size_t offset = VrrpPacketFixedLength;
318
0
    size_t packetLen = getHeaderLen();
319
0
    if (packetLen <= offset)
320
0
    {
321
0
      return false;
322
0
    }
323
324
0
    if (!shortenLayer((int)offset, packetLen - offset))
325
0
    {
326
0
      PCPP_LOG_ERROR("Cannot remove all virtual IP address(es), cannot shorted layer");
327
0
      return false;
328
0
    }
329
330
0
    getVrrpHeader()->ipAddrCount = 0;
331
332
0
    return true;
333
0
  }
334
335
  void VrrpLayer::copyIPAddressToData(uint8_t* data, const IPAddress& ipAddress) const
336
0
  {
337
0
    size_t ipAddressLen = getIPAddressLen();
338
339
0
    if (ipAddress.isIPv4())
340
0
    {
341
0
      memcpy(data, ipAddress.getIPv4().toBytes(), ipAddressLen);
342
0
    }
343
0
    else if (ipAddress.isIPv6())
344
0
    {
345
0
      memcpy(data, ipAddress.getIPv6().toBytes(), ipAddressLen);
346
0
    }
347
0
  }
348
349
  IPAddress VrrpLayer::getIPAddressFromData(uint8_t* data) const
350
27.2k
  {
351
27.2k
    if (getAddressType() == IPAddress::IPv4AddressType)
352
27.2k
    {
353
27.2k
      return IPv4Address(*reinterpret_cast<const uint32_t*>(data));
354
27.2k
    }
355
356
25
    return IPv6Address(data);
357
27.2k
  }
358
359
  bool VrrpLayer::isIPAddressValid(IPAddress& ipAddress) const
360
0
  {
361
0
    if (ipAddress.isIPv6() && (getProtocol() != VRRPv3))
362
0
    {
363
0
      PCPP_LOG_ERROR("Only VRRPv3 support IPv6 virtual address");
364
0
      return false;
365
0
    }
366
0
    if (ipAddress.getType() != getAddressType())
367
0
    {
368
0
      PCPP_LOG_ERROR("IP address version is not equal to layer's");
369
0
      return false;
370
0
    }
371
372
0
    return true;
373
0
  }
374
375
  IPAddress::AddressType VrrpLayer::getAddressType() const
376
59.7k
  {
377
59.7k
    return m_AddressType;
378
59.7k
  }
379
380
  void VrrpLayer::setAddressType(IPAddress::AddressType addressType)
381
0
  {
382
0
    m_AddressType = addressType;
383
0
  }
384
385
  // -------- Class Vrrpv2Layer -----------------
386
387
  VrrpV2Layer::VrrpV2Layer(uint8_t virtualRouterId, uint8_t priority, uint8_t advInt, uint8_t authType)
388
0
      : VrrpLayer(VRRPv2, virtualRouterId, priority)
389
0
  {
390
0
    setAdvInt(advInt);
391
0
    setAuthType(authType);
392
0
  }
393
394
  VrrpV2Layer::VrrpAuthType VrrpV2Layer::getAuthTypeAsEnum() const
395
802
  {
396
802
    auto authType = getAuthType();
397
802
    if (authType > 3)
398
717
    {
399
717
      return VrrpAuthType::Other;
400
717
    }
401
402
85
    return static_cast<VrrpAuthType>(authType);
403
802
  }
404
405
  uint8_t VrrpV2Layer::getAdvInt() const
406
802
  {
407
802
    uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt;
408
802
    auto authAdvIntPtr = reinterpret_cast<vrrpv2_auth_adv*>(&authAdvInt);
409
802
    return authAdvIntPtr->advInt;
410
802
  }
411
412
  void VrrpV2Layer::setAdvInt(uint8_t advInt)
413
0
  {
414
0
    auto authAdvIntPtr = reinterpret_cast<vrrpv2_auth_adv*>(&getVrrpHeader()->authTypeAdvInt);
415
0
    authAdvIntPtr->advInt = advInt;
416
0
  }
417
418
  uint8_t VrrpV2Layer::getAuthType() const
419
802
  {
420
802
    uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt;
421
802
    auto* authAdvIntPtr = reinterpret_cast<vrrpv2_auth_adv*>(&authAdvInt);
422
802
    return authAdvIntPtr->authType;
423
802
  }
424
425
  void VrrpV2Layer::setAuthType(uint8_t authType)
426
0
  {
427
0
    auto authAdvIntPtr = reinterpret_cast<vrrpv2_auth_adv*>(&getVrrpHeader()->authTypeAdvInt);
428
0
    authAdvIntPtr->authType = authType;
429
0
  }
430
431
  uint16_t VrrpV2Layer::calculateChecksum() const
432
1.60k
  {
433
1.60k
    if ((getData() == nullptr) || (getDataLen() == 0))
434
0
    {
435
0
      return 0;
436
0
    }
437
438
1.60k
    auto vrrpHeader = getVrrpHeader();
439
1.60k
    ScalarBuffer<uint16_t> buffer = {};
440
1.60k
    buffer.buffer = reinterpret_cast<uint16_t*>(vrrpHeader);
441
1.60k
    buffer.len = getHeaderLen();
442
443
1.60k
    uint16_t currChecksumValue = vrrpHeader->checksum;
444
1.60k
    vrrpHeader->checksum = 0;
445
1.60k
    uint16_t checksum = computeChecksum(&buffer, 1);
446
1.60k
    vrrpHeader->checksum = currChecksumValue;
447
448
1.60k
    return checksum;
449
1.60k
  }
450
451
  // -------- Class Vrrpv3Layer -----------------
452
453
  VrrpV3Layer::VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority,
454
                           uint16_t maxAdvInt)
455
0
      : VrrpLayer(VRRPv3, virtualRouterId, priority)
456
0
  {
457
0
    setAddressType(addressType);
458
0
    setMaxAdvInt(maxAdvInt);
459
0
  }
460
461
  uint16_t VrrpV3Layer::getMaxAdvInt() const
462
1.44k
  {
463
1.44k
    uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt;
464
1.44k
    auto rsvdAdv = reinterpret_cast<vrrpv3_rsvd_adv*>(&authAdvInt);
465
1.44k
    return be16toh(rsvdAdv->maxAdvInt);
466
1.44k
  }
467
468
  void VrrpV3Layer::setMaxAdvInt(uint16_t maxAdvInt)
469
0
  {
470
0
    if (maxAdvInt > 0xfff)
471
0
    {
472
0
      throw std::invalid_argument("maxAdvInt must not exceed 12 bits length");
473
0
    }
474
0
    auto rsvdAdv = reinterpret_cast<vrrpv3_rsvd_adv*>(&getVrrpHeader()->authTypeAdvInt);
475
0
    rsvdAdv->maxAdvInt = htobe16(maxAdvInt);
476
0
  }
477
478
  uint16_t VrrpV3Layer::calculateChecksum() const
479
2.88k
  {
480
2.88k
    auto* ipLayer = getAttachedPacket()->getLayerOfType<pcpp::IPLayer>();
481
2.88k
    if (ipLayer == nullptr)
482
0
    {
483
0
      PCPP_LOG_ERROR("Calculate checksum failed, for can not get IPLayer" << "");
484
0
      return 0;
485
0
    }
486
487
2.88k
    auto vrrpHeader = getVrrpHeader();
488
2.88k
    uint16_t currChecksumValue = vrrpHeader->checksum;
489
2.88k
    vrrpHeader->checksum = 0;
490
491
2.88k
    pcpp::IPAddress srcIPAddr = ipLayer->getSrcIPAddress();
492
2.88k
    pcpp::IPAddress dstIPAddr = ipLayer->getDstIPAddress();
493
2.88k
    uint16_t checksum;
494
2.88k
    if (getAddressType() == IPAddress::IPv4AddressType)
495
1.24k
    {
496
1.24k
      checksum = computePseudoHdrChecksum((uint8_t*)vrrpHeader, getDataLen(), IPAddress::IPv4AddressType,
497
1.24k
                                          PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr);
498
1.24k
    }
499
1.64k
    else
500
1.64k
    {
501
1.64k
      checksum = computePseudoHdrChecksum((uint8_t*)vrrpHeader, getDataLen(), IPAddress::IPv6AddressType,
502
1.64k
                                          PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr);
503
1.64k
    }
504
505
2.88k
    vrrpHeader->checksum = currChecksumValue;
506
507
2.88k
    return checksum;
508
2.88k
  }
509
}  // namespace pcpp