/src/PcapPlusPlus/Packet++/src/SomeIpLayer.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include <string.h> |
11 | | |
12 | | namespace pcpp |
13 | | { |
14 | | |
15 | | // SomeIpLayer |
16 | | |
17 | | void splitUint32Id(uint32_t uint32Id, uint16_t &uint16IdUpper, uint16_t &uint16IdLower) |
18 | 0 | { |
19 | 0 | uint16IdLower = (uint32Id & 0x0000ffff); |
20 | 0 | uint16IdUpper = (uint32Id & 0xffff0000) >> 16; |
21 | 0 | } |
22 | | |
23 | | std::unordered_set<uint16_t> SomeIpLayer::m_SomeIpPorts{}; |
24 | | |
25 | | SomeIpLayer::SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, |
26 | | uint8_t interfaceVersion, MsgType type, uint8_t returnCode, const uint8_t *const data, |
27 | | size_t dataLen) |
28 | 0 | { |
29 | 0 | const size_t headerLen = sizeof(someiphdr); |
30 | 0 | m_DataLen = headerLen + dataLen; |
31 | 0 | m_Data = new uint8_t[m_DataLen]; |
32 | 0 | m_Protocol = SomeIP; |
33 | 0 | memset(m_Data, 0, headerLen); |
34 | 0 | memcpy(m_Data + headerLen, data, dataLen); |
35 | |
|
36 | 0 | setServiceID(serviceID); |
37 | 0 | setMethodID(methodID); |
38 | 0 | setPayloadLength((uint32_t)dataLen); |
39 | 0 | setClientID(clientID); |
40 | 0 | setSessionID(sessionID); |
41 | 0 | setProtocolVersion(0x01); |
42 | 0 | setInterfaceVersion(interfaceVersion); |
43 | 0 | setMessageType(type); |
44 | 0 | setReturnCode(returnCode); |
45 | 0 | } |
46 | | |
47 | | Layer* SomeIpLayer::parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevLayer, Packet* packet) |
48 | 7.22k | { |
49 | | /* Ideas taken from wireshark some ip dissector */ |
50 | 7.22k | const size_t headerLen = sizeof(someiphdr); |
51 | 7.22k | if (dataLen < headerLen) |
52 | 1.05k | return new PayloadLayer(data, dataLen, prevLayer, packet); |
53 | | |
54 | 6.17k | uint32_t lengthBE = 0; |
55 | 6.17k | memcpy(&lengthBE, data + sizeof(uint32_t), sizeof(uint32_t)); // length field in SOME/IP header |
56 | 6.17k | uint32_t length = be32toh(lengthBE); |
57 | 6.17k | if ((length < 8) || (length > dataLen - 8)) |
58 | 1.34k | return new PayloadLayer(data, dataLen, prevLayer, packet); |
59 | | |
60 | 4.82k | if (data[12] != SOMEIP_PROTOCOL_VERSION) |
61 | 425 | return new PayloadLayer(data, dataLen, prevLayer, packet); |
62 | | |
63 | 4.40k | someiphdr *hdr = (someiphdr *)data; |
64 | | |
65 | 4.40k | switch (static_cast<MsgType>(hdr->msgType & ~(uint8_t)MsgType::TP_REQUEST)) |
66 | 4.40k | { |
67 | 182 | case MsgType::REQUEST: |
68 | 714 | case MsgType::REQUEST_ACK: |
69 | 1.00k | case MsgType::REQUEST_NO_RETURN: |
70 | 1.52k | case MsgType::REQUEST_NO_RETURN_ACK: |
71 | 2.21k | case MsgType::NOTIFICATION: |
72 | 2.55k | case MsgType::NOTIFICATION_ACK: |
73 | 3.20k | case MsgType::RESPONSE: |
74 | 3.81k | case MsgType::RESPONSE_ACK: |
75 | 3.92k | case MsgType::ERRORS: |
76 | 4.33k | case MsgType::ERROR_ACK: |
77 | 4.33k | break; |
78 | 71 | default: |
79 | 71 | return new PayloadLayer(data, dataLen, prevLayer, packet); |
80 | 4.40k | } |
81 | | |
82 | 4.33k | if (be16toh(hdr->serviceID) == 0xFFFF && be16toh(hdr->methodID) == 0x8100) |
83 | 73 | { |
84 | 73 | return new SomeIpSdLayer(data, dataLen, prevLayer, packet); |
85 | 73 | } |
86 | 4.25k | else if ((hdr->msgType & (uint8_t)SomeIpLayer::MsgType::TP_REQUEST) != 0) |
87 | 2.31k | { |
88 | 2.31k | return new SomeIpTpLayer(data, dataLen, prevLayer, packet); |
89 | 2.31k | } |
90 | 1.94k | else |
91 | 1.94k | { |
92 | 1.94k | return new SomeIpLayer(data, dataLen, prevLayer, packet); |
93 | 1.94k | } |
94 | 4.33k | } |
95 | | |
96 | | bool SomeIpLayer::isSomeIpPort(uint16_t port) |
97 | 204k | { |
98 | 204k | return SomeIpSdLayer::isSomeIpSdPort(port) || |
99 | 204k | std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), |
100 | 200k | [&](const uint16_t &someIpPort) { return someIpPort == port; }); |
101 | 204k | } |
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 | 0 | { |
139 | 0 | return be16toh(getSomeIpHeader()->serviceID); |
140 | 0 | } |
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 | 0 | { |
149 | 0 | return be16toh(getSomeIpHeader()->methodID); |
150 | 0 | } |
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 | 4.33k | { |
159 | 4.33k | return be32toh(getSomeIpHeader()->length); |
160 | 4.33k | } |
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 | 0 | { |
228 | 0 | return getSomeIpHeader()->msgType; |
229 | 0 | } |
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 | 0 | { |
238 | 0 | getSomeIpHeader()->msgType = type; |
239 | 0 | } |
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 | 4.33k | { |
260 | 4.33k | size_t headerLen = getHeaderLen(); |
261 | 4.33k | if (m_DataLen <= headerLen) |
262 | 1.01k | return; |
263 | | |
264 | 3.31k | uint8_t *payload = m_Data + headerLen; |
265 | 3.31k | size_t payloadLen = m_DataLen - headerLen; |
266 | | |
267 | 3.31k | m_NextLayer = parseSomeIpLayer(payload, payloadLen, this, m_Packet); |
268 | 3.31k | } |
269 | | |
270 | | std::string SomeIpLayer::toString() const |
271 | 0 | { |
272 | 0 | std::stringstream dataStream; |
273 | |
|
274 | 0 | dataStream << "SOME/IP Layer" |
275 | 0 | << std::hex |
276 | 0 | << ", Service ID: 0x" << getServiceID() |
277 | 0 | << ", Method ID: 0x" << getMethodID() |
278 | 0 | << std::dec |
279 | 0 | << ", Length: " << getLengthField(); |
280 | |
|
281 | 0 | return dataStream.str(); |
282 | 0 | } |
283 | | |
284 | | // SomeIpTpLayer |
285 | | |
286 | | SomeIpTpLayer::SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, |
287 | | uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, |
288 | | bool moreSegmentsFlag, const uint8_t *const data, size_t dataLen) |
289 | 0 | { |
290 | 0 | const size_t headerLen = sizeof(someiptphdr); |
291 | |
|
292 | 0 | m_DataLen = headerLen + dataLen; |
293 | 0 | m_Data = new uint8_t[m_DataLen]; |
294 | 0 | m_Protocol = SomeIP; |
295 | 0 | memset(m_Data, 0, headerLen); |
296 | 0 | memcpy(m_Data + headerLen, data, dataLen); |
297 | |
|
298 | 0 | setServiceID(serviceID); |
299 | 0 | setMethodID(methodID); |
300 | 0 | setPayloadLength((uint32_t)(dataLen + sizeof(uint32_t))); |
301 | 0 | setClientID(clientID); |
302 | 0 | setSessionID(sessionID); |
303 | 0 | setProtocolVersion(0x01); |
304 | 0 | setInterfaceVersion(interfaceVersion); |
305 | 0 | setMessageType(setTpFlag((uint8_t)type)); |
306 | 0 | setReturnCode(returnCode); |
307 | 0 | setOffset(offset); |
308 | 0 | setMoreSegmentsFlag(moreSegmentsFlag); |
309 | 0 | } |
310 | | |
311 | | uint32_t SomeIpTpLayer::getOffset() const |
312 | 0 | { |
313 | 0 | return (be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_OFFSET_MASK) >> 4; |
314 | 0 | } |
315 | | |
316 | | void SomeIpTpLayer::setOffset(uint32_t offset) |
317 | 0 | { |
318 | 0 | uint32_t val = (offset << 4) | (be32toh(getSomeIpTpHeader()->offsetAndFlag) & ~SOMEIP_TP_OFFSET_MASK); |
319 | 0 | getSomeIpTpHeader()->offsetAndFlag = htobe32(val); |
320 | 0 | } |
321 | | |
322 | | bool SomeIpTpLayer::getMoreSegmentsFlag() const |
323 | 0 | { |
324 | 0 | return be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_MORE_FLAG_MASK; |
325 | 0 | } |
326 | | |
327 | | void SomeIpTpLayer::setMoreSegmentsFlag(bool flag) |
328 | 0 | { |
329 | 0 | uint32_t val = be32toh(getSomeIpTpHeader()->offsetAndFlag); |
330 | |
|
331 | 0 | if (flag) |
332 | 0 | { |
333 | 0 | val = val | SOMEIP_TP_MORE_FLAG_MASK; |
334 | 0 | } |
335 | 0 | else |
336 | 0 | { |
337 | 0 | val = val & ~SOMEIP_TP_MORE_FLAG_MASK; |
338 | 0 | } |
339 | |
|
340 | 0 | getSomeIpTpHeader()->offsetAndFlag = htobe32(val); |
341 | 0 | } |
342 | | |
343 | | void SomeIpTpLayer::computeCalculateFields() |
344 | 0 | { |
345 | 0 | setMessageType(setTpFlag(getMessageTypeAsInt())); |
346 | 0 | } |
347 | | |
348 | | std::string SomeIpTpLayer::toString() const |
349 | 0 | { |
350 | 0 | std::stringstream dataStream; |
351 | |
|
352 | 0 | dataStream << "SOME/IP-TP Layer" |
353 | 0 | << std::hex |
354 | 0 | << ", Service ID: 0x" << getServiceID() |
355 | 0 | << ", Method ID: 0x" << getMethodID() |
356 | 0 | << std::dec |
357 | 0 | << ", Length: " << getLengthField(); |
358 | |
|
359 | 0 | return dataStream.str(); |
360 | 0 | } |
361 | | |
362 | | uint8_t SomeIpTpLayer::setTpFlag(uint8_t messageType) |
363 | 0 | { |
364 | 0 | return messageType | (uint8_t)SomeIpLayer::MsgType::TP_REQUEST; |
365 | 0 | } |
366 | | } // namespace pcpp |