Coverage Report

Created: 2023-01-17 06:15

/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