/src/PcapPlusPlus/Packet++/src/SomeIpLayer.cpp
Line | Count | Source |
1 | | #define LOG_MODULE PacketLogModuleSomeIpLayer |
2 | | |
3 | | #include "SomeIpLayer.h" |
4 | | #include "SomeIpSdLayer.h" |
5 | | #include "Packet.h" |
6 | | #include "PayloadLayer.h" |
7 | | #include "EndianPortable.h" |
8 | | #include <algorithm> |
9 | | #include <sstream> |
10 | | |
11 | | namespace pcpp |
12 | | { |
13 | | |
14 | | // SomeIpLayer |
15 | | |
16 | | void splitUint32Id(uint32_t uint32Id, uint16_t& uint16IdUpper, uint16_t& uint16IdLower) |
17 | 0 | { |
18 | 0 | uint16IdLower = (uint32Id & 0x0000ffff); |
19 | 0 | uint16IdUpper = (uint32Id & 0xffff0000) >> 16; |
20 | 0 | } |
21 | | |
22 | | std::unordered_set<uint16_t> SomeIpLayer::m_SomeIpPorts{}; |
23 | | |
24 | | SomeIpLayer::SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, |
25 | | uint8_t interfaceVersion, MsgType type, uint8_t returnCode, const uint8_t* const data, |
26 | | size_t dataLen) |
27 | 0 | { |
28 | 0 | const size_t headerLen = sizeof(someiphdr); |
29 | 0 | m_DataLen = headerLen + dataLen; |
30 | 0 | m_Data = new uint8_t[m_DataLen]; |
31 | 0 | m_Protocol = SomeIP; |
32 | 0 | memset(m_Data, 0, headerLen); |
33 | 0 | memcpy(m_Data + headerLen, data, dataLen); |
34 | |
|
35 | 0 | setServiceID(serviceID); |
36 | 0 | setMethodID(methodID); |
37 | 0 | setPayloadLength((uint32_t)dataLen); |
38 | 0 | setClientID(clientID); |
39 | 0 | setSessionID(sessionID); |
40 | 0 | setProtocolVersion(0x01); |
41 | 0 | setInterfaceVersion(interfaceVersion); |
42 | 0 | setMessageType(type); |
43 | 0 | setReturnCode(returnCode); |
44 | 0 | } |
45 | | |
46 | | Layer* SomeIpLayer::parseSomeIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
47 | 125k | { |
48 | | // Ideas taken from wireshark some ip dissector |
49 | 125k | const size_t headerLen = sizeof(someiphdr); |
50 | 125k | if (dataLen < headerLen) |
51 | 17.4k | return new PayloadLayer(data, dataLen, prevLayer, packet); |
52 | | |
53 | 107k | uint32_t lengthBE = 0; |
54 | 107k | memcpy(&lengthBE, data + sizeof(uint32_t), sizeof(uint32_t)); // length field in SOME/IP header |
55 | 107k | uint32_t length = be32toh(lengthBE); |
56 | 107k | if ((length < 8) || (length > dataLen - 8)) |
57 | 5.57k | return new PayloadLayer(data, dataLen, prevLayer, packet); |
58 | | |
59 | 102k | if (data[12] != SOMEIP_PROTOCOL_VERSION) |
60 | 257 | return new PayloadLayer(data, dataLen, prevLayer, packet); |
61 | | |
62 | 102k | someiphdr* hdr = (someiphdr*)data; |
63 | | |
64 | 102k | switch (static_cast<MsgType>(hdr->msgType & ~(uint8_t)MsgType::TP_REQUEST)) |
65 | 102k | { |
66 | 1.91k | case MsgType::REQUEST: |
67 | 1.94k | case MsgType::REQUEST_ACK: |
68 | 49.2k | case MsgType::REQUEST_NO_RETURN: |
69 | 49.2k | case MsgType::REQUEST_NO_RETURN_ACK: |
70 | 97.2k | case MsgType::NOTIFICATION: |
71 | 97.4k | case MsgType::NOTIFICATION_ACK: |
72 | 98.4k | case MsgType::RESPONSE: |
73 | 98.4k | case MsgType::RESPONSE_ACK: |
74 | 98.5k | case MsgType::ERRORS: |
75 | 101k | case MsgType::ERROR_ACK: |
76 | 101k | break; |
77 | 132 | default: |
78 | 132 | return new PayloadLayer(data, dataLen, prevLayer, packet); |
79 | 102k | } |
80 | | |
81 | 101k | if (be16toh(hdr->serviceID) == 0xFFFF && be16toh(hdr->methodID) == 0x8100 && |
82 | 94.8k | SomeIpSdLayer::isDataValid(data, dataLen)) |
83 | 74.8k | { |
84 | 74.8k | return new SomeIpSdLayer(data, dataLen, prevLayer, packet); |
85 | 74.8k | } |
86 | 27.0k | else if ((hdr->msgType & (uint8_t)SomeIpLayer::MsgType::TP_REQUEST) != 0) |
87 | 2.86k | { |
88 | 2.86k | return new SomeIpTpLayer(data, dataLen, prevLayer, packet); |
89 | 2.86k | } |
90 | 24.1k | else |
91 | 24.1k | { |
92 | 24.1k | return new SomeIpLayer(data, dataLen, prevLayer, packet); |
93 | 24.1k | } |
94 | 101k | } |
95 | | |
96 | | bool SomeIpLayer::isSomeIpPort(uint16_t port) |
97 | 1.19M | { |
98 | 1.19M | return SomeIpSdLayer::isSomeIpSdPort(port) || |
99 | 1.08M | std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), |
100 | 1.08M | [&](const uint16_t& someIpPort) { return someIpPort == port; }); |
101 | 1.19M | } |
102 | | |
103 | | void SomeIpLayer::addSomeIpPort(uint16_t port) |
104 | 0 | { |
105 | 0 | m_SomeIpPorts.insert(port); |
106 | 0 | } |
107 | | |
108 | | void SomeIpLayer::removeSomeIpPort(uint16_t port) |
109 | 0 | { |
110 | 0 | m_SomeIpPorts.erase(port); |
111 | 0 | } |
112 | | |
113 | | void SomeIpLayer::removeAllSomeIpPorts() |
114 | 0 | { |
115 | 0 | m_SomeIpPorts.clear(); |
116 | 0 | } |
117 | | |
118 | | uint32_t SomeIpLayer::getMessageID() const |
119 | 0 | { |
120 | 0 | someiphdr* hdr = getSomeIpHeader(); |
121 | |
|
122 | 0 | return ((uint32_t)be16toh(hdr->serviceID) << 16) + be16toh(hdr->methodID); |
123 | 0 | } |
124 | | |
125 | | void SomeIpLayer::setMessageID(uint32_t messageID) |
126 | 0 | { |
127 | 0 | uint16_t methodID; |
128 | 0 | uint16_t serviceID; |
129 | |
|
130 | 0 | splitUint32Id(messageID, serviceID, methodID); |
131 | |
|
132 | 0 | someiphdr* hdr = getSomeIpHeader(); |
133 | 0 | hdr->serviceID = htobe16(serviceID); |
134 | 0 | hdr->methodID = htobe16(methodID); |
135 | 0 | } |
136 | | |
137 | | uint16_t SomeIpLayer::getServiceID() const |
138 | 9.29k | { |
139 | 9.29k | return be16toh(getSomeIpHeader()->serviceID); |
140 | 9.29k | } |
141 | | |
142 | | void SomeIpLayer::setServiceID(uint16_t serviceID) |
143 | 0 | { |
144 | 0 | getSomeIpHeader()->serviceID = htobe16(serviceID); |
145 | 0 | } |
146 | | |
147 | | uint16_t SomeIpLayer::getMethodID() const |
148 | 9.29k | { |
149 | 9.29k | return be16toh(getSomeIpHeader()->methodID); |
150 | 9.29k | } |
151 | | |
152 | | void SomeIpLayer::setMethodID(uint16_t methodID) |
153 | 0 | { |
154 | 0 | getSomeIpHeader()->methodID = htobe16(methodID); |
155 | 0 | } |
156 | | |
157 | | uint32_t SomeIpLayer::getLengthField() const |
158 | 129k | { |
159 | 129k | return be32toh(getSomeIpHeader()->length); |
160 | 129k | } |
161 | | |
162 | | uint32_t SomeIpLayer::getRequestID() const |
163 | 0 | { |
164 | 0 | someiphdr* hdr = getSomeIpHeader(); |
165 | |
|
166 | 0 | return ((uint32_t)be16toh(hdr->clientID) << 16) + be16toh(hdr->sessionID); |
167 | 0 | } |
168 | | |
169 | | void SomeIpLayer::setRequestID(uint32_t requestID) |
170 | 0 | { |
171 | 0 | uint16_t clientID; |
172 | 0 | uint16_t sessionID; |
173 | |
|
174 | 0 | splitUint32Id(requestID, clientID, sessionID); |
175 | |
|
176 | 0 | someiphdr* hdr = getSomeIpHeader(); |
177 | 0 | hdr->clientID = htobe16(clientID); |
178 | 0 | hdr->sessionID = htobe16(sessionID); |
179 | 0 | } |
180 | | |
181 | | uint16_t SomeIpLayer::getClientID() const |
182 | 0 | { |
183 | 0 | return be16toh(getSomeIpHeader()->clientID); |
184 | 0 | } |
185 | | |
186 | | void SomeIpLayer::setClientID(uint16_t clientID) |
187 | 0 | { |
188 | 0 | getSomeIpHeader()->clientID = htobe16(clientID); |
189 | 0 | } |
190 | | |
191 | | uint16_t SomeIpLayer::getSessionID() const |
192 | 0 | { |
193 | 0 | return be16toh(getSomeIpHeader()->sessionID); |
194 | 0 | } |
195 | | |
196 | | void SomeIpLayer::setSessionID(uint16_t sessionID) |
197 | 0 | { |
198 | 0 | getSomeIpHeader()->sessionID = htobe16(sessionID); |
199 | 0 | } |
200 | | |
201 | | uint8_t SomeIpLayer::getProtocolVersion() const |
202 | 0 | { |
203 | 0 | return getSomeIpHeader()->protocolVersion; |
204 | 0 | } |
205 | | |
206 | | void SomeIpLayer::setProtocolVersion(uint8_t version) |
207 | 0 | { |
208 | 0 | getSomeIpHeader()->protocolVersion = version; |
209 | 0 | } |
210 | | |
211 | | uint8_t SomeIpLayer::getInterfaceVersion() const |
212 | 0 | { |
213 | 0 | return getSomeIpHeader()->interfaceVersion; |
214 | 0 | } |
215 | | |
216 | | void SomeIpLayer::setInterfaceVersion(uint8_t version) |
217 | 0 | { |
218 | 0 | getSomeIpHeader()->interfaceVersion = version; |
219 | 0 | } |
220 | | |
221 | | SomeIpLayer::MsgType SomeIpLayer::getMessageType() const |
222 | 0 | { |
223 | 0 | return static_cast<SomeIpLayer::MsgType>(getSomeIpHeader()->msgType); |
224 | 0 | } |
225 | | |
226 | | uint8_t SomeIpLayer::getMessageTypeAsInt() const |
227 | 368 | { |
228 | 368 | return getSomeIpHeader()->msgType; |
229 | 368 | } |
230 | | |
231 | | void SomeIpLayer::setMessageType(MsgType type) |
232 | 0 | { |
233 | 0 | setMessageType(static_cast<uint8_t>(type)); |
234 | 0 | } |
235 | | |
236 | | void SomeIpLayer::setMessageType(uint8_t type) |
237 | 368 | { |
238 | 368 | getSomeIpHeader()->msgType = type; |
239 | 368 | } |
240 | | |
241 | | uint8_t SomeIpLayer::getReturnCode() const |
242 | 0 | { |
243 | 0 | return getSomeIpHeader()->returnCode; |
244 | 0 | } |
245 | | |
246 | | void SomeIpLayer::setReturnCode(uint8_t returnCode) |
247 | 0 | { |
248 | 0 | getSomeIpHeader()->returnCode = returnCode; |
249 | 0 | } |
250 | | |
251 | | void SomeIpLayer::setPayloadLength(uint32_t payloadLength) |
252 | 0 | { |
253 | 0 | someiphdr* hdr = getSomeIpHeader(); |
254 | 0 | hdr->length = htobe32(sizeof(someiphdr) - sizeof(hdr->serviceID) - sizeof(hdr->methodID) - sizeof(hdr->length) + |
255 | 0 | payloadLength); |
256 | 0 | } |
257 | | |
258 | | void SomeIpLayer::parseNextLayer() |
259 | 101k | { |
260 | 101k | size_t headerLen = getHeaderLen(); |
261 | 101k | if (m_DataLen <= headerLen) |
262 | 80.4k | return; |
263 | | |
264 | 21.4k | uint8_t* payload = m_Data + headerLen; |
265 | 21.4k | size_t payloadLen = m_DataLen - headerLen; |
266 | | |
267 | 21.4k | constructNextLayerFromFactory(parseSomeIpLayer, payload, payloadLen); |
268 | 21.4k | } |
269 | | |
270 | | std::string SomeIpLayer::toString() const |
271 | 8.55k | { |
272 | 8.55k | std::stringstream dataStream; |
273 | | |
274 | 8.55k | dataStream << "SOME/IP Layer" << std::hex << ", Service ID: 0x" << getServiceID() << ", Method ID: 0x" |
275 | 8.55k | << getMethodID() << std::dec << ", Length: " << getLengthField(); |
276 | | |
277 | 8.55k | return dataStream.str(); |
278 | 8.55k | } |
279 | | |
280 | | // SomeIpTpLayer |
281 | | |
282 | | SomeIpTpLayer::SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, |
283 | | uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, |
284 | | bool moreSegmentsFlag, const uint8_t* const data, size_t dataLen) |
285 | 0 | { |
286 | 0 | const size_t headerLen = sizeof(someiptphdr); |
287 | |
|
288 | 0 | m_DataLen = headerLen + dataLen; |
289 | 0 | m_Data = new uint8_t[m_DataLen]; |
290 | 0 | m_Protocol = SomeIP; |
291 | 0 | memset(m_Data, 0, headerLen); |
292 | 0 | memcpy(m_Data + headerLen, data, dataLen); |
293 | |
|
294 | 0 | setServiceID(serviceID); |
295 | 0 | setMethodID(methodID); |
296 | 0 | setPayloadLength((uint32_t)(dataLen + sizeof(uint32_t))); |
297 | 0 | setClientID(clientID); |
298 | 0 | setSessionID(sessionID); |
299 | 0 | setProtocolVersion(0x01); |
300 | 0 | setInterfaceVersion(interfaceVersion); |
301 | 0 | setMessageType(setTpFlag((uint8_t)type)); |
302 | 0 | setReturnCode(returnCode); |
303 | 0 | setOffset(offset); |
304 | 0 | setMoreSegmentsFlag(moreSegmentsFlag); |
305 | 0 | } |
306 | | |
307 | | uint32_t SomeIpTpLayer::getOffset() const |
308 | 0 | { |
309 | 0 | return (be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_OFFSET_MASK); |
310 | 0 | } |
311 | | |
312 | | void SomeIpTpLayer::setOffset(uint32_t offset) |
313 | 0 | { |
314 | 0 | if ((offset & SOMEIP_TP_OFFSET_MASK) != offset) |
315 | 0 | { |
316 | 0 | throw std::invalid_argument("Invalid offset - should be a multiple of 16"); |
317 | 0 | } |
318 | | |
319 | 0 | uint32_t val = |
320 | 0 | (offset & SOMEIP_TP_OFFSET_MASK) | (be32toh(getSomeIpTpHeader()->offsetAndFlag) & ~SOMEIP_TP_OFFSET_MASK); |
321 | 0 | getSomeIpTpHeader()->offsetAndFlag = htobe32(val); |
322 | 0 | } |
323 | | |
324 | | bool SomeIpTpLayer::getMoreSegmentsFlag() const |
325 | 0 | { |
326 | 0 | return be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_MORE_FLAG_MASK; |
327 | 0 | } |
328 | | |
329 | | void SomeIpTpLayer::setMoreSegmentsFlag(bool flag) |
330 | 0 | { |
331 | 0 | uint32_t val = be32toh(getSomeIpTpHeader()->offsetAndFlag); |
332 | |
|
333 | 0 | if (flag) |
334 | 0 | { |
335 | 0 | val = val | SOMEIP_TP_MORE_FLAG_MASK; |
336 | 0 | } |
337 | 0 | else |
338 | 0 | { |
339 | 0 | val = val & ~SOMEIP_TP_MORE_FLAG_MASK; |
340 | 0 | } |
341 | |
|
342 | 0 | getSomeIpTpHeader()->offsetAndFlag = htobe32(val); |
343 | 0 | } |
344 | | |
345 | | void SomeIpTpLayer::computeCalculateFields() |
346 | 368 | { |
347 | 368 | setMessageType(setTpFlag(getMessageTypeAsInt())); |
348 | 368 | } |
349 | | |
350 | | std::string SomeIpTpLayer::toString() const |
351 | 736 | { |
352 | 736 | std::stringstream dataStream; |
353 | | |
354 | 736 | dataStream << "SOME/IP-TP Layer" << std::hex << ", Service ID: 0x" << getServiceID() << ", Method ID: 0x" |
355 | 736 | << getMethodID() << std::dec << ", Length: " << getLengthField(); |
356 | | |
357 | 736 | return dataStream.str(); |
358 | 736 | } |
359 | | |
360 | | uint8_t SomeIpTpLayer::setTpFlag(uint8_t messageType) |
361 | 368 | { |
362 | 368 | return messageType | (uint8_t)SomeIpLayer::MsgType::TP_REQUEST; |
363 | 368 | } |
364 | | } // namespace pcpp |