Coverage Report

Created: 2025-07-11 07:47

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