Coverage Report

Created: 2026-01-09 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/BgpLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleBgpLayer
2
3
#include "Logger.h"
4
#include "BgpLayer.h"
5
#include "Packet.h"
6
#include "EndianPortable.h"
7
#include "GeneralUtils.h"
8
9
namespace pcpp
10
{
11
  // ~~~~~~~~
12
  // BgpLayer
13
  // ~~~~~~~~
14
15
  size_t BgpLayer::getHeaderLen() const
16
0
  {
17
0
    if (m_DataLen < sizeof(bgp_common_header))
18
0
    {
19
0
      return m_DataLen;
20
0
    }
21
22
0
    uint16_t messageLen = be16toh(getBasicHeader()->length);
23
0
    if (m_DataLen < messageLen)
24
0
    {
25
0
      return m_DataLen;
26
0
    }
27
28
0
    return (size_t)messageLen;
29
0
  }
30
31
  BgpLayer* BgpLayer::parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
32
0
  {
33
0
    if (data == nullptr || dataLen < sizeof(bgp_common_header))
34
0
      return nullptr;
35
36
0
    auto* bgpHeader = reinterpret_cast<bgp_common_header*>(data);
37
38
    // illegal header data - length is too small
39
0
    uint16_t messageLen = be16toh(bgpHeader->length);
40
0
    if (dataLen < messageLen || messageLen < static_cast<uint16_t>(sizeof(bgp_common_header)))
41
0
      return nullptr;
42
43
0
    switch (bgpHeader->messageType)
44
0
    {
45
0
    case 1:  // OPEN
46
0
      return new BgpOpenMessageLayer(data, dataLen, prevLayer, packet);
47
0
    case 2:  // UPDATE
48
0
      return BgpUpdateMessageLayer::isDataValid(data, dataLen)
49
0
                 ? new BgpUpdateMessageLayer(data, dataLen, prevLayer, packet)
50
0
                 : nullptr;
51
0
    case 3:  // NOTIFICATION
52
0
      return new BgpNotificationMessageLayer(data, dataLen, prevLayer, packet);
53
0
    case 4:  // KEEPALIVE
54
0
      return new BgpKeepaliveMessageLayer(data, dataLen, prevLayer, packet);
55
0
    case 5:  // ROUTE-REFRESH
56
0
      return new BgpRouteRefreshMessageLayer(data, dataLen, prevLayer, packet);
57
0
    default:
58
0
      return nullptr;
59
0
    }
60
0
  }
61
62
  std::string BgpLayer::getMessageTypeAsString() const
63
0
  {
64
0
    switch (getBgpMessageType())
65
0
    {
66
0
    case BgpLayer::Open:
67
0
      return "OPEN";
68
0
    case BgpLayer::Update:
69
0
      return "UPDATE";
70
0
    case BgpLayer::Notification:
71
0
      return "NOTIFICATION";
72
0
    case BgpLayer::Keepalive:
73
0
      return "KEEPALIVE";
74
0
    case BgpLayer::RouteRefresh:
75
0
      return "ROUTE-REFRESH";
76
0
    default:
77
0
      return "Unknown";
78
0
    }
79
0
  }
80
81
  void BgpLayer::parseNextLayer()
82
0
  {
83
0
    size_t headerLen = getHeaderLen();
84
0
    if (m_DataLen <= headerLen || headerLen == 0)
85
0
      return;
86
87
0
    uint8_t* payload = m_Data + headerLen;
88
0
    size_t payloadLen = m_DataLen - headerLen;
89
90
0
    m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet);
91
0
  }
92
93
  std::string BgpLayer::toString() const
94
0
  {
95
0
    return "BGP Layer, " + getMessageTypeAsString() + " message";
96
0
  }
97
98
  void BgpLayer::computeCalculateFields()
99
0
  {
100
0
    bgp_common_header* bgpHeader = getBasicHeader();
101
0
    memset(bgpHeader->marker, 0xff, 16 * sizeof(uint8_t));
102
0
    bgpHeader->messageType = (uint8_t)getBgpMessageType();
103
0
    bgpHeader->length = htobe16(getHeaderLen());
104
0
  }
105
106
  void BgpLayer::setBgpFields(size_t messageLen)
107
0
  {
108
0
    bgp_common_header* bgpHdr = getBasicHeader();
109
0
    memset(bgpHdr->marker, 0xff, 16 * sizeof(uint8_t));
110
0
    bgpHdr->messageType = (uint8_t)getBgpMessageType();
111
0
    if (messageLen != 0)
112
0
    {
113
0
      bgpHdr->length = htobe16((uint16_t)messageLen);
114
0
    }
115
0
    else
116
0
    {
117
0
      bgpHdr->length = m_DataLen;
118
0
    }
119
0
  }
120
121
  bool BgpLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend)
122
0
  {
123
0
    if (m_Packet != nullptr)
124
0
    {
125
0
      int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
126
0
      const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
127
128
0
      if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) > static_cast<ptrdiff_t>(rawPacketLen))
129
0
      {
130
0
        PCPP_LOG_ERROR("Requested offset is larger than total packet length");
131
0
        return false;
132
0
      }
133
134
0
      if (m_NextLayer != nullptr && static_cast<ptrdiff_t>(offsetInLayer) > m_NextLayer->getData() - m_Data)
135
0
      {
136
0
        PCPP_LOG_ERROR("Requested offset exceeds current layer's boundary");
137
0
        return false;
138
0
      }
139
0
    }
140
141
0
    return Layer::extendLayer(offsetInLayer, numOfBytesToExtend);
142
0
  }
143
144
  bool BgpLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten)
145
0
  {
146
0
    if (m_Packet != nullptr)
147
0
    {
148
0
      int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
149
0
      const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
150
151
0
      if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) +
152
0
              static_cast<ptrdiff_t>(numOfBytesToShorten) >
153
0
          static_cast<ptrdiff_t>(rawPacketLen))
154
0
      {
155
0
        PCPP_LOG_ERROR("Requested number of bytes to shorten is larger than total packet length");
156
0
        return false;
157
0
      }
158
159
0
      if (m_NextLayer != nullptr &&
160
0
          static_cast<ptrdiff_t>(offsetInLayer) + static_cast<ptrdiff_t>(numOfBytesToShorten) >
161
0
              m_NextLayer->getData() - m_Data)
162
0
      {
163
0
        PCPP_LOG_ERROR("Requested number of bytes to shorten exceeds current layer's boundary");
164
0
        return false;
165
0
      }
166
0
    }
167
168
0
    return Layer::shortenLayer(offsetInLayer, numOfBytesToShorten);
169
0
  }
170
171
  // ~~~~~~~~~~~~~~~~~~~~
172
  // BgpOpenMessageLayer
173
  // ~~~~~~~~~~~~~~~~~~~~
174
175
  BgpOpenMessageLayer::optional_parameter::optional_parameter(uint8_t typeVal, const std::string& valueAsHexString)
176
0
  {
177
0
    type = typeVal;
178
0
    length = hexStringToByteArray(valueAsHexString, value, 32);
179
0
  }
180
181
  BgpOpenMessageLayer::BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId,
182
                                           const std::vector<optional_parameter>& optionalParams)
183
0
  {
184
0
    uint8_t optionalParamsData[1500];
185
0
    size_t optionalParamsDataLen = optionalParamsToByteArray(optionalParams, optionalParamsData, 1500);
186
187
0
    const size_t headerLen = sizeof(bgp_open_message) + optionalParamsDataLen;
188
0
    m_DataLen = headerLen;
189
0
    m_Data = new uint8_t[headerLen];
190
0
    memset(m_Data, 0, headerLen);
191
0
    setBgpFields(headerLen);
192
193
0
    bgp_open_message* msgHdr = getOpenMsgHeader();
194
0
    msgHdr->version = 4;
195
0
    msgHdr->myAutonomousSystem = htobe16(myAutonomousSystem);
196
0
    msgHdr->holdTime = htobe16(holdTime);
197
0
    msgHdr->bgpId = bgpId.toInt();
198
0
    msgHdr->optionalParameterLength = optionalParamsDataLen;
199
0
    if (optionalParamsDataLen > 0)
200
0
    {
201
0
      memcpy(m_Data + sizeof(bgp_open_message), optionalParamsData, optionalParamsDataLen);
202
0
    }
203
204
0
    m_Protocol = BGP;
205
0
  }
206
207
  size_t BgpOpenMessageLayer::optionalParamsToByteArray(const std::vector<optional_parameter>& optionalParams,
208
                                                        uint8_t* resultByteArr, size_t maxByteArrSize)
209
0
  {
210
0
    if (resultByteArr == nullptr || maxByteArrSize == 0)
211
0
    {
212
0
      return 0;
213
0
    }
214
215
0
    size_t dataLen = 0;
216
217
0
    for (const auto& param : optionalParams)
218
0
    {
219
0
      if (param.length > 32)
220
0
      {
221
0
        PCPP_LOG_ERROR("Illegal optional parameter length " << (int)param.length
222
0
                                                            << ", must be 32 bytes or less");
223
0
        break;  // illegal value
224
0
      }
225
226
0
      size_t curDataSize = 2 * sizeof(uint8_t) + (size_t)param.length;
227
228
0
      if (dataLen + curDataSize > maxByteArrSize)
229
0
      {
230
0
        break;
231
0
      }
232
233
0
      resultByteArr[0] = param.type;
234
0
      resultByteArr[1] = param.length;
235
0
      if (param.length > 0)
236
0
      {
237
0
        memcpy(resultByteArr + 2 * sizeof(uint8_t), param.value, param.length);
238
0
      }
239
240
0
      dataLen += curDataSize;
241
0
      resultByteArr += curDataSize;
242
0
    }
243
244
0
    return dataLen;
245
0
  }
246
247
  void BgpOpenMessageLayer::setBgpId(const IPv4Address& newBgpId)
248
0
  {
249
0
    bgp_open_message* msgHdr = getOpenMsgHeader();
250
0
    if (msgHdr == nullptr)
251
0
    {
252
0
      return;
253
0
    }
254
255
0
    msgHdr->bgpId = newBgpId.toInt();
256
0
  }
257
258
  void BgpOpenMessageLayer::getOptionalParameters(std::vector<optional_parameter>& optionalParameters)
259
0
  {
260
0
    bgp_open_message* msgHdr = getOpenMsgHeader();
261
0
    if (msgHdr == nullptr || msgHdr->optionalParameterLength == 0)
262
0
    {
263
0
      return;
264
0
    }
265
266
0
    size_t optionalParamsLen = (size_t)be16toh(msgHdr->optionalParameterLength);
267
268
0
    if (optionalParamsLen > getHeaderLen() - sizeof(bgp_open_message))
269
0
    {
270
0
      optionalParamsLen = getHeaderLen() - sizeof(bgp_open_message);
271
0
    }
272
273
0
    uint8_t* dataPtr = m_Data + sizeof(bgp_open_message);
274
0
    size_t byteCount = 0;
275
0
    while (byteCount < optionalParamsLen)
276
0
    {
277
0
      optional_parameter op;
278
0
      op.type = dataPtr[0];
279
0
      op.length = dataPtr[1];
280
281
0
      if (op.length > optionalParamsLen - byteCount)
282
0
      {
283
0
        PCPP_LOG_ERROR("Optional parameter length is out of bounds: " << (int)op.length);
284
0
        break;
285
0
      }
286
287
0
      if (op.length > 0)
288
0
      {
289
0
        memcpy(op.value, dataPtr + 2 * sizeof(uint8_t), (op.length > 32 ? 32 : op.length));
290
0
      }
291
292
0
      optionalParameters.push_back(op);
293
0
      size_t totalLen = 2 + (size_t)op.length;
294
0
      byteCount += totalLen;
295
0
      dataPtr += totalLen;
296
0
    }
297
0
  }
298
299
  size_t BgpOpenMessageLayer::getOptionalParametersLength()
300
0
  {
301
0
    bgp_open_message* msgHdr = getOpenMsgHeader();
302
0
    if (msgHdr != nullptr)
303
0
    {
304
0
      return (size_t)(msgHdr->optionalParameterLength);
305
0
    }
306
307
0
    return 0;
308
0
  }
309
310
  bool BgpOpenMessageLayer::setOptionalParameters(const std::vector<optional_parameter>& optionalParameters)
311
0
  {
312
0
    uint8_t newOptionalParamsData[1500];
313
0
    size_t newOptionalParamsDataLen = optionalParamsToByteArray(optionalParameters, newOptionalParamsData, 1500);
314
0
    size_t curOptionalParamsDataLen = getOptionalParametersLength();
315
0
    int offsetInLayer = sizeof(bgp_open_message);
316
317
0
    if (newOptionalParamsDataLen > curOptionalParamsDataLen)
318
0
    {
319
0
      size_t numOfBytesToExtend = newOptionalParamsDataLen - curOptionalParamsDataLen;
320
321
0
      if (!extendLayer(offsetInLayer, numOfBytesToExtend))
322
0
      {
323
0
        PCPP_LOG_ERROR("Couldn't extend BGP open layer to include the additional optional parameters");
324
0
        return false;
325
0
      }
326
0
    }
327
0
    else if (newOptionalParamsDataLen < curOptionalParamsDataLen)
328
0
    {
329
0
      size_t numOfBytesToShorten = curOptionalParamsDataLen - newOptionalParamsDataLen;
330
331
0
      if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
332
0
      {
333
0
        PCPP_LOG_ERROR("Couldn't shorten BGP open layer to set the right size of the optional parameters data");
334
0
        return false;
335
0
      }
336
0
    }
337
338
0
    if (newOptionalParamsDataLen > 0)
339
0
    {
340
0
      memcpy(m_Data + offsetInLayer, newOptionalParamsData, newOptionalParamsDataLen);
341
0
    }
342
343
0
    getOpenMsgHeader()->optionalParameterLength = (uint8_t)newOptionalParamsDataLen;
344
0
    getOpenMsgHeader()->length = htobe16(sizeof(bgp_open_message) + newOptionalParamsDataLen);
345
346
0
    return true;
347
0
  }
348
349
  bool BgpOpenMessageLayer::clearOptionalParameters()
350
0
  {
351
0
    return setOptionalParameters(std::vector<optional_parameter>());
352
0
  }
353
354
  // ~~~~~~~~~~~~~~~~~~~~~
355
  // BgpUpdateMessageLayer
356
  // ~~~~~~~~~~~~~~~~~~~~~
357
358
  BgpUpdateMessageLayer::path_attribute::path_attribute(uint8_t flagsVal, uint8_t typeVal,
359
                                                        const std::string& dataAsHexString)
360
0
  {
361
0
    flags = flagsVal;
362
0
    type = typeVal;
363
0
    length = hexStringToByteArray(dataAsHexString, data, 32);
364
0
  }
365
366
  BgpUpdateMessageLayer::BgpUpdateMessageLayer(const std::vector<prefix_and_ip>& withdrawnRoutes,
367
                                               const std::vector<path_attribute>& pathAttributes,
368
                                               const std::vector<prefix_and_ip>& nlri)
369
0
  {
370
0
    uint8_t withdrawnRoutesData[1500];
371
0
    uint8_t pathAttributesData[1500];
372
0
    uint8_t nlriData[1500];
373
0
    size_t withdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, withdrawnRoutesData, 1500);
374
0
    size_t pathAttributesDataLen = pathAttributesToByteArray(pathAttributes, pathAttributesData, 1500);
375
0
    size_t nlriDataLen = prefixAndIPDataToByteArray(nlri, nlriData, 1500);
376
377
0
    size_t headerLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrawnRoutesDataLen +
378
0
                       pathAttributesDataLen + nlriDataLen;
379
0
    m_DataLen = headerLen;
380
0
    m_Data = new uint8_t[headerLen];
381
0
    memset(m_Data, 0, headerLen);
382
0
    setBgpFields(headerLen);
383
384
0
    uint8_t* dataPtr = m_Data + sizeof(bgp_common_header);
385
386
    // copy withdrawn routes data
387
0
    uint16_t withdrawnRoutesDataLenBE = htobe16(withdrawnRoutesDataLen);
388
0
    memcpy(dataPtr, &withdrawnRoutesDataLenBE, sizeof(uint16_t));
389
0
    dataPtr += sizeof(uint16_t);
390
0
    if (withdrawnRoutesDataLen > 0)
391
0
    {
392
0
      memcpy(dataPtr, withdrawnRoutesData, withdrawnRoutesDataLen);
393
0
      dataPtr += withdrawnRoutesDataLen;
394
0
    }
395
396
    // copy path attributes data
397
0
    uint16_t pathAttributesDataLenBE = htobe16(pathAttributesDataLen);
398
0
    memcpy(dataPtr, &pathAttributesDataLenBE, sizeof(uint16_t));
399
0
    dataPtr += sizeof(uint16_t);
400
0
    if (pathAttributesDataLen > 0)
401
0
    {
402
0
      memcpy(dataPtr, pathAttributesData, pathAttributesDataLen);
403
0
      dataPtr += pathAttributesDataLen;
404
0
    }
405
406
    // copy nlri data
407
0
    if (nlriDataLen > 0)
408
0
    {
409
0
      memcpy(dataPtr, nlriData, nlriDataLen);
410
0
    }
411
412
0
    m_Protocol = BGP;
413
0
  }
414
415
  void BgpUpdateMessageLayer::parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen,
416
                                                   std::vector<prefix_and_ip>& result)
417
0
  {
418
0
    size_t byteCount = 0;
419
0
    while (byteCount < dataLen)
420
0
    {
421
0
      prefix_and_ip wr;
422
0
      wr.prefix = dataPtr[0];
423
0
      size_t curByteCount = 1;
424
0
      if (wr.prefix == 32)
425
0
      {
426
0
        uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], dataPtr[4] };
427
0
        wr.ipAddr = IPv4Address(octets);
428
0
        curByteCount += 4;
429
0
      }
430
0
      else if (wr.prefix == 24)
431
0
      {
432
0
        uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], 0 };
433
0
        wr.ipAddr = IPv4Address(octets);
434
0
        curByteCount += 3;
435
0
      }
436
0
      else if (wr.prefix == 16)
437
0
      {
438
0
        uint8_t octets[4] = { dataPtr[1], dataPtr[2], 0, 0 };
439
0
        wr.ipAddr = IPv4Address(octets);
440
0
        curByteCount += 2;
441
0
      }
442
0
      else if (wr.prefix == 8)
443
0
      {
444
0
        uint8_t octets[4] = { dataPtr[1], 0, 0, 0 };
445
0
        wr.ipAddr = IPv4Address(octets);
446
0
        curByteCount += 1;
447
0
      }
448
0
      else
449
0
      {
450
0
        PCPP_LOG_DEBUG("Illegal prefix value " << (int)wr.prefix);
451
0
        break;  // illegal value
452
0
      }
453
454
0
      result.push_back(wr);
455
0
      dataPtr += curByteCount;
456
0
      byteCount += curByteCount;
457
0
    }
458
0
  }
459
460
  size_t BgpUpdateMessageLayer::prefixAndIPDataToByteArray(const std::vector<prefix_and_ip>& prefixAndIpData,
461
                                                           uint8_t* resultByteArr, size_t maxByteArrSize)
462
0
  {
463
0
    if (resultByteArr == nullptr || maxByteArrSize == 0)
464
0
    {
465
0
      return 0;
466
0
    }
467
468
0
    size_t dataLen = 0;
469
470
0
    for (const auto& prefixAndIp : prefixAndIpData)
471
0
    {
472
0
      uint8_t curData[5];
473
0
      curData[0] = prefixAndIp.prefix;
474
0
      size_t curDataSize = 1;
475
0
      const uint8_t* octets = prefixAndIp.ipAddr.toBytes();
476
0
      if (prefixAndIp.prefix == 32)
477
0
      {
478
0
        curDataSize += 4;
479
0
        curData[1] = octets[0];
480
0
        curData[2] = octets[1];
481
0
        curData[3] = octets[2];
482
0
        curData[4] = octets[3];
483
0
      }
484
0
      else if (prefixAndIp.prefix == 24)
485
0
      {
486
0
        curDataSize += 3;
487
0
        curData[1] = octets[0];
488
0
        curData[2] = octets[1];
489
0
        curData[3] = octets[2];
490
0
      }
491
0
      else if (prefixAndIp.prefix == 16)
492
0
      {
493
0
        curDataSize += 2;
494
0
        curData[1] = octets[0];
495
0
        curData[2] = octets[1];
496
0
      }
497
0
      else if (prefixAndIp.prefix == 8)
498
0
      {
499
0
        curDataSize += 1;
500
0
        curData[1] = octets[0];
501
0
      }
502
0
      else
503
0
      {
504
0
        PCPP_LOG_ERROR("Illegal prefix value " << (int)prefixAndIp.prefix);
505
0
        break;  // illegal value
506
0
      }
507
508
0
      if (dataLen + curDataSize > maxByteArrSize)
509
0
      {
510
0
        break;
511
0
      }
512
513
0
      dataLen += curDataSize;
514
515
0
      memcpy(resultByteArr, curData, curDataSize);
516
0
      resultByteArr += curDataSize;
517
0
    }
518
519
0
    return dataLen;
520
0
  }
521
522
  size_t BgpUpdateMessageLayer::pathAttributesToByteArray(const std::vector<path_attribute>& pathAttributes,
523
                                                          uint8_t* resultByteArr, size_t maxByteArrSize)
524
0
  {
525
0
    if (resultByteArr == nullptr || maxByteArrSize == 0)
526
0
    {
527
0
      return 0;
528
0
    }
529
530
0
    size_t dataLen = 0;
531
532
0
    for (const auto& attribute : pathAttributes)
533
0
    {
534
0
      if (attribute.length > 32)
535
0
      {
536
0
        PCPP_LOG_ERROR("Illegal path attribute length " << (int)attribute.length);
537
0
        break;  // illegal value
538
0
      }
539
540
0
      size_t curDataSize = 3 * sizeof(uint8_t) + (size_t)attribute.length;
541
542
0
      if (dataLen + curDataSize > maxByteArrSize)
543
0
      {
544
0
        break;
545
0
      }
546
547
0
      resultByteArr[0] = attribute.flags;
548
0
      resultByteArr[1] = attribute.type;
549
0
      resultByteArr[2] = attribute.length;
550
0
      if (attribute.length > 0)
551
0
      {
552
0
        memcpy(resultByteArr + 3 * sizeof(uint8_t), attribute.data, attribute.length);
553
0
      }
554
555
0
      dataLen += curDataSize;
556
0
      resultByteArr += curDataSize;
557
0
    }
558
559
0
    return dataLen;
560
0
  }
561
562
  size_t BgpUpdateMessageLayer::getWithdrawnRoutesLength() const
563
0
  {
564
0
    size_t headerLen = getHeaderLen();
565
0
    size_t minLen = sizeof(bgp_common_header) + sizeof(uint16_t);
566
0
    if (headerLen >= minLen)
567
0
    {
568
0
      uint16_t res = be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header)));
569
0
      if ((size_t)res > headerLen - minLen)
570
0
      {
571
0
        return headerLen - minLen;
572
0
      }
573
574
0
      return (size_t)res;
575
0
    }
576
577
0
    return 0;
578
0
  }
579
580
  void BgpUpdateMessageLayer::getWithdrawnRoutes(std::vector<prefix_and_ip>& withdrawnRoutes)
581
0
  {
582
0
    size_t withdrawnRouteLen = getWithdrawnRoutesLength();
583
0
    if (withdrawnRouteLen == 0)
584
0
    {
585
0
      return;
586
0
    }
587
588
0
    uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + sizeof(uint16_t);
589
0
    parsePrefixAndIPData(dataPtr, withdrawnRouteLen, withdrawnRoutes);
590
0
  }
591
592
  size_t BgpUpdateMessageLayer::getPathAttributesLength() const
593
0
  {
594
0
    size_t headerLen = getHeaderLen();
595
0
    size_t minLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t);
596
0
    if (headerLen >= minLen)
597
0
    {
598
0
      size_t withdrawnRouteLen = getWithdrawnRoutesLength();
599
      // Ensure the memory access is within bounds
600
0
      if (sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen + sizeof(uint16_t) > headerLen)
601
0
      {
602
0
        return 0;  // Invalid access, return 0
603
0
      }
604
0
      uint16_t res =
605
0
          be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen));
606
0
      if ((size_t)res > headerLen - minLen - withdrawnRouteLen)
607
0
      {
608
0
        return headerLen - minLen - withdrawnRouteLen;
609
0
      }
610
611
0
      return (size_t)res;
612
0
    }
613
614
0
    return 0;
615
0
  }
616
617
  bool BgpUpdateMessageLayer::setWithdrawnRoutes(const std::vector<prefix_and_ip>& withdrawnRoutes)
618
0
  {
619
0
    uint8_t newWithdrawnRoutesData[1500];
620
0
    size_t newWithdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, newWithdrawnRoutesData, 1500);
621
0
    size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
622
0
    int offsetInLayer = sizeof(bgp_common_header) + sizeof(uint16_t);
623
624
0
    if (newWithdrawnRoutesDataLen > curWithdrawnRoutesDataLen)
625
0
    {
626
0
      size_t numOfBytesToExtend = newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen;
627
628
0
      if (!extendLayer(offsetInLayer, numOfBytesToExtend))
629
0
      {
630
0
        PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional withdrawn routes");
631
0
        return false;
632
0
      }
633
0
    }
634
0
    else if (newWithdrawnRoutesDataLen < curWithdrawnRoutesDataLen)
635
0
    {
636
0
      size_t numOfBytesToShorten = curWithdrawnRoutesDataLen - newWithdrawnRoutesDataLen;
637
638
0
      if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
639
0
      {
640
0
        PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the withdrawn routes data");
641
0
        return false;
642
0
      }
643
0
    }
644
645
0
    if (newWithdrawnRoutesDataLen > 0)
646
0
    {
647
0
      memcpy(m_Data + offsetInLayer, newWithdrawnRoutesData, newWithdrawnRoutesDataLen);
648
0
    }
649
650
0
    getBasicHeader()->length =
651
0
        htobe16(be16toh(getBasicHeader()->length) + newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen);
652
653
0
    uint16_t newWithdrawnRoutesDataLenBE = htobe16(newWithdrawnRoutesDataLen);
654
0
    memcpy(m_Data + sizeof(bgp_common_header), &newWithdrawnRoutesDataLenBE, sizeof(uint16_t));
655
656
0
    return true;
657
0
  }
658
659
  bool BgpUpdateMessageLayer::clearWithdrawnRoutes()
660
0
  {
661
0
    return setWithdrawnRoutes(std::vector<prefix_and_ip>());
662
0
  }
663
664
  void BgpUpdateMessageLayer::getPathAttributes(std::vector<path_attribute>& pathAttributes)
665
0
  {
666
0
    size_t pathAttrLen = getPathAttributesLength();
667
0
    if (pathAttrLen == 0)
668
0
    {
669
0
      return;
670
0
    }
671
672
0
    uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + getWithdrawnRoutesLength();
673
0
    size_t byteCount = 0;
674
0
    while (byteCount < pathAttrLen)
675
0
    {
676
0
      path_attribute pa;
677
0
      pa.flags = dataPtr[0];
678
0
      pa.type = dataPtr[1];
679
0
      pa.length = dataPtr[2];
680
0
      size_t curByteCount = 3 + pa.length;
681
0
      if (pa.length > 0)
682
0
      {
683
0
        size_t dataLenToCopy = (pa.length <= 32 ? pa.length : 32);
684
0
        memcpy(pa.data, dataPtr + 3, dataLenToCopy);
685
0
      }
686
687
0
      pathAttributes.push_back(pa);
688
0
      dataPtr += curByteCount;
689
0
      byteCount += curByteCount;
690
0
    }
691
0
  }
692
693
  bool BgpUpdateMessageLayer::setPathAttributes(const std::vector<path_attribute>& pathAttributes)
694
0
  {
695
0
    uint8_t newPathAttributesData[1500];
696
0
    size_t newPathAttributesDataLen = pathAttributesToByteArray(pathAttributes, newPathAttributesData, 1500);
697
0
    size_t curPathAttributesDataLen = getPathAttributesLength();
698
0
    size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
699
0
    int offsetInLayer = sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen;
700
701
0
    if (newPathAttributesDataLen > curPathAttributesDataLen)
702
0
    {
703
0
      size_t numOfBytesToExtend = newPathAttributesDataLen - curPathAttributesDataLen;
704
705
0
      if (!extendLayer(offsetInLayer, numOfBytesToExtend))
706
0
      {
707
0
        PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional path attributes");
708
0
        return false;
709
0
      }
710
0
    }
711
0
    else if (newPathAttributesDataLen < curPathAttributesDataLen)
712
0
    {
713
0
      size_t numOfBytesToShorten = curPathAttributesDataLen - newPathAttributesDataLen;
714
715
0
      if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
716
0
      {
717
0
        PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the path attributes data");
718
0
        return false;
719
0
      }
720
0
    }
721
722
0
    if (newPathAttributesDataLen > 0)
723
0
    {
724
0
      memcpy(m_Data + offsetInLayer, newPathAttributesData, newPathAttributesDataLen);
725
0
    }
726
727
0
    getBasicHeader()->length =
728
0
        htobe16(be16toh(getBasicHeader()->length) + newPathAttributesDataLen - curPathAttributesDataLen);
729
730
0
    uint16_t newWithdrawnRoutesDataLenBE = htobe16(newPathAttributesDataLen);
731
0
    memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + curWithdrawnRoutesDataLen,
732
0
           &newWithdrawnRoutesDataLenBE, sizeof(uint16_t));
733
734
0
    return true;
735
0
  }
736
737
  bool BgpUpdateMessageLayer::clearPathAttributes()
738
0
  {
739
0
    return setPathAttributes(std::vector<path_attribute>());
740
0
  }
741
742
  size_t BgpUpdateMessageLayer::getNetworkLayerReachabilityInfoLength() const
743
0
  {
744
0
    size_t headerLen = getHeaderLen();
745
0
    size_t minLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t);
746
0
    if (headerLen >= minLen)
747
0
    {
748
0
      size_t withdrawnRouteLen = getWithdrawnRoutesLength();
749
0
      size_t pathAttrLen = getPathAttributesLength();
750
0
      int nlriSize = headerLen - minLen - withdrawnRouteLen - pathAttrLen;
751
0
      if (nlriSize >= 0)
752
0
      {
753
0
        return (size_t)nlriSize;
754
0
      }
755
756
0
      return 0;
757
0
    }
758
759
0
    return 0;
760
0
  }
761
762
  void BgpUpdateMessageLayer::getNetworkLayerReachabilityInfo(std::vector<prefix_and_ip>& nlri)
763
0
  {
764
0
    size_t nlriSize = getNetworkLayerReachabilityInfoLength();
765
0
    if (nlriSize == 0)
766
0
    {
767
0
      return;
768
0
    }
769
770
0
    uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + getWithdrawnRoutesLength() +
771
0
                       getPathAttributesLength();
772
0
    parsePrefixAndIPData(dataPtr, nlriSize, nlri);
773
0
  }
774
775
  bool BgpUpdateMessageLayer::isDataValid(const uint8_t* data, size_t dataSize)
776
0
  {
777
0
    if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t))
778
0
      return false;
779
780
0
    uint16_t withdrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header)));
781
0
    if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrLen)
782
0
      return false;
783
784
0
    uint16_t attrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrLen));
785
0
    if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrLen + attrLen)
786
0
      return false;
787
788
0
    return true;
789
0
  }
790
791
  bool BgpUpdateMessageLayer::setNetworkLayerReachabilityInfo(const std::vector<prefix_and_ip>& nlri)
792
0
  {
793
0
    uint8_t newNlriData[1500];
794
0
    size_t newNlriDataLen = prefixAndIPDataToByteArray(nlri, newNlriData, 1500);
795
0
    size_t curNlriDataLen = getNetworkLayerReachabilityInfoLength();
796
0
    size_t curPathAttributesDataLen = getPathAttributesLength();
797
0
    size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
798
0
    int offsetInLayer =
799
0
        sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen + curPathAttributesDataLen;
800
801
0
    if (newNlriDataLen > curNlriDataLen)
802
0
    {
803
0
      size_t numOfBytesToExtend = newNlriDataLen - curNlriDataLen;
804
805
0
      if (!extendLayer(offsetInLayer, numOfBytesToExtend))
806
0
      {
807
0
        PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional NLRI data");
808
0
        return false;
809
0
      }
810
0
    }
811
0
    else if (newNlriDataLen < curNlriDataLen)
812
0
    {
813
0
      size_t numOfBytesToShorten = curNlriDataLen - newNlriDataLen;
814
815
0
      if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
816
0
      {
817
0
        PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the NLRI data");
818
0
        return false;
819
0
      }
820
0
    }
821
822
0
    if (newNlriDataLen > 0)
823
0
    {
824
0
      memcpy(m_Data + offsetInLayer, newNlriData, newNlriDataLen);
825
0
    }
826
827
0
    getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newNlriDataLen - curNlriDataLen);
828
829
0
    return true;
830
0
  }
831
832
  bool BgpUpdateMessageLayer::clearNetworkLayerReachabilityInfo()
833
0
  {
834
0
    return setNetworkLayerReachabilityInfo(std::vector<prefix_and_ip>());
835
0
  }
836
837
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
838
  // BgpNotificationMessageLayer
839
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
840
841
  BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode)
842
0
  {
843
0
    initMessageData(errorCode, errorSubCode, nullptr, 0);
844
0
  }
845
846
  BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode,
847
                                                           const uint8_t* notificationData,
848
                                                           size_t notificationDataLen)
849
0
  {
850
0
    initMessageData(errorCode, errorSubCode, notificationData, notificationDataLen);
851
0
  }
852
853
  BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode,
854
                                                           const std::string& notificationData)
855
0
  {
856
0
    uint8_t notificationDataByteArr[1500];
857
0
    size_t notificationDataLen = hexStringToByteArray(notificationData, notificationDataByteArr, 1500);
858
0
    initMessageData(errorCode, errorSubCode, notificationDataByteArr, notificationDataLen);
859
0
  }
860
861
  void BgpNotificationMessageLayer::initMessageData(uint8_t errorCode, uint8_t errorSubCode,
862
                                                    const uint8_t* notificationData, size_t notificationDataLen)
863
0
  {
864
0
    size_t headerLen = sizeof(bgp_notification_message);
865
0
    if (notificationData != nullptr && notificationDataLen > 0)
866
0
    {
867
0
      headerLen += notificationDataLen;
868
0
    }
869
0
    m_DataLen = headerLen;
870
0
    m_Data = new uint8_t[headerLen];
871
0
    memset(m_Data, 0, headerLen);
872
0
    setBgpFields(headerLen);
873
0
    bgp_notification_message* msgHdr = getNotificationMsgHeader();
874
0
    msgHdr->errorCode = errorCode;
875
0
    msgHdr->errorSubCode = errorSubCode;
876
0
    memcpy(m_Data + sizeof(bgp_notification_message), notificationData, notificationDataLen);
877
0
    m_Protocol = BGP;
878
0
  }
879
880
  size_t BgpNotificationMessageLayer::getNotificationDataLen() const
881
0
  {
882
0
    size_t headerLen = getHeaderLen();
883
0
    if (headerLen > sizeof(bgp_notification_message))
884
0
    {
885
0
      return headerLen - sizeof(bgp_notification_message);
886
0
    }
887
888
0
    return 0;
889
0
  }
890
891
  uint8_t* BgpNotificationMessageLayer::getNotificationData() const
892
0
  {
893
0
    if (getNotificationDataLen() > 0)
894
0
    {
895
0
      return m_Data + sizeof(bgp_notification_message);
896
0
    }
897
898
0
    return nullptr;
899
0
  }
900
901
  std::string BgpNotificationMessageLayer::getNotificationDataAsHexString() const
902
0
  {
903
0
    uint8_t* notificationData = getNotificationData();
904
0
    if (notificationData == nullptr)
905
0
    {
906
0
      return "";
907
0
    }
908
909
0
    return byteArrayToHexString(notificationData, getNotificationDataLen());
910
0
  }
911
912
  bool BgpNotificationMessageLayer::setNotificationData(const uint8_t* newNotificationData,
913
                                                        size_t newNotificationDataLen)
914
0
  {
915
0
    if (newNotificationData == nullptr)
916
0
    {
917
0
      newNotificationDataLen = 0;
918
0
    }
919
920
0
    size_t curNotificationDataLen = getNotificationDataLen();
921
0
    int offsetInLayer = sizeof(bgp_notification_message);
922
923
0
    if (newNotificationDataLen > curNotificationDataLen)
924
0
    {
925
0
      size_t numOfBytesToExtend = newNotificationDataLen - curNotificationDataLen;
926
927
0
      if (!extendLayer(offsetInLayer, numOfBytesToExtend))
928
0
      {
929
0
        PCPP_LOG_ERROR("Couldn't extend BGP notification layer to include the additional notification data");
930
0
        return false;
931
0
      }
932
0
    }
933
0
    else if (newNotificationDataLen < curNotificationDataLen)
934
0
    {
935
0
      size_t numOfBytesToShorten = curNotificationDataLen - newNotificationDataLen;
936
937
0
      if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
938
0
      {
939
0
        PCPP_LOG_ERROR(
940
0
            "Couldn't shorten BGP notification layer to set the right size of the notification data");
941
0
        return false;
942
0
      }
943
0
    }
944
945
0
    if (newNotificationDataLen > 0)
946
0
    {
947
0
      memcpy(m_Data + offsetInLayer, newNotificationData, newNotificationDataLen);
948
0
    }
949
950
0
    getNotificationMsgHeader()->length = htobe16(sizeof(bgp_notification_message) + newNotificationDataLen);
951
952
0
    return true;
953
0
  }
954
955
  bool BgpNotificationMessageLayer::setNotificationData(const std::string& newNotificationDataAsHexString)
956
0
  {
957
0
    if (newNotificationDataAsHexString.empty())
958
0
    {
959
0
      return setNotificationData(nullptr, 0);
960
0
    }
961
962
0
    uint8_t newNotificationData[1500];
963
0
    size_t newNotificationDataLen = hexStringToByteArray(newNotificationDataAsHexString, newNotificationData, 1500);
964
965
0
    if (newNotificationDataLen == 0)
966
0
    {
967
0
      PCPP_LOG_ERROR("newNotificationDataAsHexString is not a valid hex string");
968
0
      return false;
969
0
    }
970
971
0
    return setNotificationData(newNotificationData, newNotificationDataLen);
972
0
  }
973
974
  // ~~~~~~~~~~~~~~~~~~~~~~~~
975
  // BgpKeepaliveMessageLayer
976
  // ~~~~~~~~~~~~~~~~~~~~~~~~
977
978
0
  BgpKeepaliveMessageLayer::BgpKeepaliveMessageLayer() : BgpLayer()
979
0
  {
980
0
    const size_t headerLen = sizeof(bgp_common_header);
981
0
    m_DataLen = headerLen;
982
0
    m_Data = new uint8_t[headerLen];
983
0
    memset(m_Data, 0, headerLen);
984
0
    setBgpFields(headerLen);
985
0
    m_Protocol = BGP;
986
0
  }
987
988
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
989
  // BgpRouteRefreshMessageLayer
990
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
991
992
  BgpRouteRefreshMessageLayer::BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi)
993
0
  {
994
0
    const size_t headerLen = sizeof(bgp_route_refresh_message);
995
0
    m_DataLen = headerLen;
996
0
    m_Data = new uint8_t[headerLen];
997
0
    memset(m_Data, 0, headerLen);
998
0
    setBgpFields(headerLen);
999
0
    bgp_route_refresh_message* msgHdr = getRouteRefreshHeader();
1000
    msgHdr->afi = htobe16(afi);
1001
0
    msgHdr->safi = safi;
1002
0
    m_Protocol = BGP;
1003
0
  }
1004
1005
}  // namespace pcpp