Coverage Report

Created: 2024-02-25 06:29

/src/PcapPlusPlus/Packet++/header/SomeIpLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "Layer.h"
4
#include <unordered_set>
5
6
/// @file
7
8
/**
9
 * \namespace pcpp
10
 * \brief The main namespace for the PcapPlusPlus lib
11
 */
12
namespace pcpp
13
{
14
15
/**
16
 * @class SomeIpLayer
17
 * Represents a SOME/IP protocol layer
18
 */
19
class SomeIpLayer : public Layer
20
{
21
public:
22
  /**
23
   * SOME/IP message types
24
   */
25
  enum class MsgType : uint8_t
26
  {
27
    /** A request expecting a response (even void) */
28
    REQUEST = 0x00,
29
    /** Acknowledgment for REQUEST(optional) */
30
    REQUEST_ACK = 0x40,
31
    /** A fire&forget request */
32
    REQUEST_NO_RETURN = 0x01,
33
    /** Acknowledgment for REQUEST_NO_RETURN(informational) */
34
    REQUEST_NO_RETURN_ACK = 0x41,
35
    /** A request of a notification expecting no response */
36
    NOTIFICATION = 0x02,
37
    /** Acknowledgment for NOTIFICATION(informational) */
38
    NOTIFICATION_ACK = 0x42,
39
    /** The response message */
40
    RESPONSE = 0x80,
41
    /** The Acknowledgment for RESPONSE(informational) */
42
    RESPONSE_ACK = 0xC0,
43
    /** The response containing an error */
44
    ERRORS = 0x81,
45
    /** Acknowledgment for ERROR(informational) */
46
    ERROR_ACK = 0xC1,
47
    /** A TP request expecting a response (even void) */
48
    TP_REQUEST = 0x20,
49
    /** A TP fire&forget request */
50
    TP_REQUEST_NO_RETURN = 0x21,
51
    /** A TP request of a notification/event callback expecting no response */
52
    TP_NOTIFICATION = 0x22,
53
    /** The TP response message */
54
    TP_RESPONSE = 0xa0,
55
    /** The TP response containing an error */
56
    TP_ERROR = 0xa1,
57
  };
58
59
  /**
60
   * @struct someiphdr
61
   * Represents a SOME/IP protocol header
62
   */
63
#pragma pack(push, 1)
64
  struct someiphdr
65
  {
66
    /** Service ID */
67
    uint16_t serviceID;
68
    /** Method ID. Most significant bit 0 when E2E communication. 1 when SOME/IP event */
69
    uint16_t methodID;
70
    /** Length. Also covers payload. Excludes serviceID, methodID and length field itself */
71
    uint32_t length;
72
    /** Client ID */
73
    uint16_t clientID;
74
    /** Session ID */
75
    uint16_t sessionID;
76
    /** Protocol Version */
77
    uint8_t protocolVersion;
78
    /** Interface Version */
79
    uint8_t interfaceVersion;
80
    /** Message Type */
81
    uint8_t msgType;
82
    /** Return Code */
83
    uint8_t returnCode;
84
  };
85
#pragma pack(pop)
86
87
  /**
88
   * A constructor that creates the layer from an existing packet raw data
89
   * @param[in] data A pointer to the raw data (will be casted to someiphdr)
90
   * @param[in] dataLen Size of the data in bytes
91
   * @param[in] prevLayer A pointer to the previous layer
92
   * @param[in] packet A pointer to the Packet instance where layer will be stored in
93
   */
94
  SomeIpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
95
    : Layer(data, dataLen, prevLayer, packet)
96
53.0k
  {
97
53.0k
    m_Protocol = SomeIP;
98
53.0k
  }
99
100
  /**
101
   * Construct a new layer object
102
   * @param[in] serviceID Service ID
103
   * @param[in] methodID Method ID
104
   * @param[in] clientID Client ID
105
   * @param[in] sessionID Session ID
106
   * @param[in] interfaceVersion Interface Version
107
   * @param[in] type Type of the message
108
   * @param[in] returnCode Return Code
109
   * @param[in] data A pointer to the raw data
110
   * @param[in] dataLen Size of the data in bytes
111
   * holds the reference to a data buffer. This option can be used to reduce the number of copies to generate packets.
112
   */
113
  SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, uint8_t interfaceVersion,
114
        MsgType type, uint8_t returnCode, const uint8_t *const data = nullptr, size_t dataLen = 0);
115
116
  /**
117
   * Destroy the layer object
118
   */
119
0
  ~SomeIpLayer() {}
120
121
  /**
122
   * A static method that creates a SOME/IP or SOME/IP-TP layer from packet raw data. Returns PayloadLayer if data is
123
   * not valid.
124
   * @param[in] data A pointer to the raw data
125
   * @param[in] dataLen Size of the data in bytes
126
   * @param[in] prevLayer A pointer to the previous layer
127
   * @param[in] packet A pointer to the Packet instance where layer will be stored
128
   * @return Layer* A newly allocated layer
129
   */
130
  static Layer* parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevLayer, Packet* packet);
131
132
  /**
133
   * Get a pointer to the basic SOME/IP header. Notice this points directly to the data, so every change will change
134
   * the actual packet data
135
   * @return A pointer to the someiphdr
136
   */
137
91.2k
  someiphdr *getSomeIpHeader() const { return (someiphdr *)m_Data; }
138
139
  /**
140
   * Checks if given port is a SOME/IP protocol port (only Service Discovery ports are checked for now)
141
   * @param[in] port Port to check
142
   * @return true if SOME/IP protocol port, false if not
143
   */
144
  static bool isSomeIpPort(uint16_t port);
145
146
  /**
147
   * Adds port to a list of ports where pcap checks for SOME/IP communication.
148
   * Each port must be removed at the end in order to have no memory leak.
149
   * @param[in] port Port to add
150
   */
151
  static void addSomeIpPort(uint16_t port);
152
153
  /**
154
   * Removes port from a list of ports where pcap checks for SOME/IP communication.
155
   * @param[in] port Port to remove
156
   */
157
  static void removeSomeIpPort(uint16_t port);
158
159
  /**
160
   * Removes all ports from a list of ports where pcap checks for SOME/IP communication.
161
   */
162
  static void removeAllSomeIpPorts();
163
164
  /**
165
   * Get the messageID
166
   * @return uint32_t returned in host endian
167
   */
168
  uint32_t getMessageID() const;
169
170
  /**
171
   * Set the Message ID
172
   * @param[in] messageID messageID to set
173
   */
174
  void setMessageID(uint32_t messageID);
175
176
  /**
177
   * Get the serviceID
178
   * @return uint16_t returned in host endian
179
   */
180
  uint16_t getServiceID() const;
181
182
  /**
183
   * Set the Service ID
184
   * @param[in] serviceID serviceID to set
185
   */
186
  void setServiceID(uint16_t serviceID);
187
188
  /**
189
   * Get the methodID
190
   * @return uint16_t returned in host endian
191
   */
192
  uint16_t getMethodID() const;
193
194
  /**
195
   * Set the Method ID
196
   * @param[in] methodID methodID to set
197
   */
198
  void setMethodID(uint16_t methodID);
199
200
  /**
201
   * Get the Length Field of the SOME/IP header
202
   * @return uint32_t The length field of the SOME/IP header
203
   */
204
  uint32_t getLengthField() const;
205
206
  /**
207
   * Get the requestID
208
   * @return uint32_t returned in host endian
209
   */
210
  uint32_t getRequestID() const;
211
212
  /**
213
   * Set the Request ID
214
   * @param[in] requestID requestID to set
215
   */
216
  void setRequestID(uint32_t requestID);
217
218
  /**
219
   * Get the sessionID
220
   * @return uint16_t returned in host endian
221
   */
222
  uint16_t getSessionID() const;
223
224
  /**
225
   * Set the Session ID
226
   * @param[in] sessionID sessionID to set
227
   */
228
  void setSessionID(uint16_t sessionID);
229
230
  /**
231
   * Get the clientID
232
   * @return uint16_t returned in host endian
233
   */
234
  uint16_t getClientID() const;
235
236
  /**
237
   * Set the Client ID
238
   * @param[in] clientID clientID to set
239
   */
240
  void setClientID(uint16_t clientID);
241
242
  /**
243
   * Get the protocolVersion
244
   * @return uint8_t
245
   */
246
  uint8_t getProtocolVersion() const;
247
248
  /**
249
   * Set the Protocol Version
250
   * @param[in] version version to set
251
   */
252
  void setProtocolVersion(uint8_t version);
253
254
  /**
255
   * Get the interfaceVersion
256
   * @return uint8_t
257
   */
258
  uint8_t getInterfaceVersion() const;
259
260
  /**
261
   * Set the Interface Version
262
   * @param[in] version version to set
263
   */
264
  void setInterfaceVersion(uint8_t version);
265
266
  /**
267
   * Get the message type
268
   * @return uint8_t
269
   */
270
  uint8_t getMessageTypeAsInt() const;
271
272
  /**
273
   * Get the message type
274
   * @return SomeIpLayer::MsgType
275
   */
276
  SomeIpLayer::MsgType getMessageType() const;
277
278
  /**
279
   * Set the Message Type
280
   * @param[in] type Type to set
281
   */
282
  void setMessageType(MsgType type);
283
284
  /**
285
   * Set the Message Type
286
   * @param[in] type Type to set
287
   */
288
  void setMessageType(uint8_t type);
289
290
  /**
291
   * Get the returnCode
292
   * @return uint8_t
293
   */
294
  uint8_t getReturnCode() const;
295
296
  /**
297
   * Set the returnCode
298
   * @param[in] returnCode ReturnCode to set
299
   */
300
  void setReturnCode(uint8_t returnCode);
301
302
  /**
303
   * Set the length field of the SOME/IP header
304
   * @param[in] payloadLength Length of the payload
305
   */
306
  void setPayloadLength(uint32_t payloadLength);
307
308
  /**
309
   * @return A pointer for the layer payload, meaning the first byte after the header
310
   */
311
0
  uint8_t *getPduPayload() const { return m_Data + getSomeIpHeaderLen(); }
312
313
  /**
314
   * @return The size in bytes of the payload
315
   */
316
0
  size_t getPduPayloadSize() const { return getHeaderLen() - getSomeIpHeaderLen(); }
317
318
  /**
319
   * Get the Length of the SOME/IP header inc payload
320
   * @return size_t
321
   */
322
61.0k
  size_t getHeaderLen() const { return sizeof(uint32_t) * 2 + getLengthField(); }
323
324
  /**
325
   * Does nothing for this layer
326
   */
327
2.49k
  virtual void computeCalculateFields() {}
328
329
  /**
330
   * Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer
331
   */
332
  void parseNextLayer();
333
334
  /**
335
   * @return The string representation of the SOME/IP layer
336
   */
337
  virtual std::string toString() const;
338
339
  /**
340
   * @return The OSI model layer of this layer
341
   */
342
7.99k
  OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
343
344
protected:
345
0
  SomeIpLayer() {}
346
347
private:
348
  static const uint8_t SOMEIP_PROTOCOL_VERSION = 1;
349
0
  virtual size_t getSomeIpHeaderLen() const { return sizeof(someiphdr); }
350
351
  /* Using unordered_set since insertion and search should be almost constant time */
352
  static std::unordered_set<uint16_t> m_SomeIpPorts;
353
};
354
355
/**
356
 * @class SomeIpTpLayer
357
 * Represents an SOME/IP Transport Protocol Layer
358
 */
359
class SomeIpTpLayer : public SomeIpLayer
360
{
361
public:
362
  /**
363
   * @struct someiptphdr
364
   * Represents an SOME/IP-TP protocol header.
365
   */
366
#pragma pack(push, 1)
367
  struct someiptphdr : someiphdr
368
  {
369
    /** Contains the offset and the more segments flag. 28 bit offset field measured in 16 bytes + 3 bit reserved +
370
     * 1 bit more segments flag */
371
    uint32_t offsetAndFlag;
372
  };
373
#pragma pack(pop)
374
375
  /**
376
   * A constructor that creates the layer from an existing packet raw data
377
   * @param[in] data A pointer to the raw data (will be casted to @ref someiptphdr)
378
   * @param[in] dataLen Size of the data in bytes
379
   * @param[in] prevLayer A pointer to the previous layer
380
   * @param[in] packet A pointer to the Packet instance where layer will be stored in
381
   */
382
  SomeIpTpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet)
383
11.5k
    : SomeIpLayer(data, dataLen, prevLayer, packet) {}
384
385
  /**
386
   * A constructor that creates empty layer and sets values
387
   * @param[in] serviceID Service ID
388
   * @param[in] methodID Method ID
389
   * @param[in] clientID Client ID
390
   * @param[in] sessionID Session ID
391
   * @param[in] interfaceVersion Interface Version
392
   * @param[in] type Type of the message
393
   * @param[in] returnCode Return Code
394
   * @param[in] offset Offset indicating the data offset in increments of 16 bytes
395
   * @param[in] moreSegmentsFlag Flag indicating whether more SOME/IP-TP Packets will follow
396
   * @param[in] data A pointer to the raw data
397
   * @param[in] dataLen Size of the data in bytes
398
   */
399
  SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID,
400
          uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, bool moreSegmentsFlag,
401
          const uint8_t *const data = nullptr, size_t dataLen = 0);
402
403
  /**
404
   * Destroy the layer object
405
   */
406
0
  ~SomeIpTpLayer() {}
407
408
  /**
409
   * Get a pointer to the basic SOME/IP-TP header. Notice this points directly to the data, so every change will
410
   * change the actual packet data
411
   * @return A pointer to the @ref someiptphdr
412
   */
413
0
  someiptphdr *getSomeIpTpHeader() const { return (someiptphdr *)m_Data; }
414
415
  /**
416
   * Get the Offset. Offset is returned in multiple of 16 bytes.
417
   * @return The offset value
418
   */
419
  uint32_t getOffset() const;
420
421
  /**
422
   * Set the Offset. Already has to be in multiples of 16 bytes.
423
   * If 32 bytes have already been transmitted, the offset has to be set to 2.
424
   * @param[in] offset Offset to set. Already has to be in multiples of 16 bytes.
425
   */
426
  void setOffset(uint32_t offset);
427
428
  /**
429
   * Get the More Segments Flag
430
   * @return true if the More Segments Flag is set, false if it is not set
431
   */
432
  bool getMoreSegmentsFlag() const;
433
434
  /**
435
   * Set the More Segments Flag
436
   * @param[in] flag True if the More Segments Flag shall be set, false for resetting
437
   */
438
  void setMoreSegmentsFlag(bool flag);
439
440
  /**
441
   * Sets the message type in this layer with enabling the TP flag
442
   */
443
  void computeCalculateFields();
444
445
  /**
446
   * @return The string representation of the SOME/IP-TP layer
447
   */
448
  std::string toString() const;
449
450
private:
451
  static const uint32_t SOMEIP_TP_MORE_FLAG_MASK = 0x01;
452
  static const uint32_t SOMEIP_TP_OFFSET_MASK = 0xFFFFFFF0;
453
454
0
  size_t getSomeIpHeaderLen() const { return sizeof(someiptphdr); }
455
456
  static uint8_t setTpFlag(uint8_t messageType);
457
};
458
459
} // namespace pcpp