Coverage Report

Created: 2026-10-17 07:09

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