/src/PcapPlusPlus/Packet++/src/StpLayer.cpp
Line | Count | Source |
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] = { 0 }; |
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 = reinterpret_cast<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 | { |
86 | 0 | constructNextLayer<PayloadLayer>(m_Data, m_DataLen - sizeof(stp_tcn_bpdu)); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | // ---------------------- Class StpConfigurationBPDULayer ---------------------- |
91 | 0 | StpConfigurationBPDULayer::StpConfigurationBPDULayer() : StpTopologyChangeBPDULayer(sizeof(stp_conf_bpdu)) |
92 | 0 | { |
93 | | // Set initial value for configuration BPDU |
94 | 0 | setProtoId(0x0); |
95 | 0 | setVersion(0x0); |
96 | 0 | setType(0x0); |
97 | 0 | } |
98 | | |
99 | | uint64_t StpConfigurationBPDULayer::getRootId() const |
100 | 0 | { |
101 | 0 | return be64toh(getStpConfHeader()->rootId); |
102 | 0 | } |
103 | | |
104 | | void StpConfigurationBPDULayer::setRootId(uint64_t value) |
105 | 0 | { |
106 | 0 | getStpConfHeader()->rootId = htobe64(value); |
107 | 0 | } |
108 | | |
109 | | uint16_t StpConfigurationBPDULayer::getRootPriority() const |
110 | 0 | { |
111 | 0 | return be16toh(getStpConfHeader()->rootId) & 0xf000; |
112 | 0 | } |
113 | | |
114 | | void StpConfigurationBPDULayer::setRootPriority(uint16_t value) |
115 | 0 | { |
116 | 0 | getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0xf000)) | htobe16(value & 0xf000); |
117 | 0 | } |
118 | | |
119 | | uint16_t StpConfigurationBPDULayer::getRootSystemIDExtension() const |
120 | 0 | { |
121 | 0 | return be16toh(getStpConfHeader()->rootId) & 0x0fff; |
122 | 0 | } |
123 | | |
124 | | void StpConfigurationBPDULayer::setRootSystemIDExtension(uint16_t value) |
125 | 0 | { |
126 | 0 | getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); |
127 | 0 | } |
128 | | |
129 | | void StpConfigurationBPDULayer::setRootSystemID(const pcpp::MacAddress& value) |
130 | 0 | { |
131 | 0 | setRootId((getRootId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); |
132 | 0 | }; |
133 | | |
134 | | uint32_t StpConfigurationBPDULayer::getPathCost() const |
135 | 0 | { |
136 | 0 | return be32toh(getStpConfHeader()->pathCost); |
137 | 0 | } |
138 | | |
139 | | void StpConfigurationBPDULayer::setPathCost(uint32_t value) |
140 | 0 | { |
141 | 0 | getStpConfHeader()->pathCost = htobe32(value); |
142 | 0 | } |
143 | | |
144 | | uint64_t StpConfigurationBPDULayer::getBridgeId() const |
145 | 0 | { |
146 | 0 | return be64toh(getStpConfHeader()->bridgeId); |
147 | 0 | } |
148 | | |
149 | | void StpConfigurationBPDULayer::setBridgeId(uint64_t value) |
150 | 0 | { |
151 | 0 | getStpConfHeader()->bridgeId = htobe64(value); |
152 | 0 | } |
153 | | |
154 | | uint16_t StpConfigurationBPDULayer::getBridgePriority() const |
155 | 0 | { |
156 | 0 | return be16toh(getStpConfHeader()->bridgeId) & 0xf000; |
157 | 0 | } |
158 | | |
159 | | void StpConfigurationBPDULayer::setBridgePriority(uint16_t value) |
160 | 0 | { |
161 | 0 | getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); |
162 | 0 | } |
163 | | |
164 | | uint16_t StpConfigurationBPDULayer::getBridgeSystemIDExtension() const |
165 | 0 | { |
166 | 0 | return be16toh(getStpConfHeader()->bridgeId) & 0x0fff; |
167 | 0 | } |
168 | | |
169 | | void StpConfigurationBPDULayer::setBridgeSystemIDExtension(uint16_t value) |
170 | 0 | { |
171 | 0 | getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); |
172 | 0 | } |
173 | | |
174 | | void StpConfigurationBPDULayer::setBridgeSystemID(const pcpp::MacAddress& value) |
175 | 0 | { |
176 | 0 | setBridgeId((getBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); |
177 | 0 | } |
178 | | |
179 | | uint16_t StpConfigurationBPDULayer::getPortId() const |
180 | 0 | { |
181 | 0 | return be16toh(getStpConfHeader()->portId); |
182 | 0 | } |
183 | | |
184 | | void StpConfigurationBPDULayer::setPortId(uint16_t value) |
185 | 0 | { |
186 | 0 | getStpConfHeader()->portId = htobe16(value); |
187 | 0 | } |
188 | | |
189 | | double StpConfigurationBPDULayer::getMessageAge() const |
190 | 0 | { |
191 | 0 | return getStpConfHeader()->msgAge; |
192 | 0 | } |
193 | | |
194 | | void StpConfigurationBPDULayer::setMessageAge(double value) |
195 | 0 | { |
196 | 0 | getStpConfHeader()->msgAge = value; |
197 | 0 | } |
198 | | |
199 | | double StpConfigurationBPDULayer::getMaximumAge() const |
200 | 0 | { |
201 | 0 | return getStpConfHeader()->maxAge; |
202 | 0 | } |
203 | | |
204 | | void StpConfigurationBPDULayer::setMaximumAge(double value) |
205 | 0 | { |
206 | 0 | getStpConfHeader()->maxAge = value; |
207 | 0 | } |
208 | | |
209 | | double StpConfigurationBPDULayer::getTransmissionInterval() const |
210 | 0 | { |
211 | 0 | return getStpConfHeader()->helloTime; |
212 | 0 | } |
213 | | |
214 | | void StpConfigurationBPDULayer::setTransmissionInterval(double value) |
215 | 0 | { |
216 | 0 | getStpConfHeader()->helloTime = value; |
217 | 0 | } |
218 | | |
219 | | double StpConfigurationBPDULayer::getForwardDelay() const |
220 | 0 | { |
221 | 0 | return getStpConfHeader()->forwardDelay; |
222 | 0 | } |
223 | | |
224 | | void StpConfigurationBPDULayer::setForwardDelay(double value) |
225 | 0 | { |
226 | 0 | getStpConfHeader()->forwardDelay = value; |
227 | 0 | } |
228 | | |
229 | | void StpConfigurationBPDULayer::parseNextLayer() |
230 | 0 | { |
231 | 0 | if (m_DataLen > sizeof(stp_conf_bpdu)) |
232 | 0 | { |
233 | 0 | constructNextLayer<PayloadLayer>(m_Data, m_DataLen - sizeof(stp_conf_bpdu)); |
234 | 0 | } |
235 | 0 | } |
236 | | |
237 | | // ---------------------- Class RapidStpLayer ---------------------- |
238 | 0 | RapidStpLayer::RapidStpLayer() : StpConfigurationBPDULayer(sizeof(rstp_conf_bpdu)) |
239 | 0 | { |
240 | | // Set initial value for Rapid STP |
241 | 0 | setProtoId(0x0); |
242 | 0 | setVersion(0x2); |
243 | 0 | setType(0x2); |
244 | 0 | } |
245 | | |
246 | | void RapidStpLayer::parseNextLayer() |
247 | 0 | { |
248 | 0 | if (m_DataLen > sizeof(rstp_conf_bpdu)) |
249 | 0 | { |
250 | 0 | constructNextLayer<PayloadLayer>(m_Data, m_DataLen - sizeof(rstp_conf_bpdu)); |
251 | 0 | } |
252 | 0 | } |
253 | | |
254 | | // ---------------------- Class MultipleStpLayer ---------------------- |
255 | 0 | MultipleStpLayer::MultipleStpLayer() : RapidStpLayer(sizeof(mstp_conf_bpdu)) |
256 | 0 | { |
257 | | // Set initial value for Multiple STP |
258 | 0 | setProtoId(0x0); |
259 | 0 | setVersion(0x3); |
260 | 0 | setType(0x2); |
261 | 0 | } |
262 | | |
263 | | uint16_t MultipleStpLayer::getVersion3Len() const |
264 | 0 | { |
265 | 0 | return be16toh(getMstpHeader()->version3Len); |
266 | 0 | } |
267 | | |
268 | | void MultipleStpLayer::setVersion3Len(uint16_t value) |
269 | 0 | { |
270 | 0 | getMstpHeader()->version3Len = htobe16(value); |
271 | 0 | } |
272 | | |
273 | | uint32_t MultipleStpLayer::getCISTIrpc() const |
274 | 0 | { |
275 | 0 | return be32toh(getMstpHeader()->irpc); |
276 | 0 | } |
277 | | |
278 | | void MultipleStpLayer::setCISTIrpc(uint32_t value) |
279 | 0 | { |
280 | 0 | getMstpHeader()->irpc = htobe32(value); |
281 | 0 | } |
282 | | |
283 | | uint64_t MultipleStpLayer::getCISTBridgeId() const |
284 | 0 | { |
285 | 0 | return be64toh(getMstpHeader()->cistBridgeId); |
286 | 0 | } |
287 | | |
288 | | void MultipleStpLayer::setCISTBridgeId(uint64_t value) |
289 | 0 | { |
290 | 0 | getMstpHeader()->cistBridgeId = htobe64(value); |
291 | 0 | } |
292 | | |
293 | | uint16_t MultipleStpLayer::getCISTBridgePriority() const |
294 | 0 | { |
295 | 0 | return be16toh(getMstpHeader()->cistBridgeId) & 0xf000; |
296 | 0 | } |
297 | | |
298 | | void MultipleStpLayer::setCISTBridgePriority(uint16_t value) |
299 | 0 | { |
300 | 0 | getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); |
301 | 0 | } |
302 | | |
303 | | uint16_t MultipleStpLayer::getCISTBridgeSystemIDExtension() const |
304 | 0 | { |
305 | 0 | return be16toh(getMstpHeader()->cistBridgeId) & 0x0fff; |
306 | 0 | } |
307 | | |
308 | | void MultipleStpLayer::setCISTBridgeSystemIDExtension(uint16_t value) |
309 | 0 | { |
310 | 0 | getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); |
311 | 0 | } |
312 | | |
313 | | void MultipleStpLayer::setCISTBridgeSystemID(const pcpp::MacAddress& value) |
314 | 0 | { |
315 | 0 | setCISTBridgeId((getCISTBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); |
316 | 0 | } |
317 | | |
318 | | std::string MultipleStpLayer::getMstConfigurationName() const |
319 | 0 | { |
320 | 0 | std::string str = std::string(reinterpret_cast<char*>(getMstpHeader()->mstConfigName), 32); |
321 | 0 | str.erase(std::find(str.begin(), str.end(), '\0'), str.end()); |
322 | 0 | return str; |
323 | 0 | } |
324 | | |
325 | | uint16_t MultipleStpLayer::getMstConfigRevision() const |
326 | 0 | { |
327 | 0 | return be16toh(getMstpHeader()->mstConfigRevision); |
328 | 0 | } |
329 | | |
330 | | void MultipleStpLayer::setMstConfigRevision(uint16_t value) |
331 | 0 | { |
332 | 0 | getMstpHeader()->mstConfigRevision = htobe16(value); |
333 | 0 | } |
334 | | |
335 | | void MultipleStpLayer::setMstConfigDigest(const uint8_t* value, uint8_t len) |
336 | 0 | { |
337 | 0 | memset(getMstpHeader()->mstConfigDigest, 0, 16); |
338 | 0 | memcpy(getMstpHeader()->mstConfigDigest, value, std::min<size_t>(len, 16)); |
339 | 0 | } |
340 | | |
341 | | void MultipleStpLayer::setMstConfigurationName(const std::string& value) |
342 | 0 | { |
343 | 0 | memset(getMstpHeader()->mstConfigName, 0, 32); |
344 | 0 | memcpy(getMstpHeader()->mstConfigName, value.c_str(), std::min<size_t>(value.size(), 32)); |
345 | 0 | } |
346 | | |
347 | | msti_conf_msg* MultipleStpLayer::getMstiConfMessages() const |
348 | 0 | { |
349 | 0 | if (getNumberOfMSTIConfMessages()) |
350 | 0 | return reinterpret_cast<msti_conf_msg*>(m_Data + sizeof(mstp_conf_bpdu)); |
351 | 0 | return nullptr; |
352 | 0 | } |
353 | | |
354 | | } // namespace pcpp |