Coverage Report

Created: 2025-07-18 07:14

/src/PcapPlusPlus/Packet++/src/StpLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
0
#define LOG_MODULE PacketLogModuleStpLayer
2
3
#include "StpLayer.h"
4
#include "PayloadLayer.h"
5
#include "EndianPortable.h"
6
#include "Logger.h"
7
8
namespace pcpp
9
{
10
11
  // ---------------------- Class STPLayer ----------------------
12
  MacAddress StpLayer::StpMulticastDstMAC("01:80:C2:00:00:00");
13
  MacAddress StpLayer::StpUplinkFastMulticastDstMAC("01:00:0C:CD:CD:CD");
14
15
  MacAddress StpLayer::IDtoMacAddress(uint64_t id)
16
0
  {
17
0
    return MacAddress((id >> 40) & 0xFF, (id >> 32) & 0xFF, (id >> 24) & 0xFF, (id >> 16) & 0xFF, (id >> 8) & 0xFF,
18
0
                      id & 0xFF);
19
0
  }
20
21
  uint64_t StpLayer::macAddressToID(const pcpp::MacAddress& addr)
22
0
  {
23
0
    uint8_t value[6];
24
0
    addr.copyTo(value);
25
0
    return ((uint64_t(value[0]) << 40) | (uint64_t(value[1]) << 32) | (uint64_t(value[2]) << 24) |
26
0
            (uint64_t(value[3]) << 16) | (uint64_t(value[4]) << 8) | (uint64_t(value[5])));
27
0
  }
28
29
  bool StpLayer::isDataValid(const uint8_t* data, size_t dataLen)
30
0
  {
31
0
    return data && dataLen;
32
0
  }
33
34
  StpLayer* StpLayer::parseStpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
35
0
  {
36
0
    if (dataLen >= sizeof(stp_tcn_bpdu))
37
0
    {
38
0
      stp_tcn_bpdu* ptr = (stp_tcn_bpdu*)data;
39
0
      switch (ptr->type)
40
0
      {
41
0
      case 0x00:
42
0
        return StpConfigurationBPDULayer::isDataValid(data, dataLen)
43
0
                   ? new StpConfigurationBPDULayer(data, dataLen, prevLayer, packet)
44
0
                   : nullptr;
45
0
      case 0x02:
46
0
        if (ptr->version == 0x2)
47
0
          return RapidStpLayer::isDataValid(data, dataLen)
48
0
                     ? new RapidStpLayer(data, dataLen, prevLayer, packet)
49
0
                     : nullptr;
50
0
        if (ptr->version == 0x3)
51
0
          return MultipleStpLayer::isDataValid(data, dataLen)
52
0
                     ? new MultipleStpLayer(data, dataLen, prevLayer, packet)
53
0
                     : nullptr;
54
0
        PCPP_LOG_DEBUG("Unknown Spanning Tree Version");
55
0
        return nullptr;
56
0
      case 0x80:
57
0
        return StpTopologyChangeBPDULayer::isDataValid(data, dataLen)
58
0
                   ? new StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet)
59
0
                   : nullptr;
60
      // TODO: Per VLAN Spanning Tree+ (PVST+)
61
      // TODO: Rapid Per VLAN Spanning Tree+ (RPVST+)
62
      // TODO: Cisco Uplink Fast
63
0
      default:
64
0
        PCPP_LOG_DEBUG("Unknown Spanning Tree Protocol type");
65
0
        return nullptr;
66
0
      }
67
0
    }
68
69
0
    PCPP_LOG_DEBUG("Data length is less than any STP header");
70
0
    return nullptr;
71
0
  }
72
73
  // ---------------------- Class StpTopologyChangeBPDULayer ----------------------
74
0
  StpTopologyChangeBPDULayer::StpTopologyChangeBPDULayer() : StpLayer(sizeof(stp_tcn_bpdu))
75
0
  {
76
    // Set initial values for TCN
77
0
    setProtoId(0x0);
78
0
    setVersion(0x0);
79
0
    setType(0x80);
80
0
  }
81
82
  void StpTopologyChangeBPDULayer::parseNextLayer()
83
0
  {
84
0
    if (m_DataLen > sizeof(stp_tcn_bpdu))
85
0
      m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_tcn_bpdu), this, m_Packet);
86
0
  }
87
88
  // ---------------------- Class StpConfigurationBPDULayer ----------------------
89
0
  StpConfigurationBPDULayer::StpConfigurationBPDULayer() : StpTopologyChangeBPDULayer(sizeof(stp_conf_bpdu))
90
0
  {
91
    // Set initial value for configuration BPDU
92
0
    setProtoId(0x0);
93
0
    setVersion(0x0);
94
0
    setType(0x0);
95
0
  }
96
97
  uint64_t StpConfigurationBPDULayer::getRootId() const
98
0
  {
99
0
    return be64toh(getStpConfHeader()->rootId);
100
0
  }
101
102
  void StpConfigurationBPDULayer::setRootId(uint64_t value)
103
0
  {
104
0
    getStpConfHeader()->rootId = htobe64(value);
105
0
  }
106
107
  uint16_t StpConfigurationBPDULayer::getRootPriority() const
108
0
  {
109
0
    return be16toh(getStpConfHeader()->rootId) & 0xf000;
110
0
  }
111
112
  void StpConfigurationBPDULayer::setRootPriority(uint16_t value)
113
0
  {
114
0
    getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0xf000)) | htobe16(value & 0xf000);
115
0
  }
116
117
  uint16_t StpConfigurationBPDULayer::getRootSystemIDExtension() const
118
0
  {
119
0
    return be16toh(getStpConfHeader()->rootId) & 0x0fff;
120
0
  }
121
122
  void StpConfigurationBPDULayer::setRootSystemIDExtension(uint16_t value)
123
0
  {
124
0
    getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff);
125
0
  }
126
127
  void StpConfigurationBPDULayer::setRootSystemID(const pcpp::MacAddress& value)
128
0
  {
129
0
    setRootId((getRootId() & (uint64_t(0xffff) << 48)) | macAddressToID(value));
130
0
  };
131
132
  uint32_t StpConfigurationBPDULayer::getPathCost() const
133
0
  {
134
0
    return be32toh(getStpConfHeader()->pathCost);
135
0
  }
136
137
  void StpConfigurationBPDULayer::setPathCost(uint32_t value)
138
0
  {
139
0
    getStpConfHeader()->pathCost = htobe32(value);
140
0
  }
141
142
  uint64_t StpConfigurationBPDULayer::getBridgeId() const
143
0
  {
144
0
    return be64toh(getStpConfHeader()->bridgeId);
145
0
  }
146
147
  void StpConfigurationBPDULayer::setBridgeId(uint64_t value)
148
0
  {
149
0
    getStpConfHeader()->bridgeId = htobe64(value);
150
0
  }
151
152
  uint16_t StpConfigurationBPDULayer::getBridgePriority() const
153
0
  {
154
0
    return be16toh(getStpConfHeader()->bridgeId) & 0xf000;
155
0
  }
156
157
  void StpConfigurationBPDULayer::setBridgePriority(uint16_t value)
158
0
  {
159
0
    getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000);
160
0
  }
161
162
  uint16_t StpConfigurationBPDULayer::getBridgeSystemIDExtension() const
163
0
  {
164
0
    return be16toh(getStpConfHeader()->bridgeId) & 0x0fff;
165
0
  }
166
167
  void StpConfigurationBPDULayer::setBridgeSystemIDExtension(uint16_t value)
168
0
  {
169
0
    getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff);
170
0
  }
171
172
  void StpConfigurationBPDULayer::setBridgeSystemID(const pcpp::MacAddress& value)
173
0
  {
174
0
    setBridgeId((getBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value));
175
0
  }
176
177
  uint16_t StpConfigurationBPDULayer::getPortId() const
178
0
  {
179
0
    return be16toh(getStpConfHeader()->portId);
180
0
  }
181
182
  void StpConfigurationBPDULayer::setPortId(uint16_t value)
183
0
  {
184
0
    getStpConfHeader()->portId = htobe16(value);
185
0
  }
186
187
  double StpConfigurationBPDULayer::getMessageAge() const
188
0
  {
189
0
    return getStpConfHeader()->msgAge;
190
0
  }
191
192
  void StpConfigurationBPDULayer::setMessageAge(double value)
193
0
  {
194
0
    getStpConfHeader()->msgAge = value;
195
0
  }
196
197
  double StpConfigurationBPDULayer::getMaximumAge() const
198
0
  {
199
0
    return getStpConfHeader()->maxAge;
200
0
  }
201
202
  void StpConfigurationBPDULayer::setMaximumAge(double value)
203
0
  {
204
0
    getStpConfHeader()->maxAge = value;
205
0
  }
206
207
  double StpConfigurationBPDULayer::getTransmissionInterval() const
208
0
  {
209
0
    return getStpConfHeader()->helloTime;
210
0
  }
211
212
  void StpConfigurationBPDULayer::setTransmissionInterval(double value)
213
0
  {
214
0
    getStpConfHeader()->helloTime = value;
215
0
  }
216
217
  double StpConfigurationBPDULayer::getForwardDelay() const
218
0
  {
219
0
    return getStpConfHeader()->forwardDelay;
220
0
  }
221
222
  void StpConfigurationBPDULayer::setForwardDelay(double value)
223
0
  {
224
0
    getStpConfHeader()->forwardDelay = value;
225
0
  }
226
227
  void StpConfigurationBPDULayer::parseNextLayer()
228
0
  {
229
0
    if (m_DataLen > sizeof(stp_conf_bpdu))
230
0
      m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_conf_bpdu), this, m_Packet);
231
0
  }
232
233
  // ---------------------- Class RapidStpLayer ----------------------
234
0
  RapidStpLayer::RapidStpLayer() : StpConfigurationBPDULayer(sizeof(rstp_conf_bpdu))
235
0
  {
236
    // Set initial value for Rapid STP
237
0
    setProtoId(0x0);
238
0
    setVersion(0x2);
239
0
    setType(0x2);
240
0
  }
241
242
  void RapidStpLayer::parseNextLayer()
243
0
  {
244
0
    if (m_DataLen > sizeof(rstp_conf_bpdu))
245
0
      m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(rstp_conf_bpdu), this, m_Packet);
246
0
  }
247
248
  // ---------------------- Class MultipleStpLayer ----------------------
249
0
  MultipleStpLayer::MultipleStpLayer() : RapidStpLayer(sizeof(mstp_conf_bpdu))
250
0
  {
251
    // Set initial value for Multiple STP
252
0
    setProtoId(0x0);
253
0
    setVersion(0x3);
254
0
    setType(0x2);
255
0
  }
256
257
  uint16_t MultipleStpLayer::getVersion3Len() const
258
0
  {
259
0
    return be16toh(getMstpHeader()->version3Len);
260
0
  }
261
262
  void MultipleStpLayer::setVersion3Len(uint16_t value)
263
0
  {
264
0
    getMstpHeader()->version3Len = htobe16(value);
265
0
  }
266
267
  uint32_t MultipleStpLayer::getCISTIrpc() const
268
0
  {
269
0
    return be32toh(getMstpHeader()->irpc);
270
0
  }
271
272
  void MultipleStpLayer::setCISTIrpc(uint32_t value)
273
0
  {
274
0
    getMstpHeader()->irpc = htobe32(value);
275
0
  }
276
277
  uint64_t MultipleStpLayer::getCISTBridgeId() const
278
0
  {
279
0
    return be64toh(getMstpHeader()->cistBridgeId);
280
0
  }
281
282
  void MultipleStpLayer::setCISTBridgeId(uint64_t value)
283
0
  {
284
0
    getMstpHeader()->cistBridgeId = htobe64(value);
285
0
  }
286
287
  uint16_t MultipleStpLayer::getCISTBridgePriority() const
288
0
  {
289
0
    return be16toh(getMstpHeader()->cistBridgeId) & 0xf000;
290
0
  }
291
292
  void MultipleStpLayer::setCISTBridgePriority(uint16_t value)
293
0
  {
294
0
    getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000);
295
0
  }
296
297
  uint16_t MultipleStpLayer::getCISTBridgeSystemIDExtension() const
298
0
  {
299
0
    return be16toh(getMstpHeader()->cistBridgeId) & 0x0fff;
300
0
  }
301
302
  void MultipleStpLayer::setCISTBridgeSystemIDExtension(uint16_t value)
303
0
  {
304
0
    getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff);
305
0
  }
306
307
  void MultipleStpLayer::setCISTBridgeSystemID(const pcpp::MacAddress& value)
308
0
  {
309
0
    setCISTBridgeId((getCISTBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value));
310
0
  }
311
312
  std::string MultipleStpLayer::getMstConfigurationName() const
313
0
  {
314
0
    std::string str = std::string((char*)(getMstpHeader()->mstConfigName), 32);
315
0
    str.erase(std::find(str.begin(), str.end(), '\0'), str.end());
316
0
    return str;
317
0
  }
318
319
  uint16_t MultipleStpLayer::getMstConfigRevision() const
320
0
  {
321
0
    return be16toh(getMstpHeader()->mstConfigRevision);
322
0
  }
323
324
  void MultipleStpLayer::setMstConfigRevision(uint16_t value)
325
0
  {
326
0
    getMstpHeader()->mstConfigRevision = htobe16(value);
327
0
  }
328
329
  void MultipleStpLayer::setMstConfigDigest(const uint8_t* value, uint8_t len)
330
0
  {
331
0
    memset(getMstpHeader()->mstConfigDigest, 0, 16);
332
0
    memcpy(getMstpHeader()->mstConfigDigest, value, std::min<size_t>(len, 16));
333
0
  }
334
335
  void MultipleStpLayer::setMstConfigurationName(const std::string& value)
336
0
  {
337
0
    memset(getMstpHeader()->mstConfigName, 0, 32);
338
0
    memcpy(getMstpHeader()->mstConfigName, value.c_str(), std::min<size_t>(value.size(), 32));
339
0
  }
340
341
  msti_conf_msg* MultipleStpLayer::getMstiConfMessages() const
342
0
  {
343
0
    if (getNumberOfMSTIConfMessages())
344
0
      return (msti_conf_msg*)(m_Data + sizeof(mstp_conf_bpdu));
345
0
    return nullptr;
346
0
  }
347
348
}  // namespace pcpp