Coverage Report

Created: 2024-02-25 06:29

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