/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 |