Coverage Report

Created: 2025-07-11 07:47

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