Coverage Report

Created: 2023-01-17 06:15

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