Coverage Report

Created: 2025-07-12 07:37

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