Coverage Report

Created: 2026-02-26 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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