Coverage Report

Created: 2025-08-26 07:54

/src/PcapPlusPlus/Packet++/header/DoIpLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <vector>
4
#include <cstring>
5
#include "Layer.h"
6
#include "Logger.h"
7
8
/// @file
9
10
/// @namespace pcpp
11
/// @brief The main namespace for the PcapPlusPlus lib
12
namespace pcpp
13
{
14
/// @struct doiphdr
15
/// Represents an DoIP protocol header
16
#pragma pack(push, 1)
17
  struct doiphdr
18
  {
19
    /// DoIP version (DOIPV)
20
    uint8_t protocolVersion;
21
    /// DoIP invert version (DOIPIV). Inverse of protocol version
22
    uint8_t invertProtocolVersion;
23
    /// DoIP payload type (DOIPT)
24
    uint16_t payloadType;
25
    /// DoIP content payload length (DOIPL)
26
    uint32_t payloadLength;
27
  };
28
#pragma pack(pop)
29
  static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes.");
30
31
  namespace DoIpConstants
32
  {
33
    /// @brief Length of doip header
34
    static constexpr size_t DOIP_HEADER_LEN = sizeof(doiphdr);
35
36
    /// @brief Length of the Equiepement Identifier (EID) field.
37
    static constexpr size_t DOIP_EID_LEN = 6;
38
39
    /// @brief Length of the Group Identifier (GID) field.
40
    static constexpr size_t DOIP_GID_LEN = 6;
41
42
    /// @brief Length of the Vehicle Identification Number (VIN) field.
43
    static constexpr size_t DOIP_VIN_LEN = 17;
44
45
    /// @brief Length of the Reserved ISO field.
46
    static constexpr size_t DOIP_RESERVED_ISO_LEN = 4;
47
48
    /// @brief Length of the Reserved OEM field.
49
    static constexpr size_t DOIP_RESERVED_OEM_LEN = 4;
50
51
    /// @brief Length of the source address
52
    static constexpr size_t DOIP_SOURCE_ADDRESS_LEN = 2;
53
54
    /// @brief Length of the target address
55
    static constexpr size_t DOIP_TARGET_ADDRESS_LEN = 2;
56
  }  // namespace DoIpConstants
57
58
  /// @brief Enum representing DoIP routing activation types.
59
  /// These values specify the type of routing activation used in DoIP(Diagnostic over IP).
60
  enum class DoIpActivationTypes : uint8_t
61
  {
62
    /// Default routing activation type.
63
    /// Used when no specific type is required.
64
    DEFAULT = 0x00U,
65
66
    /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type.
67
    /// Used for vehicle diagnostics in compliance with WWH-OBD standards.
68
    WWH_OBD = 0x01U,
69
70
    /// Central security routing activation type.
71
    /// Used for secure communications involving a central security system.
72
    CENTRAL_SECURITY = 0xE0U,
73
74
    /// Unknown routing activation type.
75
    /// This value is used when the routing activation type is not specified or recognized.
76
    UNKNOWN
77
  };
78
79
  /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400).
80
  /// These codes are used to indicate specific errors in the DoIP Generic Header.
81
  enum class DoIpGenericHeaderNackCodes : uint8_t
82
  {
83
    /// Incorrect pattern detected in the header.
84
    /// Indicates that the header does not follow the expected pattern.
85
    INCORRECT_PATTERN = 0x00U,
86
87
    /// Unknown payload type.
88
    /// The payload type in the message is not recognized.
89
    UNKNOWN_PAYLOAD_TYPE = 0x01U,
90
91
    /// Message too large.
92
    /// The message size exceeds the allowed limit.
93
    MESSAGE_TOO_LARGE = 0x02U,
94
95
    /// Out of memory.
96
    /// There is insufficient memory available to process the message.
97
    OUT_OF_MEMORY = 0x03U,
98
99
    /// Invalid payload length.
100
    /// The payload length specified in the header is invalid.
101
    INVALID_PAYLOAD_LENGTH = 0x04U,
102
103
    /// UNKNOWN.
104
    /// Indicates that the NACK code is not recognized or supported.
105
    UNKNOWN
106
  };
107
108
  /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400).
109
  /// These action codes specify the next steps required after receiving a DoIP announcement message.
110
  /// Some codes are reserved for future use by ISO standards.
111
  enum class DoIpActionCodes : uint8_t
112
  {
113
    /// No further action required.
114
    /// Indicates that no additional steps are needed after the announcement.
115
    NO_FURTHER_ACTION_REQUIRED = 0x00U,
116
117
    /// Reserved for ISO (0x01).
118
    /// Reserved for future use as per ISO standards.
119
    RESERVED_ISO_0x01 = 0x01U,
120
121
    /// Reserved for ISO (0x02).
122
    /// Reserved for future use as per ISO standards.
123
    RESERVED_ISO_0x02 = 0x02U,
124
125
    /// Reserved for ISO (0x03).
126
    /// Reserved for future use as per ISO standards.
127
    RESERVED_ISO_0x03 = 0x03U,
128
129
    /// Reserved for ISO (0x04).
130
    /// Reserved for future use as per ISO standards.
131
    RESERVED_ISO_0x04 = 0x04U,
132
133
    /// Reserved for ISO (0x05).
134
    /// Reserved for future use as per ISO standards.
135
    RESERVED_ISO_0x05 = 0x05U,
136
137
    /// Reserved for ISO (0x06).
138
    /// Reserved for future use as per ISO standards.
139
    RESERVED_ISO_0x06 = 0x06U,
140
141
    /// Reserved for ISO (0x07).
142
    /// Reserved for future use as per ISO standards.
143
    RESERVED_ISO_0x07 = 0x07U,
144
145
    /// Reserved for ISO (0x08).
146
    /// Reserved for future use as per ISO standards.
147
    RESERVED_ISO_0x08 = 0x08U,
148
149
    /// Reserved for ISO (0x09).
150
    /// Reserved for future use as per ISO standards.
151
    RESERVED_ISO_0x09 = 0x09U,
152
153
    /// Reserved for ISO (0x0A).
154
    /// Reserved for future use as per ISO standards.
155
    RESERVED_ISO_0x0A = 0x0AU,
156
157
    /// Reserved for ISO (0x0B).
158
    /// Reserved for future use as per ISO standards.
159
    RESERVED_ISO_0x0B = 0x0BU,
160
161
    /// Reserved for ISO (0x0C).
162
    /// Reserved for future use as per ISO standards.
163
    RESERVED_ISO_0x0C = 0x0CU,
164
165
    /// Reserved for ISO (0x0D).
166
    /// Reserved for future use as per ISO standards.
167
    RESERVED_ISO_0x0D = 0x0DU,
168
169
    /// Reserved for ISO (0x0E).
170
    /// Reserved for future use as per ISO standards.
171
    RESERVED_ISO_0x0E = 0x0EU,
172
173
    /// Reserved for ISO (0x0F).
174
    /// Reserved for future use as per ISO standards.
175
    RESERVED_ISO_0x0F = 0x0FU,
176
177
    /// Routing activation required.
178
    /// Indicates that routing activation is needed after the announcement message.
179
    ROUTING_ACTIVATION_REQUIRED = 0x10U,
180
181
    /// UNKNOWN.
182
    /// Indicates that the action code is not recognized or supported.
183
    UNKNOWN
184
  };
185
186
  /// @brief Enum representing DoIP routing activation response codes (ISO 13400).
187
  /// These codes are used in response to routing activation requests, providing status
188
  /// or error information related to the request.
189
  enum class DoIpRoutingResponseCodes : uint8_t
190
  {
191
    /// Unknown source address.
192
    /// The source address provided in the request is not recognized.
193
    UNKNOWN_SOURCE_ADDRESS = 0x00U,
194
195
    /// No free socket.
196
    /// There are no available sockets to establish the connection.
197
    NO_FREE_SOCKET = 0x01U,
198
199
    /// Wrong source address.
200
    /// The source address provided in the request is invalid.
201
    WRONG_SOURCE_ADDRESS = 0x02U,
202
203
    /// Source address already registered.
204
    /// The provided source address has already been activated.
205
    SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U,
206
207
    /// Missing authentication.
208
    /// The request is missing required authentication credentials.
209
    MISSING_AUTHENTICATION = 0x04U,
210
211
    /// Rejected confirmation.
212
    /// The confirmation of routing activation was rejected.
213
    REJECTED_CONFIRMATION = 0x05U,
214
215
    /// Unsupported activation type.
216
    /// The requested routing activation type is not supported.
217
218
    UNSUPPORTED_ACTIVATION_TYPE = 0x06U,
219
220
    /// Encrypted connection required(TLS).
221
    /// Indicates that the routing activation requires a secure TLS connection.
222
    ENCRYPTED_CONNECTION_TLS = 0x07U,
223
224
    /// Reserved for ISO (0x08).
225
    /// Reserved for future use as per ISO standards.
226
    RESERVED_ISO_0x08 = 0x08U,
227
228
    /// Reserved for ISO (0x09).
229
    /// Reserved for future use as per ISO standards.
230
    RESERVED_ISO_0x09 = 0x09U,
231
232
    /// Reserved for ISO (0x0A).
233
    /// Reserved for future use as per ISO standards.
234
    RESERVED_ISO_0x0A = 0x0AU,
235
236
    /// Reserved for ISO (0x0B).
237
    /// Reserved for future use as per ISO standards.
238
    RESERVED_ISO_0x0B = 0x0BU,
239
240
    /// Reserved for ISO (0x0C).
241
    /// Reserved for future use as per ISO standards.
242
    RESERVED_ISO_0x0C = 0x0CU,
243
244
    /// Reserved for ISO (0x0D).
245
    /// Reserved for future use as per ISO standards.
246
    RESERVED_ISO_0x0D = 0x0DU,
247
248
    /// Reserved for ISO (0x0E).
249
    /// Reserved for future use as per ISO standards.
250
    RESERVED_ISO_0x0E = 0x0EU,
251
252
    /// Reserved for ISO (0x0F).
253
    /// Reserved for future use as per ISO standards.
254
    RESERVED_ISO_0x0F = 0x0FU,
255
256
    /// Routing successfully activated.
257
    /// The routing activation request was processed successfully.
258
    ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U,
259
260
    /// Confirmation required.
261
    /// Additional confirmation is required to complete the routing activation.
262
    CONFIRMATION_REQUIRED = 0x11U,
263
264
    /// UNKNOWN.
265
    /// Indicates that the routing response code is not recognized or supported.
266
    UNKNOWN
267
  };
268
269
  /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400).
270
  /// These codes indicate reasons for rejecting or failing to process a diagnostic message
271
  /// in the DoIP protocol.
272
  enum class DoIpDiagnosticMessageNackCodes : uint8_t
273
  {
274
    /// Reserved for ISO (0x00).
275
    /// Reserved for future use as per ISO standards.
276
    RESERVED_ISO_0x00 = 0x00U,
277
278
    /// Reserved for ISO (0x01).
279
    /// Reserved for future use as per ISO standards.
280
    RESERVED_ISO_0x01 = 0x01U,
281
282
    /// Invalid source address.
283
    /// The source address specified in the message is invalid.
284
    INVALID_SOURCE_ADDRESS = 0x02U,
285
286
    /// Invalid target address.
287
    /// The target address specified in the message is invalid.
288
    INVALID_TARGET_ADDRESS = 0x03U,
289
290
    /// Message too large.
291
    /// The size of the message exceeds the maximum allowed limit.
292
    MESSAGE_TOO_LARGE = 0x04U,
293
294
    /// Out of memory.
295
    /// There is insufficient memory available to process the message.
296
    OUT_OF_MEMORY = 0x05U,
297
298
    /// Target unreachable.
299
    /// The specified target address cannot be reached.
300
    TARGET_UNREACHABLE = 0x06U,
301
302
    /// Unknown network.
303
    /// The message references a network that is not recognized or supported.
304
    UNKNOWN_NETWORK = 0x07U,
305
306
    /// Transport protocol error.
307
    /// An error occurred at the transport protocol level, preventing the message from being processed.
308
    TRANSPORT_PROTOCOL_ERROR = 0x08U,
309
310
    /// UNKNOWN.
311
    /// Indicates that the NACK code is not recognized or supported.
312
    UNKNOWN
313
  };
314
315
  /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400).
316
  /// These codes indicate the diagnostic power mode status of a DoIP entity,
317
  /// providing information about its readiness for diagnostic operations.
318
  enum class DoIpDiagnosticPowerModeCodes : uint8_t
319
  {
320
    /// Not ready.
321
    /// The DoIP entity is not ready to perform diagnostic operations.
322
    NOT_READY = 0x00U,
323
324
    /// Ready.
325
    /// The DoIP entity is ready to perform diagnostic operations.
326
    READY = 0x01U,
327
328
    /// Not supported.
329
    /// The DoIP entity does not support diagnostic power mode reporting.
330
    NOT_SUPPORTED = 0x02U,
331
332
    /// UNKNOWN.
333
    /// Indicates that the power mode code is not recognized or supported.
334
    UNKNOWN
335
  };
336
337
  /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400).
338
  /// These codes are used to acknowledge the receipt or processing of diagnostic messages
339
  /// in the DoIP protocol.
340
  enum class DoIpDiagnosticAckCodes : uint8_t
341
  {
342
    /// Acknowledgment.
343
    /// Indicates successful receipt or acknowledgment of a diagnostic message.
344
    ACK = 0x00U,
345
346
    /// UNKNOWN.
347
    /// Indicates that the acknowledgment code is not recognized or supported.
348
    UNKNOWN
349
  };
350
351
  /// @brief Enum representing DoIP entity status response codes (ISO 13400).
352
  /// These codes are used to indicate the role or type of a DoIP entity in the network.
353
  enum class DoIpEntityStatusResponseCode : uint8_t
354
  {
355
    /// Gateway.
356
    /// The entity functions as a gateway,
357
    /// facilitating communication between networks.
358
    GATEWAY = 0x00U,
359
360
    /// Node.
361
    /// The entity functions as an individual node within the DoIP network.
362
    NODE = 0x01U,
363
364
    /// UNKNOWN.
365
    /// Indicates that the entity status response code is not recognized or supported.
366
    UNKNOWN
367
  };
368
369
  /// @brief Enum representing DoIP sync status (ISO 13400).
370
  /// These codes are used to indicate whether GID and VIN are synchronized or not.
371
  enum class DoIpSyncStatus : uint8_t
372
  {
373
    /// VIN and or GID are synchronized.
374
    VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00,
375
376
    /// Reserved for ISO (0x01).
377
    /// Reserved for future use as per ISO standards.
378
    RESERVED_ISO_0x01 = 0x01U,
379
380
    /// Reserved for ISO (0x02).
381
    /// Reserved for future use as per ISO standards.
382
    RESERVED_ISO_0x02 = 0x02U,
383
384
    /// Reserved for ISO (0x03).
385
    /// Reserved for future use as per ISO standards.
386
    RESERVED_ISO_0x03 = 0x03U,
387
388
    /// Reserved for ISO (0x04).
389
    /// Reserved for future use as per ISO standards.
390
    RESERVED_ISO_0x04 = 0x04U,
391
392
    /// Reserved for ISO (0x05).
393
    /// Reserved for future use as per ISO standards.
394
    RESERVED_ISO_0x05 = 0x05U,
395
396
    /// Reserved for ISO (0x06).
397
    /// Reserved for future use as per ISO standards.
398
    RESERVED_ISO_0x06 = 0x06U,
399
400
    /// Reserved for ISO (0x07).
401
    /// Reserved for future use as per ISO standards.
402
    RESERVED_ISO_0x07 = 0x07U,
403
404
    /// Reserved for ISO (0x08).
405
    /// Reserved for future use as per ISO standards.
406
    RESERVED_ISO_0x08 = 0x08U,
407
408
    /// Reserved for ISO (0x09).
409
    /// Reserved for future use as per ISO standards.
410
    RESERVED_ISO_0x09 = 0x09U,
411
412
    /// Reserved for ISO (0x0A).
413
    /// Reserved for future use as per ISO standards.
414
    RESERVED_ISO_0x0A = 0x0AU,
415
416
    /// Reserved for ISO (0x0B).
417
    /// Reserved for future use as per ISO standards.
418
    RESERVED_ISO_0x0B = 0x0BU,
419
420
    /// Reserved for ISO (0x0C).
421
    /// Reserved for future use as per ISO standards.
422
    RESERVED_ISO_0x0C = 0x0CU,
423
424
    /// Reserved for ISO (0x0D).
425
    /// Reserved for future use as per ISO standards.
426
    RESERVED_ISO_0x0D = 0x0DU,
427
428
    /// Reserved for ISO (0x0E).
429
    /// Reserved for future use as per ISO standards.
430
    RESERVED_ISO_0x0E = 0x0EU,
431
432
    /// Reserved for ISO (0x08).
433
    /// Reserved for future use as per ISO standards.
434
    RESERVED_ISO_0x0F = 0x0FU,
435
436
    /// VIN and or GID are not synchronized.
437
    VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U,
438
439
    /// UNKNOWN.
440
    /// Indicates that the sync status is not recognized or supported.
441
    UNKNOWN
442
  };
443
444
  /// @brief Represents the DoIP (Diagnostics over IP) protocol versions.
445
  enum class DoIpProtocolVersion : uint8_t
446
  {
447
    /// @brief Reserved protocol version.
448
    /// This value is used when the version is not specified.
449
    RESERVED_VER = 0x00U,
450
451
    /// @brief Protocol version 1, based on ISO 2010 specification.
452
    ISO13400_2010 = 0x01U,
453
454
    /// @brief Protocol version 2, based on ISO 2012 specification.
455
    ISO13400_2012 = 0x02U,
456
457
    /// @brief Protocol version 3, based on ISO 2019 specification.
458
    ISO13400_2019 = 0x03U,
459
460
    /// @brief Protocol version 4, based on ISO 2019 AMD1 (Amendment 1) specification.
461
    ISO13400_2019_AMD1 = 0x04U,
462
463
    /// @brief Default protocol version.
464
    /// Used for broadcast Vehicle Identification Request Messages.
465
    DEFAULT_VALUE = 0xFFU,
466
467
    /// Represents an unknown or unsupported protocol version (not specified by ISO).
468
    /// Used to indicate an unsupported or unknown protocol version for internal usage.
469
    UNKNOWN = 0xEF
470
  };
471
472
  /// @brief Enum representing DoIP payload types.
473
  /// These payload types are defined as part of theDoIP(Diagnostic over IP) protocol
474
  /// and specify the type of message being transmitted.
475
  enum class DoIpPayloadTypes : uint16_t
476
  {
477
    /// Generic header negative acknowledgment.
478
    /// Indicates a failure or error in processing the generic header.
479
    GENERIC_HEADER_NACK = 0x0000U,
480
481
    /// Vehicle identification request.
482
    /// Used to request identification details of a vehicle.
483
    VEHICLE_IDENTIFICATION_REQUEST = 0x0001U,
484
485
    /// Vehicle identification request with EID.
486
    /// Requests identification using an external identifier(EID).
487
    VEHICLE_IDENTIFICATION_REQUEST_WITH_EID = 0x0002U,
488
489
    /// Vehicle identification request with VIN.
490
    /// Requests identification using the vehicle's VIN (Vehicle Identification Number).
491
    VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN = 0x0003U,
492
493
    /// Vehicle announcement message.
494
    /// Sent to announce the availability of a DoIP entity.
495
    VEHICLE_ANNOUNCEMENT_MESSAGE = 0x0004U,
496
497
    /// Routing activation request.
498
    /// Initiates a routing activation procedure.
499
    ROUTING_ACTIVATION_REQUEST = 0x0005U,
500
501
    /// Routing activation response.
502
    /// Response to a routing activation request.
503
    ROUTING_ACTIVATION_RESPONSE = 0x0006U,
504
505
    /// Alive check request.
506
    /// Sent to verify that a DoIP entity is still operational.
507
    ALIVE_CHECK_REQUEST = 0x0007U,
508
509
    /// Alive check response.
510
    /// Response to an alive check request.
511
    ALIVE_CHECK_RESPONSE = 0x0008U,
512
513
    /// Entity status request.
514
    /// Used to request the status of a DoIP entity.
515
    ENTITY_STATUS_REQUEST = 0x4001U,
516
517
    /// Entity status response.
518
    /// Response to an entity status request.
519
    ENTITY_STATUS_RESPONSE = 0x4002U,
520
521
    /// Diagnostic power mode request.
522
    /// Requests the current power mode of a DoIP entity.
523
    DIAGNOSTIC_POWER_MODE_REQUEST = 0x4003U,
524
525
    /// Diagnostic power mode response.
526
    /// Response to a diagnostic power mode request.
527
    DIAGNOSTIC_POWER_MODE_RESPONSE = 0x4004U,
528
529
    /// Diagnostic message type.
530
    /// Represents a generic diagnostic message.
531
    DIAGNOSTIC_MESSAGE = 0x8001U,
532
533
    /// Diagnostic message positive acknowledgment.
534
    /// Indicates successful processing of a diagnostic message.
535
    DIAGNOSTIC_MESSAGE_ACK = 0x8002U,
536
537
    /// Diagnostic message negative acknowledgment.
538
    /// Indicates an error in processing a diagnostic message.
539
    DIAGNOSTIC_MESSAGE_NACK = 0x8003U
540
  };
541
542
  /// @brief Enum representing DoIP diagnostic ports (ISO 13400).
543
  /// These ports are used for communication in the DoIP protocol over different transport layers.
544
  enum class DoIpPorts : uint16_t
545
  {
546
    /// TCP and UDP doip Ports.
547
    /// The standard port for DoIP communication.
548
    TCP_UDP_PORT = 13400U,
549
550
    /// TLS Port.
551
    /// The standard port for DoIP communication over a secure TLS connection.
552
    TLS_PORT = 3496U
553
  };
554
555
  using namespace DoIpConstants;
556
557
  /// @class DoIpLayer
558
  /// Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported
559
  class DoIpLayer : public Layer
560
  {
561
  public:
562
    /// Get the doip payload type
563
    /// @return DoIpPayloadTypes presenting the message doip payload type
564
    virtual DoIpPayloadTypes getPayloadType() const = 0;
565
566
    /// Get the doip payload type as string
567
    /// @return uint16_t presenting the message doip payload type as string
568
    std::string getPayloadTypeAsStr() const;
569
570
    /// Get the version of DOIP protocol
571
    /// @return DoIpProtocolVersion presenting the used protocol version (DOIPV)
572
    DoIpProtocolVersion getProtocolVersion() const;
573
574
    /// Get the version of DOIP protocol
575
    /// @return string presentation the used protocol version (DOIPV)
576
    std::string getProtocolVersionAsStr() const;
577
578
    /// Set the version of DOIP protocol
579
    /// @param[in] version the version of DOIP protocol to set, restricted to existent doip version
580
    void setProtocolVersion(DoIpProtocolVersion version);
581
582
    /// Additional setter for raw protocol version (for testing/fuzzing/debugging)
583
    /// @param[in] rawVersion the raw version of DOIP protocol to set
584
    void setProtocolVersion(uint8_t rawVersion);
585
586
    /// Get the invert version of DOIP protocol
587
    /// @return A uint8_t presenting the used protocol invert version (DOIPV)
588
    uint8_t getInvertProtocolVersion() const;
589
590
    /// Set the invert protocol version of DOIP protocol
591
    /// @param[in] iVersion the invert version of DOIP protocol to set
592
    void setInvertProtocolVersion(uint8_t iVersion);
593
594
    /// Get the doip payload length
595
    /// @return uint32_t presenting the length of doip paylad not including the header
596
    uint32_t getPayloadLength() const;
597
598
    /// Set the doip payload length
599
    /// @param[in] length the doip payload length to set
600
    void setPayloadLength(uint32_t length);
601
602
    /// A method that creates a DoIP layer from packet raw data
603
    /// @param[in] data A pointer to the raw data
604
    /// @param[in] dataLen Size of the data in bytes
605
    /// @param[in] prevLayer A pointer to the previous layer
606
    /// @param[in] packet A pointer to the Packet instance where layer will be stored
607
    /// @return A newly allocated DoIP layer of one of the declared types (according to the message type)
608
    static DoIpLayer* parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
609
610
    /// A static method that checks whether a port is considered as a DOIP port
611
    /// @param[in] port The port number to check
612
    /// @return True if this is a DOIP port number, false otherwise
613
    static inline bool isDoIpPort(uint16_t port);
614
615
    /// A static method that validates the input data
616
    /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer
617
    /// @param[in] dataLen The length of the byte stream
618
    /// @return True if the data is valid and can represent an DOIP layer
619
    static bool isDataValid(uint8_t* data, size_t dataLen);
620
621
    // implement abstract methods
622
623
    /// parse UDS layer
624
    void parseNextLayer() override;
625
626
    /// @return The size of @ref doiphdr + attached fields length
627
    size_t getHeaderLen() const override
628
760
    {
629
760
      return m_DataLen;
630
760
    }
631
632
    std::string toString() const override;
633
634
    void computeCalculateFields() override
635
842
    {}
636
637
    OsiModelLayer getOsiModelLayer() const override
638
842
    {
639
842
      return OsiModelApplicationLayer;
640
842
    }
641
642
  private:
643
    void setPayloadType(DoIpPayloadTypes payloadType);
644
645
    static inline bool isPayloadTypeValid(uint16_t type);
646
647
    static inline bool isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type);
648
649
    static inline bool isPayloadLengthValid(uint32_t payloadLength, size_t dataLen);
650
651
  protected:
652
    // protected c'tors, this class cannot be instantiated by users
653
    DoIpLayer(size_t length);
654
655
    DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
656
657
    doiphdr* getDoIpHeader() const
658
0
    {
659
0
      return reinterpret_cast<doiphdr*>(m_Data);
660
0
    }
661
662
    void setHeaderFields(DoIpProtocolVersion version, DoIpPayloadTypes type, uint32_t length);
663
  };
664
665
  // inline methods definition
666
  inline bool DoIpLayer::isDoIpPort(uint16_t port)
667
311k
  {
668
311k
    auto portAsEnum = static_cast<DoIpPorts>(port);
669
311k
    return (portAsEnum == DoIpPorts::TCP_UDP_PORT || portAsEnum == DoIpPorts::TLS_PORT);
670
311k
  }
671
672
  inline bool DoIpLayer::isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type)
673
4.90k
  {
674
4.90k
    const DoIpProtocolVersion parsedVersion = static_cast<DoIpProtocolVersion>(version);
675
676
4.90k
    switch (parsedVersion)
677
4.90k
    {
678
12
    case DoIpProtocolVersion::RESERVED_VER:
679
12
    {
680
12
      PCPP_LOG_DEBUG("[Malformed doip packet]: Reserved ISO DoIP protocol version detected: 0x"
681
12
                     << std::hex << static_cast<int>(version));
682
12
      return false;
683
0
    }
684
73
    case DoIpProtocolVersion::DEFAULT_VALUE:
685
73
      if (type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN &&
686
73
          type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID &&
687
73
          type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST)
688
5
      {
689
5
        PCPP_LOG_DEBUG("[Malformed doip packet]: Invalid/unsupported DoIP version!");
690
5
        return false;
691
5
      }
692
73
    case DoIpProtocolVersion::ISO13400_2010:
693
4.84k
    case DoIpProtocolVersion::ISO13400_2012:
694
4.84k
    case DoIpProtocolVersion::ISO13400_2019:
695
4.85k
    case DoIpProtocolVersion::ISO13400_2019_AMD1:
696
4.85k
    {
697
4.85k
      if (version != static_cast<uint8_t>(~inVersion))
698
56
      {
699
56
        PCPP_LOG_DEBUG("[Malformed doip packet]: Protocol version and inverse version mismatch! Version: 0x"
700
56
                       << std::hex << static_cast<int>(version) << ", Inverted: 0x"
701
56
                       << static_cast<int>(inVersion));
702
56
        return false;
703
56
      }
704
4.79k
      return true;
705
4.85k
    }
706
29
    default:
707
29
      PCPP_LOG_DEBUG("[Malformed doip packet]: Unknown DoIP protocol version: 0x" << std::hex
708
29
                                                                                  << static_cast<int>(version));
709
29
      return false;
710
4.90k
    }
711
4.90k
  }
712
713
  inline bool DoIpLayer::isPayloadTypeValid(uint16_t type)
714
5.01k
  {
715
5.01k
    const DoIpPayloadTypes payloadType = static_cast<DoIpPayloadTypes>(type);
716
717
5.01k
    switch (payloadType)
718
5.01k
    {
719
468
    case DoIpPayloadTypes::GENERIC_HEADER_NACK:
720
681
    case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST:
721
901
    case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID:
722
1.03k
    case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN:
723
1.26k
    case DoIpPayloadTypes::VEHICLE_ANNOUNCEMENT_MESSAGE:
724
1.64k
    case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST:
725
1.88k
    case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE:
726
2.13k
    case DoIpPayloadTypes::ALIVE_CHECK_REQUEST:
727
2.36k
    case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE:
728
2.76k
    case DoIpPayloadTypes::ENTITY_STATUS_REQUEST:
729
3.21k
    case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE:
730
3.46k
    case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST:
731
3.69k
    case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE:
732
4.18k
    case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE:
733
4.49k
    case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_ACK:
734
4.90k
    case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NACK:
735
4.90k
      return true;
736
737
110
    default:
738
110
      PCPP_LOG_DEBUG("[Malformed doip packet]: Invalid DoIP payload type: 0x" << std::hex << type);
739
110
      return false;
740
5.01k
    }
741
5.01k
  }
742
743
  inline bool DoIpLayer::isPayloadLengthValid(uint32_t payloadLength, size_t dataLen)
744
4.79k
  {
745
4.79k
    const size_t actualPayloadLen = dataLen - DOIP_HEADER_LEN;
746
747
4.79k
    if (payloadLength != actualPayloadLen)
748
230
    {
749
230
      PCPP_LOG_DEBUG("[Malformed doip packet]: Payload length mismatch: expected "
750
230
                     << payloadLength << " bytes, but got " << actualPayloadLen << " bytes.");
751
230
      return false;
752
230
    }
753
754
4.56k
    return true;
755
4.79k
  }
756
757
  //~~~~~~~~~~~~~~~~~~~~~~|
758
  // DoIpGenericHeaderNack|
759
  //~~~~~~~~~~~~~~~~~~~~~~|
760
761
  /// @class DoIpGenericHeaderNack
762
  /// @brief Represents a DoIP Generic Header Negative Acknowledgement message.
763
  ///
764
  /// This message indicates that a received DoIP header was invalid or unsupported.
765
  class DoIpGenericHeaderNack : public DoIpLayer
766
  {
767
  public:
768
    /// @brief Constructs the layer from raw DoIP packet data.
769
    /// @param[in] data Pointer to raw packet data.
770
    /// @param[in] dataLen Length of the raw data.
771
    /// @param[in] prevLayer Pointer to the previous layer.
772
    /// @param[in] packet Pointer to the parent packet instance.
773
    DoIpGenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
774
775
    /// @brief Constructs the message with a specific NACK code.
776
    /// @param[in] nackCode The generic header NACK code.
777
    explicit DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode);
778
779
    /// @brief Gets the NACK code.
780
    /// @return enum DoIpGenericHeaderNackCodes representing the NACK code.
781
    DoIpGenericHeaderNackCodes getNackCode() const;
782
783
    /// @brief Sets the NACK code.
784
    /// @param[in] code enum DoIpGenericHeaderNackCodes representing the NACK code to set.
785
    void setNackCode(DoIpGenericHeaderNackCodes code);
786
787
    /// @brief Returns a human-readable summary of the message.
788
    std::string getSummary() const;
789
790
    /// @brief Returns the DoIP payload type for this message.
791
    DoIpPayloadTypes getPayloadType() const override
792
770
    {
793
770
      return DoIpPayloadTypes::GENERIC_HEADER_NACK;
794
770
    }
795
796
    /// @brief Checks if the NACK data length is valid.
797
    /// @param[in] dataLen Length of the data buffer.
798
    /// @return true if the data length is valid, false otherwise.
799
    static inline bool isDataLenValid(size_t dataLen)
800
468
    {
801
468
      return (dataLen == FIXED_LEN);
802
468
    }
803
804
  private:
805
#pragma pack(push, 1)
806
    struct generic_header_nack : doiphdr
807
    {
808
      uint8_t nackCode;
809
    };
810
#pragma pack(pop)
811
    generic_header_nack* getGenericHeaderNack() const
812
0
    {
813
0
      return reinterpret_cast<generic_header_nack*>(m_Data);
814
0
    }
815
    static constexpr size_t FIXED_LEN = sizeof(generic_header_nack);
816
  };
817
818
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
819
  // DoIpVehicleIdentificationRequest|
820
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
821
822
  /// @class DoIpVehicleIdentificationRequest
823
  /// @brief Represents a Vehicle Identification Request message in the DoIP protocol.
824
  ///
825
  /// This message is sent by a tester to request vehicle identification information
826
  /// such as VIN, logical addresses, and other metadata. It can be broadcast or directed.
827
  class DoIpVehicleIdentificationRequest : public DoIpLayer
828
  {
829
  public:
830
    /// @brief Constructs a VehicleIdentificationRequest from raw packet data.
831
    /// @param[in] data Pointer to the raw payload data.
832
    /// @param[in] dataLen Length of the data buffer.
833
    /// @param[in] prevLayer Pointer to the previous protocol layer.
834
    /// @param[in] packet Pointer to the parent packet.
835
    DoIpVehicleIdentificationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
836
208
        : DoIpLayer(data, dataLen, prevLayer, packet)
837
208
    {}
838
839
    /// @brief Default constructor to create an empty VehicleIdentificationRequest.
840
    DoIpVehicleIdentificationRequest();
841
842
    /// @brief Returns the DoIP payload type.
843
    DoIpPayloadTypes getPayloadType() const override
844
372
    {
845
372
      return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST;
846
372
    }
847
848
    /// @brief Checks if the Vehicle Identification Request data length is valid.
849
    /// @param[in] dataLen Length of the data buffer.
850
    /// @return true if the data length is valid, false otherwise.
851
    static inline bool isDataLenValid(size_t dataLen)
852
213
    {
853
213
      return (dataLen == DOIP_HEADER_LEN);  // No payload
854
213
    }
855
  };
856
857
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
858
  // DoIpVehicleIdentificationRequestWithEID|
859
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
860
861
  /// @class DoIpVehicleIdentificationRequestWithEID
862
  /// @brief Represents a DoIP Vehicle Identification Request with EID.
863
  ///
864
  /// This message is used to identify a vehicle based on its Entity ID (EID).
865
  class DoIpVehicleIdentificationRequestWithEID : public DoIpLayer
866
  {
867
  public:
868
    /// @brief Constructs the layer from raw DoIP packet data.
869
    /// @param[in] data Pointer to raw packet data.
870
    /// @param[in] dataLen Length of the raw data.
871
    /// @param[in] prevLayer Pointer to the previous layer.
872
    /// @param[in] packet Pointer to the parent packet instance.
873
    DoIpVehicleIdentificationRequestWithEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
874
875
    /// @brief Constructs the message using the specified EID.
876
    /// @param[in] eid A 6-byte Entity ID used for vehicle identification.
877
    explicit DoIpVehicleIdentificationRequestWithEID(const std::array<uint8_t, DOIP_EID_LEN>& eid = {});
878
879
    /// @brief Gets the Entity ID (EID).
880
    /// @return A 6-byte Entity ID (EID).
881
    std::array<uint8_t, DOIP_EID_LEN> getEID() const;
882
883
    /// @brief Sets the Entity ID (EID).
884
    /// @param[in] eid A 6-byte Entity ID (EID).
885
    void setEID(const std::array<uint8_t, DOIP_EID_LEN>& eid);
886
887
    /// @brief Returns a human-readable summary of the message.
888
    std::string getSummary() const;
889
890
    /// @brief Returns the DoIP payload type for this message.
891
    DoIpPayloadTypes getPayloadType() const override
892
387
    {
893
387
      return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID;
894
387
    }
895
896
    /// @brief Checks if the EID data length is valid.
897
    /// @param[in] dataLen Length of the data buffer.
898
    /// @return true if the data length is valid, false otherwise.
899
    static inline bool isDataLenValid(size_t dataLen)
900
220
    {
901
220
      return (dataLen == FIXED_LEN);
902
220
    }
903
904
  private:
905
#pragma pack(push, 1)
906
    struct vehicle_identification_request_with_eid : doiphdr
907
    {
908
      std::array<uint8_t, DOIP_EID_LEN> eid;
909
    };
910
#pragma pack(pop)
911
    vehicle_identification_request_with_eid* getVehicleIdentificationRequestWEID() const
912
0
    {
913
0
      return reinterpret_cast<vehicle_identification_request_with_eid*>(m_Data);
914
0
    }
915
    static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_with_eid);
916
  };
917
918
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
919
  // DoIpVehicleIdentificationRequestWithVIN|
920
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
921
922
  /// @class DoIpVehicleIdentificationRequestWithVIN
923
  /// @brief Represents a DoIP Vehicle Identification Request with VIN.
924
  ///
925
  /// This message is used to identify a vehicle based on its Vehicle Identification Number (VIN).
926
  class DoIpVehicleIdentificationRequestWithVIN : public DoIpLayer
927
  {
928
  public:
929
    /// @brief Constructs the layer from raw DoIP packet data.
930
    /// @param[in] data Pointer to raw packet data.
931
    /// @param[in] dataLen Length of the raw data.
932
    /// @param[in] prevLayer Pointer to the previous layer.
933
    /// @param[in] packet Pointer to the parent packet instance.
934
    DoIpVehicleIdentificationRequestWithVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
935
936
    /// @brief Constructs the message using the specified VIN.
937
    /// @param[in] vin A 17-byte Vehicle Identification Number.
938
    explicit DoIpVehicleIdentificationRequestWithVIN(const std::array<uint8_t, DOIP_VIN_LEN>& vin = {});
939
940
    /// @brief Gets the Vehicle Identification Number (VIN).
941
    /// @return A 17-byte Vehicle Identification Number (VIN).
942
    std::array<uint8_t, DOIP_VIN_LEN> getVIN() const;
943
944
    /// @brief Sets the Vehicle Identification Number (VIN).
945
    /// @param[in] vin A 17-byte Vehicle Identification Number (VIN).
946
    void setVIN(const std::array<uint8_t, DOIP_VIN_LEN>& vin);
947
948
    /// @brief Returns a human-readable summary of the message.
949
    std::string getSummary() const;
950
951
    /// @brief Returns the DoIP payload type for this message.
952
    DoIpPayloadTypes getPayloadType() const override
953
234
    {
954
234
      return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN;
955
234
    }
956
957
    /// @brief Checks if the VIN data length is valid.
958
    /// @param[in] dataLen Length of the data buffer.
959
    /// @return true if the data length is valid, false otherwise.
960
    static inline bool isDataLenValid(size_t dataLen)
961
130
    {
962
130
      return (dataLen == FIXED_LEN);
963
130
    }
964
965
  private:
966
#pragma pack(push, 1)
967
    struct vehicle_identification_request_with_vin : doiphdr
968
    {
969
      std::array<uint8_t, DOIP_VIN_LEN> vin;
970
    };
971
#pragma pack(pop)
972
    vehicle_identification_request_with_vin* getVehicleIdentificationRequestWVIN() const
973
0
    {
974
0
      return reinterpret_cast<vehicle_identification_request_with_vin*>(m_Data);
975
0
    }
976
    static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_with_vin);
977
  };
978
979
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
980
  // DoIpVehicleAnnouncementMessage|
981
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
982
983
  /// @class DoIpVehicleAnnouncementMessage
984
  /// @brief Represents a DoIP Vehicle Announcement message.
985
  ///
986
  /// This message is broadcasted by a vehicle to announce its presence, including VIN,
987
  /// logical address, EID, GID, and optionally synchronization status.
988
  class DoIpVehicleAnnouncementMessage : public DoIpLayer
989
  {
990
  public:
991
    /// @brief Constructs the layer from raw DoIP packet data.
992
    /// @param[in] data Pointer to the raw data buffer.
993
    /// @param[in] dataLen Size of the data buffer in bytes.
994
    /// @param[in] prevLayer Pointer to the previous protocol layer.
995
    /// @param[in] packet Pointer to the parent packet.
996
    DoIpVehicleAnnouncementMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
997
998
    /// @brief Constructs the message using specified field values.
999
    /// @param[in] vin Vehicle Identification Number (VIN).
1000
    /// @param[in] logicalAddress Logical address of the vehicle.
1001
    /// @param[in] eid Entity Identifier (EID).
1002
    /// @param[in] gid Group Identifier (GID).
1003
    /// @param[in] actionCode Further action code.
1004
    DoIpVehicleAnnouncementMessage(const std::array<uint8_t, DOIP_VIN_LEN>& vin, uint16_t logicalAddress,
1005
                                   const std::array<uint8_t, DOIP_EID_LEN>& eid,
1006
                                   const std::array<uint8_t, DOIP_GID_LEN>& gid, DoIpActionCodes actionCode);
1007
1008
    /// @brief Gets the Vehicle Identification Number (VIN).
1009
    /// @return A 17-byte Vehicle Identification Number (VIN).
1010
    std::array<uint8_t, DOIP_VIN_LEN> getVIN() const;
1011
1012
    /// @brief Sets the Vehicle Identification Number (VIN).
1013
    /// @param[in] vin A 17-byte Vehicle Identification Number (VIN).
1014
    void setVIN(const std::array<uint8_t, DOIP_VIN_LEN>& vin);
1015
1016
    /// @brief Gets the logical address of the vehicle.
1017
    /// @return A 2-byte logical address of the vehicle.
1018
    uint16_t getLogicalAddress() const;
1019
1020
    /// @brief Sets the logical address.
1021
    /// @param[in] address A 2-byte logical address of the vehicle.
1022
    void setLogicalAddress(uint16_t address);
1023
1024
    /// @brief Gets the Entity Identifier (EID).
1025
    /// @return A 6-byte Entity Identifier (EID).
1026
    std::array<uint8_t, DOIP_EID_LEN> getEID() const;
1027
1028
    /// @brief Sets the Entity Identifier (EID).
1029
    /// @param[in] eid A 6-byte Entity Identifier (EID).
1030
    void setEID(const std::array<uint8_t, DOIP_EID_LEN>& eid);
1031
1032
    /// @brief Gets the Group Identifier (GID).
1033
    /// @return A 6-byte Group Identifier (GID).
1034
    std::array<uint8_t, DOIP_GID_LEN> getGID() const;
1035
1036
    /// @brief Sets the Group Identifier (GID).
1037
    /// @param[in] gid A 6-byte Group Identifier (GID).
1038
    void setGID(const std::array<uint8_t, DOIP_GID_LEN>& gid);
1039
1040
    /// @brief Gets the further action required code.
1041
    /// @return enum DoIpActionCodes representing the further action required code.
1042
    DoIpActionCodes getFurtherActionRequired() const;
1043
1044
    /// @brief Sets the further action required code.
1045
    /// @param[in] action enum DoIpActionCodes representing the further action required code to set.
1046
    void setFurtherActionRequired(DoIpActionCodes action);
1047
1048
    /// @brief Gets the optional synchronization status if available.
1049
    /// @throw std::runtime_error if the sync status is not present.
1050
    /// @note To use this method safely, check beforehand if the sync status is present using hasSyncStatus().
1051
    /// @return A 1-byte synchronization status.
1052
    DoIpSyncStatus getSyncStatus() const;
1053
1054
    /// @brief Sets the synchronization status.
1055
    /// @param[in] sync enum DoIpSyncStatus representing the synchronization status to set.
1056
    void setSyncStatus(DoIpSyncStatus sync);
1057
1058
    /// @brief Checks whether the sync status is present.
1059
    /// @return true if the sync status is present, false otherwise.
1060
    bool hasSyncStatus() const;
1061
1062
    /// @brief Clears the optional sync status field.
1063
    void clearSyncStatus();
1064
1065
    /// @brief Returns a human-readable summary of the message.
1066
    std::string getSummary() const;
1067
1068
    /// @brief Returns the DoIP payload type.
1069
    DoIpPayloadTypes getPayloadType() const override
1070
396
    {
1071
396
      return DoIpPayloadTypes::VEHICLE_ANNOUNCEMENT_MESSAGE;
1072
396
    }
1073
1074
    /// @brief checks if the vehicle announcement data length is valid.
1075
    /// @param[in] dataLen Length of the data buffer.
1076
    /// @return true if the data length is valid, false otherwise.
1077
    static inline bool isDataLenValid(size_t dataLen)
1078
226
    {
1079
226
      return (dataLen == FIXED_LEN || dataLen == OPT_LEN);
1080
226
    }
1081
1082
  private:
1083
#pragma pack(push, 1)
1084
    struct vehicle_announcement_message : doiphdr
1085
    {
1086
      std::array<uint8_t, DOIP_VIN_LEN> vin;
1087
1088
      uint16_t logicalAddress;
1089
1090
      std::array<uint8_t, DOIP_EID_LEN> eid;
1091
1092
      std::array<uint8_t, DOIP_GID_LEN> gid;
1093
1094
      uint8_t actionCode;
1095
    };
1096
#pragma pack(pop)
1097
1098
    vehicle_announcement_message* getVehicleAnnouncementMessage() const
1099
0
    {
1100
0
      return reinterpret_cast<vehicle_announcement_message*>(m_Data);
1101
0
    }
1102
    static constexpr size_t FIXED_LEN = sizeof(vehicle_announcement_message);
1103
    static constexpr size_t SYNC_STATUS_OFFSET = FIXED_LEN;
1104
    static constexpr size_t SYNC_STATUS_LEN = sizeof(uint8_t);
1105
    static constexpr size_t OPT_LEN = FIXED_LEN + SYNC_STATUS_LEN;
1106
  };
1107
1108
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1109
  // DoIpRoutingActivationRequest|
1110
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1111
1112
  /// @class DoIpRoutingActivationRequest
1113
  /// @brief Represents a DoIP Routing Activation Request message.
1114
  ///
1115
  /// Provides parsing and construction for Routing Activation Request messages
1116
  /// as defined by the DoIP protocol.
1117
  class DoIpRoutingActivationRequest : public DoIpLayer
1118
  {
1119
  public:
1120
    /// @brief Constructs the layer from raw DoIP packet data.
1121
    /// @param[in] data Pointer to raw packet data.
1122
    /// @param[in] dataLen Length of the raw data.
1123
    /// @param[in] prevLayer Pointer to the previous layer.
1124
    /// @param[in] packet Pointer to the parent packet instance.
1125
    DoIpRoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1126
1127
    /// @brief Constructs the message from field values.
1128
    /// @param[in] sourceAddress Source address of the tester.
1129
    /// @param[in] activationType Type of routing activation.
1130
    DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType);
1131
1132
    /// @brief Returns the source address.
1133
    /// @return The 2-byte source address.
1134
    uint16_t getSourceAddress() const;
1135
1136
    /// @brief Sets the source address.
1137
    /// @param[in] value The source address to set.
1138
    void setSourceAddress(uint16_t value);
1139
1140
    /// @brief Returns the activation type.
1141
    /// @return The activation type as a DoIpActivationTypes enum value.
1142
    DoIpActivationTypes getActivationType() const;
1143
1144
    /// @brief Sets the activation type.
1145
    /// @param[in] activationType The activation type to set.
1146
    void setActivationType(DoIpActivationTypes activationType);
1147
1148
    /// @brief Gets the reserved ISO bytes.
1149
    /// @return 4-byte array representing the reserved ISO bytes.
1150
    std::array<uint8_t, DOIP_RESERVED_ISO_LEN> getReservedIso() const;
1151
1152
    /// @brief Sets the reserved ISO bytes.
1153
    /// @param[in] reservedIso The reserved ISO bytes to set.
1154
    void setReservedIso(const std::array<uint8_t, DOIP_RESERVED_ISO_LEN>& reservedIso);
1155
1156
    /// @brief Gets the to reserved OEM bytes if present.
1157
    /// @throw std::runtime_error if the reserved OEM bytes are not present.
1158
    /// @note To use this method safely, check beforehand if the reserved OEM bytes are present using
1159
    /// hasReservedOem().
1160
    std::array<uint8_t, DOIP_RESERVED_OEM_LEN> getReservedOem() const;
1161
1162
    /// @brief Sets the reserved OEM bytes.
1163
    /// @param[in] reservedOem The reserved OEM bytes to set.
1164
    void setReservedOem(const std::array<uint8_t, DOIP_RESERVED_OEM_LEN>& reservedOem);
1165
1166
    /// @brief Checks if OEM reserved bytes are present.
1167
    /// @return true if OEM reserved bytes are present, false otherwise.
1168
    bool hasReservedOem() const;
1169
1170
    /// @brief Clears the OEM reserved bytes.
1171
    void clearReservedOem();
1172
1173
    /// @brief Returns a human-readable summary of the message.
1174
    std::string getSummary() const;
1175
1176
    /// @brief Returns the DoIP payload type for this message.
1177
    DoIpPayloadTypes getPayloadType() const override
1178
414
    {
1179
414
      return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST;
1180
414
    }
1181
1182
    /// @brief Checks if the routing activation request data length is valid.
1183
    /// @param[in] dataLen The length of the data.
1184
    /// @return true if the data is valid, false otherwise.
1185
    static inline bool isDataLenValid(size_t dataLen)
1186
235
    {
1187
235
      return (dataLen == FIXED_LEN || dataLen == OPT_LEN);
1188
235
    }
1189
1190
  private:
1191
#pragma pack(push, 1)
1192
    struct routing_activation_request : doiphdr
1193
    {
1194
      uint16_t sourceAddress;
1195
1196
      uint8_t activationType;
1197
1198
      std::array<uint8_t, DOIP_RESERVED_ISO_LEN> reservedIso;
1199
    };
1200
#pragma pack(pop)
1201
1202
    routing_activation_request* getRoutingActivationRequest() const
1203
0
    {
1204
0
      return reinterpret_cast<routing_activation_request*>(m_Data);
1205
0
    }
1206
    static constexpr size_t FIXED_LEN = sizeof(routing_activation_request);
1207
    static constexpr size_t RESERVED_OEM_OFFSET = FIXED_LEN;
1208
    static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN;
1209
  };
1210
1211
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1212
  // DoIpRoutingActivationResponse|
1213
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1214
1215
  /// @class DoIpRoutingActivationResponse
1216
  /// @brief Represents a DoIP Routing Activation Response message.
1217
  ///
1218
  /// Provides parsing and construction for Routing Activation Response messages
1219
  /// as defined by the DoIP protocol.
1220
  class DoIpRoutingActivationResponse : public DoIpLayer
1221
  {
1222
  public:
1223
    /// @brief Constructs the layer from raw DoIP packet data.
1224
    /// @param[in] data Pointer to raw packet data.
1225
    /// @param[in] dataLen Length of the raw data.
1226
    /// @param[in] prevLayer Pointer to the previous layer.
1227
    /// @param[in] packet Pointer to the parent packet instance.
1228
    DoIpRoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1229
1230
    /// @brief Constructs the message from field values.
1231
    /// @param[in] logicalAddressExternalTester Logical address of the external tester.
1232
    /// @param[in] sourceAddress ECU source address.
1233
    /// @param[in] responseCode The routing response code.
1234
    DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress,
1235
                                  DoIpRoutingResponseCodes responseCode);
1236
1237
    /// @brief Gets the logical address of the external tester.
1238
    /// @return The 2-byte logical address of the external tester.
1239
    uint16_t getLogicalAddressExternalTester() const;
1240
1241
    /// @brief Sets the logical address of the external tester.
1242
    /// @param[in] addr The logical address of the external tester to set.
1243
    void setLogicalAddressExternalTester(uint16_t addr);
1244
1245
    /// @brief Gets the source address.
1246
    /// @return The 2-byte source address.
1247
    uint16_t getSourceAddress() const;
1248
1249
    /// @brief Sets the source address.
1250
    /// @param[in] sourceAddress The source address to set.
1251
    void setSourceAddress(uint16_t sourceAddress);
1252
1253
    /// @brief Gets the routing response code.
1254
    /// @return enum DoIpRoutingResponseCodes representing the routing response code.
1255
    DoIpRoutingResponseCodes getResponseCode() const;
1256
1257
    /// @brief Sets the routing response code.
1258
    /// @param[in] code The routing response code to set.
1259
    void setResponseCode(DoIpRoutingResponseCodes code);
1260
1261
    /// @brief Gets the reserved ISO bytes.
1262
    /// @return 4-byte array representing the reserved ISO bytes.
1263
    std::array<uint8_t, DOIP_RESERVED_ISO_LEN> getReservedIso() const;
1264
1265
    /// @brief Sets the reserved ISO bytes.
1266
    /// @param[in] reservedIso The reserved ISO bytes to set.
1267
    void setReservedIso(const std::array<uint8_t, DOIP_RESERVED_ISO_LEN>& reservedIso);
1268
1269
    /// @brief Gets pointer to reserved OEM bytes if present.
1270
    /// @throw std::runtime_error if the reserved OEM bytes are not present.
1271
    /// @note before using this method, check beforehand if the reserved OEM bytes are present using
1272
    /// hasReservedOem().
1273
    std::array<uint8_t, DOIP_RESERVED_OEM_LEN> getReservedOem() const;
1274
1275
    /// @brief Sets the reserved OEM bytes.
1276
    /// @param[in] reservedOem The reserved OEM bytes to set.
1277
    void setReservedOem(const std::array<uint8_t, DOIP_RESERVED_OEM_LEN>& reservedOem);
1278
1279
    /// @brief Checks if OEM reserved bytes are present.
1280
    /// @return true if OEM reserved bytes are present, false otherwise.
1281
    bool hasReservedOem() const;
1282
1283
    /// @brief Clears the OEM reserved bytes.
1284
    void clearReservedOem();
1285
1286
    /// @brief Returns a human-readable summary of the message.
1287
    std::string getSummary() const;
1288
1289
    /// @brief Returns the DoIP payload type for this message.
1290
    DoIpPayloadTypes getPayloadType() const override
1291
432
    {
1292
432
      return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE;
1293
432
    }
1294
1295
    /// @brief Checks if the routing activation response data length is valid.
1296
    /// @param[in] dataLen The length of the data.
1297
    /// @return true if the data is valid, false otherwise.
1298
    static inline bool isDataLenValid(size_t dataLen)
1299
240
    {
1300
240
      return (dataLen == FIXED_LEN || dataLen == OPT_LEN);
1301
240
    }
1302
1303
  private:
1304
#pragma pack(push, 1)
1305
    struct routing_activation_response : doiphdr
1306
    {
1307
      uint16_t logicalAddressExternalTester;
1308
1309
      uint16_t sourceAddress;
1310
1311
      uint8_t responseCode;
1312
1313
      std::array<uint8_t, DOIP_RESERVED_ISO_LEN> reservedIso;
1314
    };
1315
#pragma pack(pop)
1316
    routing_activation_response* getRoutingActivationResponse() const
1317
0
    {
1318
0
      return reinterpret_cast<routing_activation_response*>(m_Data);
1319
0
    }
1320
    static constexpr size_t FIXED_LEN = sizeof(routing_activation_response);
1321
    static constexpr size_t RESERVED_OEM_OFFSET = FIXED_LEN;
1322
    static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN;
1323
  };
1324
1325
  //~~~~~~~~~~~~~~~~~~~~~~|
1326
  // DoIpAliveCheckRequest|
1327
  //~~~~~~~~~~~~~~~~~~~~~~|
1328
1329
  /// @class DoIpAliveCheckRequest
1330
  /// @brief Represents an Alive Check Request message in the DoIP protocol.
1331
  ///
1332
  /// This message is sent by a tester to verify if a DoIP entity is responsive.
1333
  /// The responding DoIP node should reply with an Alive Check Response.
1334
  class DoIpAliveCheckRequest : public DoIpLayer
1335
  {
1336
  public:
1337
    /// @brief Constructs an AliveCheckRequest from raw packet data.
1338
    /// @param[in] data Pointer to the raw payload data.
1339
    /// @param[in] dataLen Length of the data buffer.
1340
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1341
    /// @param[in] packet Pointer to the parent packet.
1342
    DoIpAliveCheckRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
1343
245
        : DoIpLayer(data, dataLen, prevLayer, packet)
1344
245
    {}
1345
1346
    /// @brief Default constructor to create an empty AliveCheckRequest message.
1347
    DoIpAliveCheckRequest();
1348
1349
    /// @brief Returns the DoIP payload type for this message.
1350
    DoIpPayloadTypes getPayloadType() const override
1351
441
    {
1352
441
      return DoIpPayloadTypes::ALIVE_CHECK_REQUEST;
1353
441
    }
1354
1355
    /// @brief Checks if the Alive Check Request data length is valid.
1356
    /// @param[in] dataLen Length of the data buffer.
1357
    /// @return true if the data length is valid, false otherwise.
1358
    static inline bool isDataLenValid(size_t dataLen)
1359
245
    {
1360
245
      return (dataLen == DOIP_HEADER_LEN);  // No payload
1361
245
    }
1362
  };
1363
1364
  //~~~~~~~~~~~~~~~~~~~~~~~|
1365
  // DoIpAliveCheckResponse|
1366
  //~~~~~~~~~~~~~~~~~~~~~~~|
1367
1368
  /// @class DoIpAliveCheckResponse
1369
  /// @brief Represents a DoIP Alive Check Response message.
1370
  ///
1371
  /// The Alive Check Response is used to confirm that an entity is still active in the network.
1372
  /// It contains the source address of the responder.
1373
  class DoIpAliveCheckResponse : public DoIpLayer
1374
  {
1375
  public:
1376
    /// @brief Constructs the layer from raw DoIP packet data.
1377
    /// @param[in] data Pointer to the raw data buffer.
1378
    /// @param[in] dataLen Size of the data buffer in bytes.
1379
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1380
    /// @param[in] packet Pointer to the parent packet.
1381
    DoIpAliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1382
1383
    /// @brief Constructs the message using the specified source address.
1384
    /// @param[in] sourceAddress The source address of the responder.
1385
    explicit DoIpAliveCheckResponse(uint16_t sourceAddress);
1386
1387
    /// @brief Gets the source address.
1388
    /// @return The 2-byte source address of the responder.
1389
    uint16_t getSourceAddress() const;
1390
1391
    /// @brief Sets the source address.
1392
    /// @param[in] address The new source address.
1393
    void setSourceAddress(uint16_t address);
1394
1395
    /// @brief Returns a human-readable summary of the message.
1396
    std::string getSummary() const;
1397
1398
    /// @brief Returns the DoIP payload type.
1399
    /// @return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE
1400
    DoIpPayloadTypes getPayloadType() const override
1401
342
    {
1402
342
      return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE;
1403
342
    }
1404
    /// @brief Checks if the Alive Check Response data length is valid.
1405
    /// @param[in] dataLen Length of the data buffer.
1406
    /// @return true if the data length is valid, false otherwise.
1407
    static inline bool isDataLenValid(size_t dataLen)
1408
195
    {
1409
195
      return (dataLen == FIXED_LEN);
1410
195
    }
1411
1412
  private:
1413
#pragma pack(push, 1)
1414
    struct alive_check_response : doiphdr
1415
    {
1416
      uint16_t sourceAddress;
1417
    };
1418
#pragma pack(pop)
1419
    alive_check_response* getAliveCheckResponse() const
1420
0
    {
1421
0
      return reinterpret_cast<alive_check_response*>(m_Data);
1422
0
    }
1423
    static constexpr size_t FIXED_LEN = sizeof(alive_check_response);
1424
  };
1425
1426
  //~~~~~~~~~~~~~~~~~~~~~~~~|
1427
  // DoIpEntityStatusRequest|
1428
  //~~~~~~~~~~~~~~~~~~~~~~~~|
1429
1430
  /// @class DoIpEntityStatusRequest
1431
  /// @brief Represents an Entity Status Request message in the DoIP protocol.
1432
  ///
1433
  /// This message is sent by a tester to request the current status of the DoIP entity,
1434
  /// including capabilities such as maximum number of concurrent socket connections
1435
  /// and optionally the maximum data size supported.
1436
  class DoIpEntityStatusRequest : public DoIpLayer
1437
  {
1438
  public:
1439
    /// @brief Constructs an EntityStatusRequest from raw packet data.
1440
    /// @param[in] data Pointer to the raw payload data.
1441
    /// @param[in] dataLen Length of the data buffer.
1442
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1443
    /// @param[in] packet Pointer to the parent packet.
1444
    DoIpEntityStatusRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
1445
400
        : DoIpLayer(data, dataLen, prevLayer, packet)
1446
400
    {}
1447
1448
    /// @brief Default constructor to create an empty EntityStatusRequest message.
1449
    DoIpEntityStatusRequest();
1450
1451
    /// @brief Returns the DoIP payload type for this message.
1452
    DoIpPayloadTypes getPayloadType() const override
1453
720
    {
1454
720
      return DoIpPayloadTypes::ENTITY_STATUS_REQUEST;
1455
720
    }
1456
1457
    /// @brief Checks if the Entity Status Request data length is valid.
1458
    /// @param[in] dataLen Length of the data buffer.
1459
    /// @return true if the data length is valid, false otherwise.
1460
    static inline bool isDataLenValid(size_t dataLen)
1461
400
    {
1462
400
      return (dataLen == DOIP_HEADER_LEN);  // No payload
1463
400
    }
1464
  };
1465
1466
  //~~~~~~~~~~~~~~~~~~~~~~~~~|
1467
  // DoIpEntityStatusResponse|
1468
  //~~~~~~~~~~~~~~~~~~~~~~~~~|
1469
1470
  /// @class DoIpEntityStatusResponse
1471
  /// @brief Represents a DoIP Entity Status Response message.
1472
  ///
1473
  /// This message provides the status of a DoIP entity, such as its type,
1474
  /// the number of concurrent sockets it can support, and optionally the max data size.
1475
  class DoIpEntityStatusResponse : public DoIpLayer
1476
  {
1477
  public:
1478
    /// @brief Constructs the layer from raw DoIP packet data.
1479
    /// @param[in] data Pointer to the raw data buffer.
1480
    /// @param[in] dataLen Size of the data buffer in bytes.
1481
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1482
    /// @param[in] packet Pointer to the parent packet.
1483
    DoIpEntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1484
1485
    /// @brief Constructs the message using provided field values.
1486
    /// @param[in] nodeType Type of the DoIP node (default: GATEWAY).
1487
    /// @param[in] maxConcurrentSockets Maximum supported concurrent sockets.
1488
    /// @param[in] currentlyOpenSockets Currently active sockets.
1489
    DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, uint8_t maxConcurrentSockets,
1490
                             uint8_t currentlyOpenSockets);
1491
1492
    /// @brief Returns the DoIP payload type.
1493
    /// @return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE
1494
    DoIpPayloadTypes getPayloadType() const override
1495
690
    {
1496
690
      return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE;
1497
690
    }
1498
1499
    /// @brief Gets the type of the DoIP node.
1500
    /// @return enum DoIpEntityStatusResponseCode representing the node type.
1501
    DoIpEntityStatusResponseCode getNodeType() const;
1502
1503
    /// @brief Gets the maximum number of concurrent sockets supported.
1504
    /// @return Max supported concurrent sockets.
1505
    uint8_t getMaxConcurrentSockets() const;
1506
1507
    /// @brief Gets the number of currently open sockets.
1508
    /// @return Number of currently open sockets.
1509
    uint8_t getCurrentlyOpenSockets() const;
1510
1511
    /// @brief Gets the optional maximum data size field.
1512
    /// @throws std::runtime_error if the max data size is not present.
1513
    /// @note To use this method safely, check beforehand if the max data size is present using hasMaxDataSize().
1514
    /// @return The maximum data size in bytes.
1515
    uint32_t getMaxDataSize() const;
1516
1517
    /// @brief Sets the DoIP node type.
1518
    /// @param[in] status enum DoIpEntityStatusResponseCode representing the node type to set.
1519
    void setNodeType(DoIpEntityStatusResponseCode status);
1520
1521
    /// @brief Sets the maximum number of concurrent sockets.
1522
    /// @param[in] sockets New maximum concurrent socket count.
1523
    void setMaxConcurrentSockets(uint8_t sockets);
1524
1525
    /// @brief Sets the number of currently open sockets.
1526
    /// @param[in] sockets New count of currently open sockets.
1527
    void setCurrentlyOpenSockets(uint8_t sockets);
1528
1529
    /// @brief Sets the maximum data size field.
1530
    /// @param[in] data uint32_t representing the max data size.
1531
    void setMaxDataSize(uint32_t data);
1532
1533
    /// @brief Checks if the optional max data size is present.
1534
    /// @return True if max data size is available, false otherwise.
1535
    bool hasMaxDataSize() const;
1536
1537
    /// @brief Clears the optional max data size field.
1538
    void clearMaxDataSize();
1539
1540
    /// @brief Returns a human-readable summary of the message.
1541
    /// @return A string summarizing the Entity Status Response.
1542
    std::string getSummary() const;
1543
1544
    /// @brief  Checks if the Entity Status Response data length is valid.
1545
    /// @param[in] dataLen Length of the data buffer.
1546
    /// @return  true if the data length is valid, false otherwise.
1547
    static inline bool isDataLenValid(size_t dataLen)
1548
414
    {
1549
414
      return (dataLen == FIXED_LEN || dataLen == OPT_LEN);
1550
414
    }
1551
1552
  private:
1553
#pragma pack(push, 1)
1554
    struct entity_status_response : doiphdr
1555
    {
1556
      uint8_t nodeType;
1557
1558
      uint8_t maxConcurrentSockets;
1559
1560
      uint8_t currentlyOpenSockets;
1561
    };
1562
#pragma pack(pop)
1563
1564
    entity_status_response* getEntityStatusResponse() const
1565
0
    {
1566
0
      return reinterpret_cast<entity_status_response*>(m_Data);
1567
0
    }
1568
    static constexpr size_t FIXED_LEN = sizeof(entity_status_response);
1569
    static constexpr size_t MAX_DATA_SIZE_OFFSET = FIXED_LEN;
1570
    static constexpr size_t MAX_DATA_SIZE_LEN = sizeof(uint32_t);
1571
    static constexpr size_t OPT_LEN = FIXED_LEN + MAX_DATA_SIZE_LEN;
1572
  };
1573
1574
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1575
  // DoIpDiagnosticPowerModeRequest|
1576
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1577
1578
  /// @class DoIpDiagnosticPowerModeRequest
1579
  /// @brief Represents a Diagnostic Power Mode Request message in the DoIP protocol.
1580
  ///
1581
  /// This message is sent to inquire about the current power mode status of the vehicle,
1582
  /// which helps determine if diagnostic communication can be initiated or continued.
1583
  class DoIpDiagnosticPowerModeRequest : public DoIpLayer
1584
  {
1585
  public:
1586
    /// @brief Constructs a DiagnosticPowerModeRequest from raw packet data.
1587
    /// @param[in] data Pointer to the raw payload data.
1588
    /// @param[in] dataLen Length of the data buffer.
1589
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1590
    /// @param[in] packet Pointer to the parent packet.
1591
    DoIpDiagnosticPowerModeRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
1592
250
        : DoIpLayer(data, dataLen, prevLayer, packet)
1593
250
    {}
1594
1595
    /// @brief Default constructor to create an empty DiagnosticPowerModeRequest.
1596
    DoIpDiagnosticPowerModeRequest();
1597
1598
    /// @brief Returns the DoIP payload type.
1599
    DoIpPayloadTypes getPayloadType() const override
1600
450
    {
1601
450
      return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST;
1602
450
    }
1603
1604
    /// @brief Checks if the Entity Status Request data length is valid.
1605
    /// @param[in] dataLen Length of the data buffer.
1606
    /// @return true if the data length is valid, false otherwise.
1607
    static inline bool isDataLenValid(size_t dataLen)
1608
250
    {
1609
250
      return (dataLen == DOIP_HEADER_LEN);  // No payload
1610
250
    }
1611
  };
1612
1613
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1614
  // DoIpDiagnosticPowerModeResponse|
1615
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1616
1617
  /// @class DoIpDiagnosticPowerModeResponse
1618
  /// @brief Represents a DoIP Diagnostic Power Mode Response message.
1619
  ///
1620
  /// This message is used to communicate the current power mode of the vehicle
1621
  /// or control unit in response to a diagnostic power mode request.
1622
  class DoIpDiagnosticPowerModeResponse : public DoIpLayer
1623
  {
1624
  public:
1625
    /// @brief Constructs the layer from raw DoIP packet data.
1626
    /// @param[in] data Pointer to the raw data buffer.
1627
    /// @param[in] dataLen Size of the data buffer in bytes.
1628
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1629
    /// @param[in] packet Pointer to the parent packet.
1630
    DoIpDiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1631
1632
    /// @brief Constructs the message using the specified power mode code.
1633
    /// @param[in] modeCode Diagnostic power mode code to set.
1634
    explicit DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes modeCode);
1635
1636
    /// @brief Gets the current power mode code.
1637
    /// @return The diagnostic power mode code.
1638
    DoIpDiagnosticPowerModeCodes getPowerModeCode() const;
1639
1640
    /// @brief Sets the power mode code.
1641
    /// @param[in] code enum DoIpDiagnosticPowerModeCodes representing the power mode code to set.
1642
    void setPowerModeCode(DoIpDiagnosticPowerModeCodes code);
1643
1644
    /// @brief Returns a human-readable summary of the message.
1645
    std::string getSummary() const;
1646
1647
    /// @brief Returns the DoIP payload type.
1648
    /// @return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE
1649
    DoIpPayloadTypes getPayloadType() const override
1650
360
    {
1651
360
      return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE;
1652
360
    }
1653
1654
    /// @brief Checks if the Diagnostic Power Mode Response data length is valid.
1655
    /// @param[in] dataLen Length of the data buffer.
1656
    /// @return true if the data length is valid, false otherwise.
1657
    static inline bool isDataLenValid(size_t dataLen)
1658
216
    {
1659
216
      return (dataLen == FIXED_LEN);
1660
216
    }
1661
1662
  private:
1663
#pragma pack(push, 1)
1664
    struct diagnostic_power_mode_response : doiphdr
1665
    {
1666
      uint8_t powerModeCode;
1667
    };
1668
#pragma pack(pop)
1669
    diagnostic_power_mode_response* getDiagnosticPowerModeResponse() const
1670
0
    {
1671
0
      return reinterpret_cast<diagnostic_power_mode_response*>(m_Data);
1672
0
    }
1673
    static constexpr size_t FIXED_LEN = sizeof(diagnostic_power_mode_response);
1674
  };
1675
1676
  //~~~~~~~~~~~~~~~~~~~|
1677
  // DoIpDiagnosticBase|
1678
  //~~~~~~~~~~~~~~~~~~~|
1679
1680
  /// @class DoIpDiagnosticBase
1681
  /// @brief Represents a DoIP Diagnostic Message sent between tester and ECU.
1682
  /// This class includes source and target addresses.
1683
  class DoIpDiagnosticBase : public DoIpLayer
1684
  {
1685
  public:
1686
    /// @brief Gets the source logical address of the message.
1687
    /// @return 16-bit address of the source ECU.
1688
    uint16_t getSourceAddress() const;
1689
1690
    /// @brief Sets the source logical address.
1691
    /// @param[in] sourceAddress 16-bit source address.
1692
    void setSourceAddress(uint16_t sourceAddress);
1693
1694
    /// @brief Gets the target logical address of the message.
1695
    /// @return 16-bit address of the destination ECU.
1696
    uint16_t getTargetAddress() const;
1697
1698
    /// @brief Sets the target logical address.
1699
    /// @param[in] targetAddress 16-bit target address.
1700
    void setTargetAddress(uint16_t targetAddress);
1701
1702
    /// @brief Returns a human-readable summary of the message content.
1703
    /// @return A string summarizing the diagnostic message.
1704
    virtual std::string getSummary() const = 0;
1705
1706
  protected:
1707
    DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1708
1709
0
    DoIpDiagnosticBase(size_t length) : DoIpLayer(length) {};
1710
1711
#pragma pack(push, 1)
1712
    /// An internal structure representing the common diagnostic header.
1713
    struct common_diagnostic_header : doiphdr
1714
    {
1715
      uint16_t sourceAddress;
1716
1717
      uint16_t targetAddress;
1718
    };
1719
#pragma pack(pop)
1720
    common_diagnostic_header* getCommonDiagnosticHeader() const
1721
0
    {
1722
0
      return reinterpret_cast<common_diagnostic_header*>(m_Data);
1723
0
    }
1724
  };
1725
1726
  //~~~~~~~~~~~~~~~~~~~~~~|
1727
  // DoIpDiagnosticMessage|
1728
  //~~~~~~~~~~~~~~~~~~~~~~|
1729
1730
  /// @class DoIpDiagnosticMessage
1731
  /// @brief Represents a DoIP Diagnostic message sent between tester and ECU.
1732
  ///
1733
  /// This message includes source and target addresses and carries diagnostic service data.
1734
  class DoIpDiagnosticMessage : public DoIpDiagnosticBase
1735
  {
1736
  public:
1737
    /// @brief Constructs the DiagnosticMessage from raw packet data.
1738
    /// @param[in] data Pointer to the raw payload data.
1739
    /// @param[in] dataLen Length of the data buffer.
1740
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1741
    /// @param[in] packet Pointer to the parent packet.
1742
    DoIpDiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1743
1744
    /// @brief Constructs a DiagnosticMessage from specified field values.
1745
    /// @param[in] sourceAddress Address of the sending ECU/tester.
1746
    /// @param[in] targetAddress Address of the target ECU.
1747
    /// @param[in] diagnosticData Vector containing UDS diagnostic service data.
1748
    DoIpDiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress,
1749
                          const std::vector<uint8_t>& diagnosticData);
1750
1751
    /// @brief Set the diagnostic data payload.
1752
    /// @param[in] data A vector containing the diagnostic data bytes to be stored.
1753
    void setDiagnosticData(const std::vector<uint8_t>& data);
1754
1755
    /// @brief Get the diagnostic data payload.
1756
    /// @return A vector containing the diagnostic data bytes.
1757
    std::vector<uint8_t> getDiagnosticData() const;
1758
1759
    /// @brief Returns a human-readable summary of the message content.
1760
    /// @return A string summarizing the diagnostic message.
1761
    std::string getSummary() const override;
1762
1763
    /// @brief Returns the DoIP payload type.
1764
    /// @return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE
1765
    DoIpPayloadTypes getPayloadType() const override
1766
821
    {
1767
821
      return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE;
1768
821
    }
1769
1770
    // override getHeaderLen()
1771
    size_t getHeaderLen() const override
1772
575
    {
1773
575
      return sizeof(doiphdr) + 2 * sizeof(uint16_t);
1774
575
    }
1775
1776
    /// @brief Checks if the diagnostic data length is valid.
1777
    /// @return true if the data length is valid, false otherwise.
1778
    static inline bool isDataLenValid(size_t dataLen)
1779
493
    {
1780
493
      return (dataLen >= MIN_LEN);
1781
493
    }
1782
1783
  private:
1784
    static constexpr size_t DIAGNOSTIC_DATA_OFFSET = sizeof(common_diagnostic_header);
1785
    static constexpr size_t MIN_LEN = DIAGNOSTIC_DATA_OFFSET + 1; /*Min diagnostic request Len*/
1786
  };
1787
1788
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1789
  // DoIpDiagnosticResponseMessageBase|
1790
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1791
  /// @class DoIpDiagnosticResponseMessageBase
1792
  /// @brief Represents a Basic class for Diagnostic message (ACK/NACK) sent back to tester.
1793
  class DoIpDiagnosticResponseMessageBase : public DoIpDiagnosticBase
1794
  {
1795
  public:
1796
    /// @brief Gets the acknowledgment/nack code (1-byte).
1797
    /// @return The acknowledgment/nack code.
1798
    uint8_t getResponseCode() const;
1799
1800
    /// @brief Sets the acknowledgment/nack code (1-byte).
1801
    /// @param[in] code The acknowledgment/nack code to set.
1802
    void setResponseCode(uint8_t code);
1803
1804
    /// @brief Gets the optional previously echoed diagnostic message.
1805
    /// @return A vector containing the previously echoed diagnostic message.
1806
    std::vector<uint8_t> getPreviousMessage() const;
1807
1808
    /// @brief Checks if a previous message is attached.
1809
    /// @return true if a previous message is present, false otherwise.
1810
    bool hasPreviousMessage() const;
1811
1812
    /// @brief Sets the previous echoed diagnostic message.
1813
    /// @param[in] msg A vector containing the previously echoed diagnostic message.
1814
    void setPreviousMessage(const std::vector<uint8_t>& msg);
1815
1816
    /// @brief Clears the previously stored diagnostic message.
1817
    void clearPreviousMessage();
1818
1819
    /// @brief Checks if data length is valid.
1820
    /// @param[in] dataLen Length of the data buffer.
1821
    /// @return true if the data length is valid, false otherwise.
1822
    static inline bool isDataLenValid(size_t dataLen)
1823
623
    {
1824
623
      return (dataLen >= FIXED_LEN);
1825
623
    }
1826
1827
  protected:
1828
    DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1829
    DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type);
1830
1831
  private:
1832
#pragma pack(push, 1)
1833
    struct diagnostic_response_message_base : common_diagnostic_header
1834
    {
1835
      uint8_t diagnosticCode;
1836
    };
1837
#pragma pack(pop)
1838
    diagnostic_response_message_base* getDiagnosticResponseMessageBase() const
1839
0
    {
1840
0
      return reinterpret_cast<diagnostic_response_message_base*>(m_Data);
1841
0
    }
1842
    static constexpr size_t FIXED_LEN = sizeof(diagnostic_response_message_base);
1843
    static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN;
1844
  };
1845
1846
  //~~~~~~~~~~~~~~~~~~~~~~~~~|
1847
  // DoIpDiagnosticMessageAck|
1848
  //~~~~~~~~~~~~~~~~~~~~~~~~~|
1849
1850
  /// @class DoIpDiagnosticMessageAck
1851
  /// @brief Represents a positive acknowledgment message in response to a DiagnosticMessage.
1852
  ///
1853
  /// This message is sent by a DoIP node to acknowledge the correct reception and processing
1854
  /// of a diagnostic message. Optionally, the original message (or part of it) may be echoed back.
1855
  class DoIpDiagnosticMessageAck : public DoIpDiagnosticResponseMessageBase
1856
  {
1857
  public:
1858
    /// @brief Constructs a DiagnosticAckMessage from raw packet data.
1859
    /// @param[in] data Pointer to the raw payload data.
1860
    /// @param[in] dataLen Length of the data buffer.
1861
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1862
    /// @param[in] packet Pointer to the parent packet.
1863
    DoIpDiagnosticMessageAck(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1864
1865
    /// @brief Constructs a DiagnosticAckMessage from specified field values.
1866
    /// @param[in] sourceAddress Address of the sending ECU.
1867
    /// @param[in] targetAddress Address of the receiving ECU.
1868
    /// @param[in] ackCode Acknowledgment code describing the result.
1869
    DoIpDiagnosticMessageAck(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode);
1870
1871
    /// @brief Gets the diagnostic acknowledgment code.
1872
    /// @return enum DoIpDiagnosticAckCodes describing the acknowledgment code.
1873
    DoIpDiagnosticAckCodes getAckCode() const;
1874
1875
    /// @brief Sets the acknowledgment code.
1876
    /// @param[in] code enum DoIpDiagnosticAckCodes describing the acknowledgment code.
1877
    void setAckCode(DoIpDiagnosticAckCodes code);
1878
1879
    /// @brief Returns a human-readable summary of the message.
1880
    std::string getSummary() const override;
1881
1882
    /// @brief Returns the DoIP payload type.
1883
    DoIpPayloadTypes getPayloadType() const override
1884
495
    {
1885
495
      return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_ACK;
1886
495
    }
1887
  };
1888
1889
  //~~~~~~~~~~~~~~~~~~~~~~~~~~|
1890
  // DoIpDiagnosticMessageNack|
1891
  //~~~~~~~~~~~~~~~~~~~~~~~~~~|
1892
1893
  /// @class DoIpDiagnosticMessageNack
1894
  /// @brief Represents a negative acknowledgment message in response to a DiagnosticMessage.
1895
  ///
1896
  /// This message is sent by a DoIP node when a diagnostic message is received but could not
1897
  /// be processed successfully. It may include the original message for reference.
1898
  class DoIpDiagnosticMessageNack : public DoIpDiagnosticResponseMessageBase
1899
  {
1900
  public:
1901
    /// @brief Constructs a DiagnosticNackMessage from raw packet data.
1902
    /// @param[in] data Pointer to the raw payload data.
1903
    /// @param[in] dataLen Length of the data buffer.
1904
    /// @param[in] prevLayer Pointer to the previous protocol layer.
1905
    /// @param[in] packet Pointer to the parent packet.
1906
    DoIpDiagnosticMessageNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
1907
1908
    /// @brief Constructs a DiagnosticNackMessage from specified field values.
1909
    /// @param[in] sourceAddress Address of the sending ECU.
1910
    /// @param[in] targetAddress Address of the receiving ECU.
1911
    /// @param[in] nackCode Negative acknowledgment code describing the failure.
1912
    DoIpDiagnosticMessageNack(uint16_t sourceAddress, uint16_t targetAddress,
1913
                              DoIpDiagnosticMessageNackCodes nackCode);
1914
1915
    /// @brief Gets the negative acknowledgment code.
1916
    /// @return enum DoIpDiagnosticMessageNackCodes describing the negative acknowledgment code.
1917
    DoIpDiagnosticMessageNackCodes getNackCode() const;
1918
1919
    /// @brief Sets the negative acknowledgment code.
1920
    /// @param[in] code enum DoIpDiagnosticMessageNackCodes describing the negative acknowledgment code.
1921
    void setNackCode(DoIpDiagnosticMessageNackCodes code);
1922
1923
    /// @brief Returns a human-readable summary of the message.
1924
    std::string getSummary() const override;
1925
1926
    /// @brief Returns the DoIP payload type.
1927
    DoIpPayloadTypes getPayloadType() const override
1928
580
    {
1929
580
      return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NACK;
1930
580
    }
1931
  };
1932
1933
}  // namespace pcpp