Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/header/StpLayer.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_STP_LAYER
2
#define PACKETPP_STP_LAYER
3
4
#include "Layer.h"
5
#include "MacAddress.h"
6
7
/// @file
8
9
/**
10
 * \namespace pcpp
11
 * \brief The main namespace for the PcapPlusPlus lib
12
 */
13
namespace pcpp
14
{
15
16
/**
17
 * @struct stp_tcn_bpdu
18
 * Represents payload of network changes announcements of BPDU
19
 */
20
#pragma pack(push, 1)
21
  struct stp_tcn_bpdu
22
  {
23
    /// Protocol ID. Fixed at 0x0, which represents IEEE 802.1d
24
    uint16_t protoId;
25
    /// Protocol version. 0x0 for STP, 0x2 for RSTP, 0x3 for MSTP
26
    uint8_t version;
27
    /// Type of the BPDU. 0x0 for configuration, 0x2 for RSTP/MSTP, 0x80 for TCN
28
    uint8_t type;
29
  };
30
#pragma pack(pop)
31
32
/// Spanning Tree protocol common header
33
typedef stp_tcn_bpdu stp_header;
34
35
/**
36
 * @struct stp_conf_bpdu
37
 * Represents payload configuration of BPDU for STP
38
 */
39
#pragma pack(push, 1)
40
  struct stp_conf_bpdu : stp_tcn_bpdu
41
  {
42
    /// Flag for indicate purpose of BPDU
43
    uint8_t flag;
44
    /// Root bridge ID
45
    uint64_t rootId;
46
    /// Cost of path
47
    uint32_t pathCost;
48
    /// Bridge ID
49
    uint64_t bridgeId;
50
    /// Port ID
51
    uint16_t portId;
52
    /// Age of the BPDU
53
    uint16_t msgAge;
54
    /// Maximum age of the BPDU
55
    uint16_t maxAge;
56
    /// BPDU transmission interval
57
    uint16_t helloTime;
58
    /// Delay for STP
59
    uint16_t forwardDelay;
60
  };
61
#pragma pack(pop)
62
63
/**
64
 * @struct rstp_conf_bpdu
65
 * Represents payload configuration of BPDU for Rapid STP (RSTP)
66
 */
67
#pragma pack(push, 1)
68
  struct rstp_conf_bpdu : stp_conf_bpdu
69
  {
70
    /// Version1 length. The value is 0x0
71
    uint8_t version1Len;
72
  };
73
#pragma pack(pop)
74
75
/**
76
 * @struct mstp_conf_bpdu
77
 * Represents payload configuration of BPDU for Multiple STP (MSTP)
78
 */
79
#pragma pack(push, 1)
80
  struct mstp_conf_bpdu : rstp_conf_bpdu
81
  {
82
    /// Version3 length.
83
    uint16_t version3Len;
84
    /// Configuration id format selector
85
    uint8_t mstConfigFormatSelector;
86
    /// Configuration id name
87
    uint8_t mstConfigName[32];
88
    /// Configuration id revision
89
    uint16_t mstConfigRevision;
90
    /// Configuration id digest
91
    uint8_t mstConfigDigest[16];
92
    /// CIST internal root path cost
93
    uint32_t irpc;
94
    /// CIST bridge id
95
    uint64_t cistBridgeId;
96
    /// CIST remaining hop count
97
    uint8_t remainId;
98
  };
99
#pragma pack(pop)
100
101
/**
102
 * @struct msti_conf_msg
103
 * Represents MSTI configuration messages. Each message contains 16 bytes and MSTP can contain 0 to 64 MSTI messages.
104
 */
105
#pragma pack(push, 1)
106
  struct msti_conf_msg
107
  {
108
    /// MSTI flags
109
    uint8_t flags;
110
    /// Regional root switching id (Priority (4 bits) + ID (12 bits) + Regional root (48 bits - MAC address))
111
    uint64_t regionalRootId;
112
    /// Total path cost from local port to regional port
113
    uint32_t pathCost;
114
    /// Priority value of switching device
115
    uint8_t bridgePriority;
116
    /// Priority value of port
117
    uint8_t portPriority;
118
    /// Remaining hops of BPDU
119
    uint8_t remainingHops;
120
  };
121
#pragma pack(pop)
122
123
  /**
124
   * @class StpLayer
125
   * Represents an Spanning Tree Protocol Layer
126
   */
127
  class StpLayer : public Layer
128
  {
129
    protected:
130
    StpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
131
      : Layer(data, dataLen, prevLayer, packet)
132
864
    {
133
864
      m_Protocol = STP;
134
864
    }
135
136
    static pcpp::MacAddress IDtoMacAddress(uint64_t id);
137
138
    public:
139
    /// STP protocol uses "01:80:C2:00:00:00" multicast address as destination MAC
140
    static pcpp::MacAddress StpMulticastDstMAC;
141
    /// STP Uplink Fast protocol uses "01:00:0C:CD:CD:CD" as destination MAC
142
    static pcpp::MacAddress StpUplinkFastMulticastDstMAC;
143
144
    /**
145
     * Get a pointer to base Spanning tree header
146
     * @return A pointer to spanning tree header
147
     */
148
0
    stp_header *getStpHeader() const { return (stp_header *)(m_Data); }
149
150
    /**
151
     * Returns the protocol id. Fixed at 0x0 for STP messages which represents IEEE 802.1d
152
     * @return ID of the protocol
153
     */
154
0
    uint16_t getProtoId() const { return getStpHeader()->protoId; }
155
156
    /**
157
     * Returns the version. Fixed at 0x0 for STP messages
158
     * @return Version number
159
     */
160
0
    uint8_t getVersion() const { return getStpHeader()->version; }
161
162
    /**
163
     * Returns the type of configuration message.
164
     * @return Type of configuration message
165
     */
166
0
    uint8_t getType() const { return getStpHeader()->type; }
167
168
    // overridden methods
169
170
    /**
171
     * @return The size of STP packet
172
     */
173
0
    size_t getHeaderLen() const { return m_DataLen; }
174
175
    /// Parses the next layer. STP is the always last so does nothing for this layer
176
864
    void parseNextLayer() {}
177
178
    /// Does nothing for this layer
179
0
    void computeCalculateFields() {}
180
181
    /**
182
     * @return The OSI layer level of STP (Data Link Layer).
183
     */
184
864
    OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
185
186
    /**
187
     * A static method that validates the input data
188
     * @param[in] data The pointer to the beginning of a byte stream of an Spanning Tree packet
189
     * @param[in] dataLen The length of the byte stream
190
     * @return True if the data is valid and can represent an Spanning Tree packet
191
     */
192
    static bool isDataValid(const uint8_t *data, size_t dataLen);
193
194
    /**
195
     * A method to create STP layer from existing packet
196
     * @param[in] data A pointer to the raw data
197
     * @param[in] dataLen Size of the data in bytes
198
     * @param[in] prevLayer A pointer to the previous layer
199
     * @param[in] packet A pointer to the Packet instance where layer will be stored
200
     * @return A newly allocated STP layer of one of the following types (according to the message type):
201
     * StpConfigurationBPDULayer, StpTopologyChangeBPDULayer, RapidStpLayer, MultipleStpLayer
202
     */
203
    static StpLayer *parseStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet);
204
  };
205
206
  /**
207
   * @class StpTopologyChangeBPDULayer
208
   * Represents network topology change BPDU message of Spanning Tree Protocol
209
   */
210
  class StpTopologyChangeBPDULayer : public StpLayer
211
  {
212
    public:
213
    /**
214
     * A constructor that creates the layer from an existing packet raw data
215
     * @param[in] data A pointer to the raw data
216
     * @param[in] dataLen Size of the data in bytes
217
     * @param[in] prevLayer A pointer to the previous layer
218
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
219
     */
220
    StpTopologyChangeBPDULayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
221
      : StpLayer(data, dataLen, prevLayer, packet)
222
864
    {
223
864
    }
224
225
    /**
226
     * Get a pointer to network topology change (TCN) BPDU message
227
     * @return A pointer to TCN BPDU message
228
     */
229
0
    stp_tcn_bpdu* getStpTcnHeader() { return getStpHeader(); }
230
231
    // overridden methods
232
233
    /**
234
     * @return Returns the protocol info as readable string
235
     */
236
0
    std::string toString() const { return "Spanning Tree Topology Change Notification"; }
237
238
    /**
239
     * A static method that validates the input data
240
     * @param[in] data The pointer to the beginning of a byte stream of an Spanning Tree Topology Change BPDU packet
241
     * @param[in] dataLen The length of the byte stream
242
     * @return True if the data is valid and can represent an Spanning Tree packet
243
     */
244
770
    static bool isDataValid(const uint8_t *data, size_t dataLen) { return data && dataLen >= sizeof(stp_tcn_bpdu); }
245
  };
246
247
  /**
248
   * @class StpConfigurationBPDULayer
249
   * Represents configuration BPDU message of Spanning Tree Protocol
250
   */
251
  class StpConfigurationBPDULayer : public StpTopologyChangeBPDULayer
252
  {
253
    public:
254
    /**
255
     * A constructor that creates the layer from an existing packet raw data
256
     * @param[in] data A pointer to the raw data
257
     * @param[in] dataLen Size of the data in bytes
258
     * @param[in] prevLayer A pointer to the previous layer
259
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
260
     */
261
    StpConfigurationBPDULayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
262
      : StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet)
263
94
    {
264
94
    }
265
266
    /**
267
     * Get a pointer to configuration BPDU message
268
     * @return A pointer to configuration BPDU message
269
     */
270
0
    stp_conf_bpdu *getStpConfHeader() const { return (stp_conf_bpdu *)(m_Data); }
271
272
    /**
273
     * Returns the flags of configuration message which indicates purpose of BPDU
274
     * @return Flags of the configuration message
275
     */
276
0
    uint8_t getFlag() const { return getStpConfHeader()->flag; }
277
278
    /**
279
     * Returns the root bridge identifier
280
     * @return root bridge identifier
281
     */
282
    uint64_t getRootId() const;
283
284
    /**
285
     * Returns the priority of root bridge
286
     * @return Priority of root bridge
287
     */
288
    uint16_t getRootPriority() const;
289
290
    /**
291
     * Returns the system identifier extension of root bridge
292
     * @return System extension of root bridge
293
     */
294
    uint16_t getRootSystemIDExtension() const;
295
296
    /**
297
     * Returns the system identifier of root bridge
298
     * @return System identifier of root bridge
299
     */
300
0
    pcpp::MacAddress getRootSystemID() const { return IDtoMacAddress(getRootId()); }
301
302
    /**
303
     * Returns the value of the cost of path
304
     * @return Cost of path
305
     */
306
    uint32_t getPathCost() const;
307
308
    /**
309
     * Returns the bridge identifier
310
     * @return Bridge identifier
311
     */
312
    uint64_t getBridgeId() const;
313
314
    /**
315
     * Returns the priority of bridge
316
     * @return Priority of bridge
317
     */
318
    uint16_t getBridgePriority() const;
319
320
    /**
321
     * Returns the system identifier extension of bridge
322
     * @return System extension of bridge
323
     */
324
    uint16_t getBridgeSystemIDExtension() const;
325
326
    /**
327
     * Returns the system identifier of bridge
328
     * @return System identifier of bridge
329
     */
330
0
    pcpp::MacAddress getBridgeSystemID() const { return IDtoMacAddress(getBridgeId()); }
331
332
    /**
333
     * Returns the port identifier
334
     * @return Port identifier
335
     */
336
    uint16_t getPortId() const;
337
338
    /**
339
     * Returns age of the BPDU message
340
     * @return Age of BPDU in seconds
341
     */
342
    double getMessageAge() const;
343
344
    /**
345
     * Returns maximum age of the BPDU message
346
     * @return Maximum age of BPDU in seconds
347
     */
348
    double getMaximumAge() const;
349
350
    /**
351
     * Returns the BPDU transmission interval
352
     * @return Value of the transmission interval in seconds
353
     */
354
    double getTransmissionInterval() const;
355
356
    /**
357
     * Returns the delay for STP message
358
     * @return Value of the forward delay in seconds
359
     */
360
    double getForwardDelay() const;
361
362
    // overridden methods
363
364
    /**
365
     * @return Returns the protocol info as readable string
366
     */
367
0
    std::string toString() const { return "Spanning Tree Configuration"; }
368
369
    /**
370
     * A static method that validates the input data
371
     * @param[in] data The pointer to the beginning of a byte stream of an Spanning Tree Configuration BPDU packet
372
     * @param[in] dataLen The length of the byte stream
373
     * @return True if the data is valid and can represent an Spanning Tree packet
374
     */
375
    static bool isDataValid(const uint8_t *data, size_t dataLen)
376
589
    {
377
589
      return data && dataLen >= sizeof(stp_conf_bpdu);
378
589
    }
379
  };
380
381
  /**
382
   * @class RapidStpLayer
383
   * Represents Rapid Spanning Tree Protocol (RSTP)
384
   */
385
  class RapidStpLayer : public StpConfigurationBPDULayer
386
  {
387
    public:
388
    /**
389
     * A constructor that creates the layer from an existing packet raw data
390
     * @param[in] data A pointer to the raw data
391
     * @param[in] dataLen Size of the data in bytes
392
     * @param[in] prevLayer A pointer to the previous layer
393
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
394
     */
395
    RapidStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
396
      : StpConfigurationBPDULayer(data, dataLen, prevLayer, packet)
397
70
    {
398
70
    }
399
400
    /**
401
     * Get a pointer to Rapid STP header
402
     * @return A pointer to Rapid STP header
403
     */
404
0
    rstp_conf_bpdu *getRstpConfHeader() const { return (rstp_conf_bpdu *)(m_Data); }
405
406
    /**
407
     * Returns the length of version1 field. Fixed at 0x0 for Rapid STP
408
     * @return Length of the version1 field
409
     */
410
0
    uint8_t getVersion1Len() const { return getRstpConfHeader()->version1Len; }
411
412
    // overridden methods
413
414
    /**
415
     * @return Returns the protocol info as readable string
416
     */
417
0
    std::string toString() const { return "Rapid Spanning Tree"; }
418
419
    /**
420
     * A static method that validates the input data
421
     * @param[in] data The pointer to the beginning of a byte stream of an Rapid STP packet
422
     * @param[in] dataLen The length of the byte stream
423
     * @return True if the data is valid and can represent an Spanning Tree packet
424
     */
425
    static bool isDataValid(const uint8_t *data, size_t dataLen)
426
161
    {
427
161
      return data && dataLen >= sizeof(rstp_conf_bpdu);
428
161
    }
429
  };
430
431
  /**
432
   * @class MultipleStpLayer
433
   * Represents Multiple Spanning Tree Protocol (MSTP)
434
   */
435
  class MultipleStpLayer : public RapidStpLayer
436
  {
437
    public:
438
    /**
439
     * A constructor that creates the layer from an existing packet raw data
440
     * @param[in] data A pointer to the raw data
441
     * @param[in] dataLen Size of the data in bytes
442
     * @param[in] prevLayer A pointer to the previous layer
443
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
444
     */
445
    MultipleStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
446
      : RapidStpLayer(data, dataLen, prevLayer, packet)
447
34
    {
448
34
    }
449
450
    /**
451
     * Get a pointer to Multiple STP header
452
     * @return A pointer to Multiple STP header
453
     */
454
0
    mstp_conf_bpdu *getMstpHeader() const { return (mstp_conf_bpdu *)(m_Data); }
455
456
    /**
457
     * @return Returns the length of version3 field.
458
     */
459
    uint16_t getVersion3Len() const;
460
461
    /**
462
     * Returns the configuration ID format selector
463
     * @return Configuration ID of format selector
464
     */
465
0
    uint8_t getMstConfigurationFormatSelector() const { return getMstpHeader()->mstConfigFormatSelector; }
466
467
    /**
468
     * Returns the pointer to configuration name field.
469
     * @return Configuration name
470
     */
471
    std::string getMstConfigurationName() const;
472
473
    /**
474
     * Returns the revision of configuration ID
475
     * @return Revision of configuration ID
476
     */
477
0
    uint16_t getMstConfigRevision() const { return getMstpHeader()->mstConfigRevision; }
478
479
    /**
480
     * Returns the pointer to configuration message digest. The field itself always 16 bytes long.
481
     * @return A pointer to configuration digest
482
     */
483
0
    uint8_t *getMstConfigDigest() const { return getMstpHeader()->mstConfigDigest; }
484
485
    /**
486
     * Returns CIST internal root path cost
487
     * @return Value of the internal root path cost
488
     */
489
    uint32_t getCISTIrpc() const;
490
491
    /**
492
     * Returns CIST bridge identifier
493
     * @return Value of the bridge identifier
494
     */
495
    uint64_t getCISTBridgeId() const;
496
497
    /**
498
     * Returns the priority of CIST bridge
499
     * @return Priority of CIST bridge
500
     */
501
    uint16_t getCISTBridgePriority() const;
502
503
    /**
504
     * Returns the system identifier extension of CIST bridge
505
     * @return System extension of CIST bridge
506
     */
507
    uint16_t getCISTBridgeSystemIDExtension() const;
508
509
    /**
510
     * Returns the system identifier of CIST bridge
511
     * @return System identifier of CIST bridge
512
     */
513
0
    pcpp::MacAddress getCISTBridgeSystemID() const { return IDtoMacAddress(getCISTBridgeId()); }
514
515
    /**
516
     * Returns the remaining hop count
517
     * @return Value of remaining hop count
518
     */
519
0
    uint8_t getRemainingHopCount() const { return getMstpHeader()->remainId; }
520
521
    /**
522
     * Returns the total number of MSTI configuration messages
523
     * @return Number of MSTI configuration messages. Can be between 0 and 64.
524
     */
525
0
    uint8_t getNumberOfMSTIConfMessages() const { return (getVersion3Len() - (sizeof(mstp_conf_bpdu) - sizeof(rstp_conf_bpdu) - sizeof(uint16_t))) / sizeof(msti_conf_msg); }
526
527
    /**
528
     * Returns a reference to MSTI configuration messages. An MSTP packet can contain between 0 to 64 MSTI messages.
529
     * The number of messages can be obtained by using getNumberOfMSTIConfMessages()
530
     * @return An array pointer to MSTI configuration messages. Returns NULL if there is no MSTI
531
     * message.
532
     */
533
    msti_conf_msg *getMstiConfMessages() const;
534
535
    // overridden methods
536
537
    /**
538
     * @return Returns the protocol info as readable string
539
     */
540
0
    std::string toString() const { return "Multiple Spanning Tree"; }
541
542
    /**
543
     * A static method that validates the input data
544
     * @param[in] data The pointer to the beginning of a byte stream of an Multiple STP packet
545
     * @param[in] dataLen The length of the byte stream
546
     * @return True if the data is valid and can represent an Spanning Tree packet
547
     */
548
    static bool isDataValid(const uint8_t *data, size_t dataLen)
549
59
    {
550
59
      return data && dataLen >= sizeof(mstp_conf_bpdu);
551
59
    }
552
  };
553
} // namespace pcpp
554
555
#endif /* PACKETPP_STP_LAYER */