From a50cf6874bf82870fa35a4b70b4eb0f46106d2dd Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 8 Dec 2024 01:57:14 -0500 Subject: [PATCH 01/43] Add Layer Build and Validation for DoIP (Diagnostic over IP) Support --- 3rdParty/json/include/json.hpp | 4 +- Common++/header/Logger.h | 3 +- Examples/PcapSearch/README.md | 2 +- .../dirent-for-Visual-Studio/include/dirent.h | 2 +- Packet++/CMakeLists.txt | 6 + Packet++/header/DoIpEnumToString.h | 253 ++++ Packet++/header/DoIpEnums.h | 706 +++++++++ Packet++/header/DoIpLayer.h | 250 ++++ Packet++/header/DoIpLayerData.h | 855 +++++++++++ Packet++/header/HttpLayer.h | 1 - Packet++/header/ProtocolType.h | 5 + Packet++/src/DoIpLayer.cpp | 193 +++ Packet++/src/DoIpLayerData.cpp | 850 +++++++++++ Packet++/src/TcpLayer.cpp | 8 +- Packet++/src/UdpLayer.cpp | 4 + Pcap++/src/PcapRemoteDeviceList.cpp | 1 - Tests/Packet++Test/CMakeLists.txt | 1 + .../DoIpAliveCheckRequestPacket.dat | 1 + .../DoIpAliveCheckResponsePacket.dat | 1 + .../DoIpDiagnosticAckMessagePacket.dat | 1 + .../DoIpDiagnosticMessagePacket.dat | 1 + .../DoIpDiagnosticNackMessagePacket.dat | 1 + .../DoIpEntityStatusRequestPacket.dat | 1 + .../DoIpEntityStatusResponsePacket.dat | 1 + .../DoIpGenericHeaderNackPacket.dat | 1 + .../DoIpPowerModeRequestPacket.dat | 1 + .../DoIpPowerModeResponsePacket.dat | 1 + .../DoIpRoutingActivationRequestPacket.dat | 1 + .../DoIpRoutingActivationResponsePacket.dat | 1 + .../DoIpVehicleAnnouncementPacket.dat | 1 + ...pVehicleIdentificationRequestEIDPacket.dat | 1 + ...DoIpVehicleIdentificationRequestPacket.dat | 1 + ...pVehicleIdentificationRequestVINPacket.dat | 1 + Tests/Packet++Test/TestDefinition.h | 34 + Tests/Packet++Test/Tests/DoIpTests.cpp | 1330 +++++++++++++++++ Tests/Packet++Test/main.cpp | 33 + Tests/Pcap++Test/Common/PcapFileNamesDef.h | 1 + Tests/Pcap++Test/TestDefinition.h | 3 + Tests/Pcap++Test/Tests/PacketParsingTests.cpp | 19 + Tests/Pcap++Test/main.cpp | 2 +- 40 files changed, 4571 insertions(+), 11 deletions(-) create mode 100644 Packet++/header/DoIpEnumToString.h create mode 100644 Packet++/header/DoIpEnums.h create mode 100644 Packet++/header/DoIpLayer.h create mode 100644 Packet++/header/DoIpLayerData.h create mode 100644 Packet++/src/DoIpLayer.cpp create mode 100644 Packet++/src/DoIpLayerData.cpp create mode 100644 Tests/Packet++Test/PacketExamples/DoIpAliveCheckRequestPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpAliveCheckResponsePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpDiagnosticMessagePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpEntityStatusRequestPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpEntityStatusResponsePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpGenericHeaderNackPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpPowerModeRequestPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpPowerModeResponsePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpRoutingActivationRequestPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpRoutingActivationResponsePacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpVehicleAnnouncementPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestPacket.dat create mode 100644 Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat create mode 100644 Tests/Packet++Test/Tests/DoIpTests.cpp diff --git a/3rdParty/json/include/json.hpp b/3rdParty/json/include/json.hpp index 8b72ea6539..f7859fdc29 100644 --- a/3rdParty/json/include/json.hpp +++ b/3rdParty/json/include/json.hpp @@ -3406,7 +3406,7 @@ NLOHMANN_JSON_NAMESPACE_END template class AllocatorType = std::allocator, template class JSONSerializer = adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError + class BinaryType = std::vector, class CustomBaseClass = void> class basic_json; @@ -4251,7 +4251,6 @@ inline std::size_t concat_length(const char /*c*/, const Args& ... rest) template inline std::size_t concat_length(const char* cstr, const Args& ... rest) { - // cppcheck-suppress ignoredReturnValue return ::strlen(cstr) + concat_length(rest...); } @@ -19991,7 +19990,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #if JSON_DIAGNOSTICS JSON_TRY { - // cppcheck-suppress assertWithSideEffect JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) { return j.m_parent == this; diff --git a/Common++/header/Logger.h b/Common++/header/Logger.h index fafe6a9e37..b5854bdce2 100644 --- a/Common++/header/Logger.h +++ b/Common++/header/Logger.h @@ -114,7 +114,8 @@ namespace pcpp PcapLogModuleKniDevice, ///< KniDevice module (Pcap++) PcapLogModuleXdpDevice, ///< XdpDevice module (Pcap++) NetworkUtils, ///< NetworkUtils module (Pcap++) - NumOfLogModules + PacketLogModuleDoIpLayer, ///< DoipLayer module (Packet++) + NumOfLogModules, }; /** diff --git a/Examples/PcapSearch/README.md b/Examples/PcapSearch/README.md index 564c99476e..c4ff2f54dc 100644 --- a/Examples/PcapSearch/README.md +++ b/Examples/PcapSearch/README.md @@ -33,6 +33,6 @@ Using the utility -s search_criteria : Criteria to search in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1' -r file_name : Write a detailed search report to a file -e extension_list : Set file extensions to search. The default is searching '.pcap' and '.pcapng' files. - extnesions_list should be a comma-separated list of extensions, for example: pcap,net,dmp + extensions_list should be a comma-separated list of extensions, for example: pcap,net,dmp -v : Displays the current version and exists -h : Displays this help message and exits diff --git a/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h b/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h index 6adbbfdfa5..6bcd8059ab 100644 --- a/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h +++ b/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h @@ -846,7 +846,7 @@ extern "C" wcstr[n] = 0; } - /* Length of resuting multi-byte string WITH zero terminator */ + /* Length of resulting multi-byte string WITH zero terminator */ if (pReturnValue) { *pReturnValue = n + 1; diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index bab9488be6..331d1acc42 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -10,6 +10,8 @@ add_library( src/DnsLayer.cpp src/DnsResource.cpp src/DnsResourceData.cpp + src/DoIpLayerData.cpp + src/DoIpLayer.cpp src/EthDot3Layer.cpp src/EthLayer.cpp src/FtpLayer.cpp @@ -80,6 +82,10 @@ set(public_headers header/DnsResourceData.h header/DnsResource.h header/EthDot3Layer.h + header/DoIpEnumToString.h + header/DoIpEnums.h + header/DoIpLayer.h + header/DoIpLayerData.h header/EthLayer.h header/FtpLayer.h header/GreLayer.h diff --git a/Packet++/header/DoIpEnumToString.h b/Packet++/header/DoIpEnumToString.h new file mode 100644 index 0000000000..42500b1061 --- /dev/null +++ b/Packet++/header/DoIpEnumToString.h @@ -0,0 +1,253 @@ +#pragma once + +#include +#include "DoIpEnums.h" + +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib + */ +namespace pcpp +{ + /** + * @brief Mapping of DoIP Protocol Versions to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each version of the + * DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values + * to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringProtocolVersion{ + { DoIpProtocolVersion::defaultVersion, "Default value for vehicle identification request messages" }, + { DoIpProtocolVersion::version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, + { DoIpProtocolVersion::version02Iso2012, "DoIP ISO 13400-2:2012" }, + { DoIpProtocolVersion::version03Iso2019, "DoIP ISO 13400-2:2019" }, + { DoIpProtocolVersion::version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, + { DoIpProtocolVersion::reservedVersion, "Reserved" }, + }; + + /** + * @brief Mapping of DoIP Payload Types to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each payload type + * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values + * to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringPayloadType{ + { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, + { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, + "Vehicle announcement message / vehicle identification response message" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, + { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, + { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, + { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, + { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } + }; + + /** + * @brief Mapping of DoIP Activation Types to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each activation type + * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values + * to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringActivationTypes{ + { DoIpActivationTypes::Default, "Default" }, + { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, + { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, + }; + + /** + * @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each Nack code related to + * the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum + * values to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ + { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, + { DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, + { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, + { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, + { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, + }; + + /** + * @brief Mapping of DoIP Action Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each action code related to + * the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum + * values to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringActionCodes{ + { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, + { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } + }; + + /** + * @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each routing response code + * related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` enum + * values to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ + { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, "Routing activation denied due to unknown source address" }, + { DoIpRoutingResponseCodes::NO_FREE_SOCKET, + "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, + { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, + "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, + { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, + "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, + { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, "Routing activation denied due to missing authentication" }, + { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, "Routing activation denied due to rejected confirmation" }, + { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, + "Routing activation denied due to unsupported routing activation type" }, + { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, + "Routing activation denied due to request for encrypted connection via TLS" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, + { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } + }; + + /** + * @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code + * related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum + * values to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, + { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, + { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, + { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, + { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, + { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, + { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, + }; + + /** + * @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each power mode code + * related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum + * values to their corresponding descriptions. + */ + static const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ + { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, + { DoIpDiagnosticPowerModeCodes::READY, "ready" }, + { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, + }; + + /** + * @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for the entity status codes + * in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values + * to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." + */ + static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatus::NODE, "DoIp node" }, + { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, + }; + + /** + * @brief Mapping of DoIP Acknowledgement Codes to their string representations. + * + * This unordered map provides a human-readable description for the DoIP acknowledgement + * code `ACK`, which is used to confirm the successful reception or processing of a message. + */ + static const std::unordered_map DoIpEnumToStringAckCode{ + { DoIpDiagnosticAckCodes::ACK, "ACK" }, + }; + + /** + * @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. + * + * This unordered map provides a human-readable string for each synchronization status + * defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status + * values to their respective descriptions for logging or display purposes. + */ + static const std::unordered_map DoIpEnumToStringSyncStatus{ + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, + { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, + { DoIpSyncStatus::NON_INITIALIZED, "NULL" } + }; + + /** + * @brief Mapping of DoIP Payload Types to their corresponding payload lengths. + * + * This unordered map associates each `DoIpPayloadType` enum value with a specific max payload length. + * It provides the needed length for each payload type, ensuring proper handling of message sizes + * when building DoIP messages. + + inline static const std::unordered_map DoIpMapPayloadTypeToPayloadLength{ + { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, 1 }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, 0 }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, 6 }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, 17 }, + { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, 40 }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, 11 }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, 9 }, + { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, 0 }, + { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, 2 }, + { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, 0 }, + { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, 7 }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, 0 }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, 1 }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, 1452 }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, 5 }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, 4 } + }; */ + +} // namespace pcpp diff --git a/Packet++/header/DoIpEnums.h b/Packet++/header/DoIpEnums.h new file mode 100644 index 0000000000..78cc1648e0 --- /dev/null +++ b/Packet++/header/DoIpEnums.h @@ -0,0 +1,706 @@ +#pragma once + +#include +#include + +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib + */ +namespace pcpp +{ + /** + * @brief Represents the DoIP (Diagnostics over IP) protocol versions. + */ + enum class DoIpProtocolVersion : uint8_t + { + /** + * @brief Reserved protocol version. + * This value is used when the version is not specified or invalid. + */ + reservedVersion = 0x00U, + + /** + * @brief Protocol version 1, based on ISO 2010 specification. + */ + version01Iso2010 = 0x01U, + + /** + * @brief Protocol version 2, based on ISO 2012 specification. + */ + version02Iso2012 = 0x02U, + + /** + * @brief Protocol version 3, based on ISO 2019 specification. + */ + version03Iso2019 = 0x03U, + + /** + * @brief Protocol version 4, based on ISO 2019 AMD1 (Amendment 1) specification. + */ + version04Iso2019_AMD1 = 0x04U, + + /** + * @brief Default protocol version. + * Used for broadcast Vehicle Identification Request Messages. + */ + defaultVersion = 0xFFU + }; + + /** + * @brief Enum representing DoIP routing activation types. + * These values specify the type of routing activation used in DoIP (Diagnostic over IP). + */ + enum class DoIpActivationTypes : uint8_t + { + /** + * Default routing activation type. + * Used when no specific type is required. + */ + Default = 0x00U, + + /** + * WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. + * Used for vehicle diagnostics in compliance with WWH-OBD standards. + */ + WWH_OBD = 0x01U, + + /** + * Central security routing activation type. + * Used for secure communications involving a central security system. + */ + CENTRAL_SECURITY = 0xE0U + }; + + /** + * @brief Enum representing DoIP payload types. + * + * These payload types are defined as part of the DoIP (Diagnostic over IP) protocol + * and specify the type of message being transmitted. + */ + enum class DoIpPayloadTypes : uint16_t + { + /** + * Generic header negative acknowledgment. + * Indicates a failure or error in processing the generic header. + */ + GENERIC_HEADER_NEG_ACK = 0x0000U, + + /** + * Vehicle identification request. + * Used to request identification details of a vehicle. + */ + VEHICLE_IDENTIFICATION_REQUEST = 0x0001U, + + /** + * Vehicle identification request with EID. + * Requests identification using an external identifier (EID). + */ + VEHICLE_IDENTIFICATION_REQUEST_WITH_EID = 0x0002U, + + /** + * Vehicle identification request with VIN. + * Requests identification using the vehicle's VIN (Vehicle Identification Number). + */ + VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN = 0x0003U, + + /** + * Announcement message. + * Sent to announce the availability of a DoIP entity. + */ + ANNOUNCEMENT_MESSAGE = 0x0004U, + + /** + * Routing activation request. + * Initiates a routing activation procedure. + */ + ROUTING_ACTIVATION_REQUEST = 0x0005U, + + /** + * Routing activation response. + * Response to a routing activation request. + */ + ROUTING_ACTIVATION_RESPONSE = 0x0006U, + + /** + * Alive check request. + * Sent to verify that a DoIP entity is still operational. + */ + ALIVE_CHECK_REQUEST = 0x0007U, + + /** + * Alive check response. + * Response to an alive check request. + */ + ALIVE_CHECK_RESPONSE = 0x0008U, + + /** + * Entity status request. + * Used to request the status of a DoIP entity. + */ + ENTITY_STATUS_REQUEST = 0x4001U, + + /** + * Entity status response. + * Response to an entity status request. + */ + ENTITY_STATUS_RESPONSE = 0x4002U, + + /** + * Diagnostic power mode request. + * Requests the current power mode of a DoIP entity. + */ + DIAGNOSTIC_POWER_MODE_REQUEST = 0x4003U, + + /** + * Diagnostic power mode response. + * Response to a diagnostic power mode request. + */ + DIAGNOSTIC_POWER_MODE_RESPONSE = 0x4004U, + + /** + * Diagnostic message type. + * Represents a generic diagnostic message. + */ + DIAGNOSTIC_MESSAGE_TYPE = 0x8001U, + + /** + * Diagnostic message positive acknowledgment. + * Indicates successful processing of a diagnostic message. + */ + DIAGNOSTIC_MESSAGE_POS_ACK = 0x8002U, + + /** + * Diagnostic message negative acknowledgment. + * Indicates an error in processing a diagnostic message. + */ + DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U, + }; + + /** + * @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). + * + * These codes are used to indicate specific errors in the DoIP Generic Header. + */ + enum class DoIpGenericHeaderNackCodes : uint8_t + { + /** + * Incorrect pattern detected in the header. + * Indicates that the header does not follow the expected pattern. + */ + INCORRECT_PATTERN = 0x00U, + + /** + * Unknown payload type. + * The payload type in the message is not recognized. + */ + INKNOWN_PAYLOAD_TYPE = 0x01U, + + /** + * Message too large. + * The message size exceeds the allowed limit. + */ + MESSAGE_TOO_LARGE = 0x02U, + + /** + * Out of memory. + * There is insufficient memory available to process the message. + */ + OUT_OF_MEMORY = 0x03U, + + /** + * Invalid payload length. + * The payload length specified in the header is invalid. + */ + INVALID_PAYLOAD_LENGTH = 0x04U, + }; + + /** + * @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). + * + * These action codes specify the next steps required after receiving a DoIP announcement message. + * Some codes are reserved for future use by ISO standards. + */ + enum class DoIpActionCodes : uint8_t + { + /** + * No further action required. + * Indicates that no additional steps are needed after the announcement. + */ + NO_FURTHER_ACTION_REQUIRED = 0x00U, + + /** + * Reserved for ISO (0x01). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x01 = 0x01U, + + /** + * Reserved for ISO (0x02). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x02 = 0x02U, + + /** + * Reserved for ISO (0x03). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x03 = 0x03U, + + /** + * Reserved for ISO (0x04). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x04 = 0x04U, + + /** + * Reserved for ISO (0x05). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x05 = 0x05U, + + /** + * Reserved for ISO (0x06). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x06 = 0x06U, + + /** + * Reserved for ISO (0x07). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x07 = 0x07U, + + /** + * Reserved for ISO (0x08). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x08 = 0x08U, + + /** + * Reserved for ISO (0x09). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x09 = 0x09U, + + /** + * Reserved for ISO (0x0A). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0A = 0x0AU, + + /** + * Reserved for ISO (0x0B). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0B = 0x0BU, + + /** + * Reserved for ISO (0x0C). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0C = 0x0CU, + + /** + * Reserved for ISO (0x0D). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0D = 0x0DU, + + /** + * Reserved for ISO (0x0E). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0E = 0x0EU, + + /** + * Reserved for ISO (0x0F). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0F = 0x0FU, + + /** + * Routing activation required. + * Indicates that routing activation is needed after the announcement message. + */ + ROUTING_ACTIVATION_REQUIRED = 0x10U, + }; + + /** + * @brief Enum representing DoIP routing activation response codes (ISO 13400). + * + * These codes are used in response to routing activation requests, providing status + * or error information related to the request. + */ + enum class DoIpRoutingResponseCodes : uint8_t + { + /** + * Unknown source address. + * The source address provided in the request is not recognized. + */ + UNKNOWN_SOURCE_ADDRESS = 0x00U, + + /** + * No free socket. + * There are no available sockets to establish the connection. + */ + NO_FREE_SOCKET = 0x01U, + + /** + * Wrong source address. + * The source address provided in the request is invalid. + */ + WRONG_SOURCE_ADDRESS = 0x02U, + + /** + * Source address already registered. + * The provided source address has already been activated. + */ + SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, + + /** + * Missing authentication. + * The request is missing required authentication credentials. + */ + MISSING_AUTHENTICATION = 0x04U, + + /** + * Rejected confirmation. + * The confirmation of routing activation was rejected. + */ + REJECTED_CONFIRMATION = 0x05U, + + /** + * Unsupported activation type. + * The requested routing activation type is not supported. + */ + UNSUPPORTED_ACTIVATION_TYPE = 0x06U, + + /** + * Encrypted connection required (TLS). + * Indicates that the routing activation requires a secure TLS connection. + */ + ENCRYPTED_CONNECTION_TLS = 0x07U, + + /** + * Reserved for ISO (0x08). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x08 = 0x08U, + + /** + * Reserved for ISO (0x09). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x09 = 0x09U, + + /** + * Reserved for ISO (0x0A). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0A = 0x0AU, + + /** + * Reserved for ISO (0x0B). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0B = 0x0BU, + + /** + * Reserved for ISO (0x0C). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0C = 0x0CU, + + /** + * Reserved for ISO (0x0D). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0D = 0x0DU, + + /** + * Reserved for ISO (0x0E). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0E = 0x0EU, + + /** + * Reserved for ISO (0x0F). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0F = 0x0FU, + + /** + * Routing successfully activated. + * The routing activation request was processed successfully. + */ + ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, + + /** + * Confirmation required. + * Additional confirmation is required to complete the routing activation. + */ + CONFIRMATION_REQUIRED = 0x11U, + }; + + /** + * @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). + * + * These codes indicate reasons for rejecting or failing to process a diagnostic message + * in the DoIP protocol. + */ + enum class DoIpDiagnosticMessageNackCodes : uint8_t + { + /** + * Reserved for ISO (0x00). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x00 = 0x00U, + + /** + * Reserved for ISO (0x01). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x01 = 0x01U, + + /** + * Invalid source address. + * The source address specified in the message is invalid. + */ + INVALID_SOURCE_ADDRESS = 0x02U, + + /** + * Invalid target address. + * The target address specified in the message is invalid. + */ + INVALID_TARGET_ADDRESS = 0x03U, + + /** + * Message too large. + * The size of the message exceeds the maximum allowed limit. + */ + MESSAGE_TOO_LARGE = 0x04U, + + /** + * Out of memory. + * There is insufficient memory available to process the message. + */ + OUT_OF_MEMORY = 0x05U, + + /** + * Target unreachable. + * The specified target address cannot be reached. + */ + TARGET_UNREACHABLE = 0x06U, + + /** + * Unknown network. + * The message references a network that is not recognized or supported. + */ + UNKNOWN_NETWORK = 0x07U, + + /** + * Transport protocol error. + * An error occurred at the transport protocol level, preventing the message from being processed. + */ + TRANSPORT_PROTOCOL_ERROR = 0x08U, + }; + + /** + * @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). + * + * These codes indicate the diagnostic power mode status of a DoIP entity, + * providing information about its readiness for diagnostic operations. + */ + enum class DoIpDiagnosticPowerModeCodes : uint8_t + { + /** + * Not ready. + * The DoIP entity is not ready to perform diagnostic operations. + */ + NOT_READY = 0x00U, + + /** + * Ready. + * The DoIP entity is ready to perform diagnostic operations. + */ + READY = 0x01U, + + /** + * Not supported. + * The DoIP entity does not support diagnostic power mode reporting. + */ + NOT_SUPPORTED = 0x02U + }; + + /** + * @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). + * + * These codes are used to acknowledge the receipt or processing of diagnostic messages + * in the DoIP protocol. + */ + enum class DoIpDiagnosticAckCodes : uint8_t + { + /** + * Acknowledgment. + * Indicates successful receipt or acknowledgment of a diagnostic message. + */ + ACK = 0x00U + }; + + /** + * @brief Enum representing DoIP entity status response codes (ISO 13400). + * + * These codes are used to indicate the role or type of a DoIP entity in the network. + */ + enum class DoIpEntityStatus : uint8_t + { + /** + * Gateway. + * The entity functions as a gateway, facilitating communication between networks. + */ + GATEWAY = 0x00U, + + /** + * Node. + * The entity functions as an individual node within the DoIP network. + */ + NODE = 0x01U + }; + + enum class DoIpSyncStatus : uint8_t + { + /** + * VIN and/or GID are synchronized. + */ + VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, + + /** + * Reserved for ISO (0x01). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x01 = 0x01U, + + /** + * Reserved for ISO (0x02). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x02 = 0x02U, + + /** + * Reserved for ISO (0x03). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x03 = 0x03U, + + /** + * Reserved for ISO (0x04). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x04 = 0x04U, + + /** + * Reserved for ISO (0x05). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x05 = 0x05U, + + /** + * Reserved for ISO (0x06). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x06 = 0x06U, + + /** + * Reserved for ISO (0x07). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x07 = 0x07U, + + /** + * Reserved for ISO (0x08). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x08 = 0x08U, + + /** + * Reserved for ISO (0x09). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x09 = 0x09U, + + /** + * Reserved for ISO (0x0A). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0A = 0x0AU, + + /** + * Reserved for ISO (0x0B). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0B = 0x0BU, + /** + * Reserved for ISO (0x0C). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0C = 0x0CU, + + /** + * Reserved for ISO (0x0D). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0D = 0x0DU, + + /** + * Reserved for ISO (0x0E). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0E = 0x0EU, + + /** + * Reserved for ISO (0x08). + * Reserved for future use as per ISO standards. + */ + RESERVED_ISO_0x0F = 0x0FU, + + /** + * VIN and/or GID are not synchronized. + */ + VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, + + /** + * Check whether this field is initialised or not + */ + NON_INITIALIZED + }; + + /** + * @brief Enum representing DoIP diagnostic ports (ISO 13400). + * + * These ports are used for communication in the DoIP protocol over different transport layers. + */ + enum class DoIpPorts : uint16_t + { + /** + * UDP Port. + * The standard port for DoIP communication over UDP. + */ + UDP_PORT = 13400U, + + /** + * TCP Port. + * The standard port for DoIP communication over TCP. + */ + TCP_PORT = 13400U, + + /** + * TLS Port. + * The standard port for DoIP communication over a secure TLS connection. + */ + TLS_PORT = 3496U + }; + +} // namespace pcpp diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h new file mode 100644 index 0000000000..cb5c67cb85 --- /dev/null +++ b/Packet++/header/DoIpLayer.h @@ -0,0 +1,250 @@ +#pragma once + +#include +#include +#include "Layer.h" +#include "IpAddress.h" +#include "MacAddress.h" +#include "Logger.h" +#include "GeneralUtils.h" +#include "DoIpLayerData.h" + +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib + */ +namespace pcpp +{ + /** + * @struct doiphdr + * Represents an DoIP protocol header + */ +#pragma pack(push, 1) + struct doiphdr + { + /** DoIP version (DOIPV) */ + uint8_t protocolVersion; + /** DoIP invert version (DOIPIV). Inverse of protocol version */ + uint8_t invertProtocolVersion; + /** DoIP payload type (DOIPT)*/ + uint16_t payloadType; + /** DoIP content payload length (DOIPL)*/ + uint32_t payloadLength; + }; +#pragma pack(pop) + + /** + * @class DoipLayer + * Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported + */ + class DoIpLayer : public Layer + { + // class DoIpLayerData; + public: + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data (will be casted to @ref doiphdr) + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet, DOIP) + {} + + /** + * A constructor that creates an generic doip layer and set header and payload fields + * @param[in] Fields DoIpMessageFields contains all doipMessage specification based on its payload type + */ + DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); + + /** + * A constructor that create a doip announcement message with all + * zeros for vin, eid, gid and no further action required + */ + DoIpLayer(); + + /** + * init doip layer with all zeros with size of doip header + */ + void initLayer(); + + /** + * A destructor for DoIpLayer class + */ + ~DoIpLayer() override {}; + + /** + * Get a pointer to the DoIP header. Notice this points directly to the data, so every change will change the + * actual packet data + * @return A pointer to the @ref doiphdr + */ + doiphdr* getDoIpHeader() const + { + return reinterpret_cast(m_Data); + } + /** + * Check the integrity of protocol version in doip header + * @return true if version has no integration errors + */ + bool resolveProtocolVersion() const; + + /** + * Check the integrity of length field in doip header + * @return true if length represent the exact payload arg struct size + */ + bool resolvePayloadLength() const; + + /** + * Get the version of DOIP protocol + * @return DoIpProtocolVersion presenting the used protocol version (DOIPV) + */ + DoIpProtocolVersion getProtocolVersion() const; + + /** + * Get the version of DOIP protocol + * @return string presentation the used protocol version (DOIPV) + */ + std::string getProtocolVersionAsStr() const; + + /** + * Set the version of DOIP protocol + * @param[in] version the version of DOIP protocol to set, restricted to existent doip version + */ + void setProtocolVersion(DoIpProtocolVersion version); + + /** + * Get the invert version of DOIP protocol + * @return A uint8_t presenting the used protocol invert version (DOIPV) + */ + uint8_t getInvertProtocolVersion() const; + + /** + * Set the invert protocol version of DOIP protocol + * @param[in] version the invert version of DOIP protocol to set + */ + void setInvertProtocolVersion(uint8_t iVersion); + + /** + * Get the doip payload type + * @return DoIpPayloadTypes presenting the message doip payload type + */ + DoIpPayloadTypes getPayloadType() const; + + /** + * Get the doip payload type as string + * @return uint16_t presenting the message doip payload type as string + */ + std::string getPayloadTypeAsStr() const; + + /** + * Set the doip payload type + * @param[in] payloadType the payload type to set + */ + void setPayloadType(DoIpPayloadTypes payloadType); + + /** + * Get the doip payload length + * @return uint32_t presenting the length of doip paylad not including the header + */ + uint32_t getPayloadLength() const; + + /** + * Set the doip payload length + * @param[in] length the doip payload length to set + */ + void setPayloadength(uint32_t length); + + /** + * copy data from msgFields to dest + * @param[in] dest pointer to where start copying + * @param[in] msgFields the doip Fields to copy + */ + void serializeData(uint8_t* dest, std::vector data); + + /** + * A static method that checks whether a port is considered as a DOIP port + * @param[in] port The port number to check + * @return True if this is a DOIP port number, false otherwise + */ + static inline bool isDoIpPort(uint16_t port); + + /** + * A static method that validates the input data + * @param[in] data The pointer to the beginning of a byte stream of an DOIP layer + * @param[in] dataLen The length of the byte stream + * @return True if the data is valid and can represent an DOIP layer + */ + static inline bool isDataValid(const uint8_t* data, size_t dataLen); + + /** + * @brief Builds the DoIP layer based on the payload type and provided data. + * + * This function configures the DoIP layer with the appropriate payload type, payload length, + * and data, depending on the specified payload type. If the payload type does not require + * additional data, the payload length is set to zero. For payloads that require data, the data + * is serialized and added to the layer. + * + * @param type The DoIP payload type to set for this layer. + * @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. + * This parameter can be nullptr for payload types that do not require additional data. + * + * @note If the payload type requires data and the `data` parameter is `nullptr`, an error message + * is logged, and the function does not build the layer. + */ + void buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); + + /** + * @brief Resolves and validates the DoIP layer. + * + * This function validates the protocol version and payload length of the DoIP layer. + * If either validation fails, an error is logged, and the function returns `false`. + * + * @return `true` if both the protocol version and payload length are valid; + * otherwise, `false`. + * + * @note This function is typically used to ensure the integrity of the DoIP layer + * before further processing or transmission. + */ + bool resolveLayer() const; + + // implement abstract methods + + /** + * TODO, parse UDS layer + */ + void parseNextLayer() override + {} + + /** + * @return The size of @ref doiphdr + attached fields length + */ + size_t getHeaderLen() const override + { + return m_DataLen; + } + + std::string toString() const override; + + void computeCalculateFields() override {}; + + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelTransportLayer; + } + }; + + // inline methods definition + inline bool DoIpLayer::isDoIpPort(uint16_t port) + { + return ((DoIpPorts)port == DoIpPorts::UDP_PORT || (DoIpPorts)port == DoIpPorts::TCP_PORT || + (DoIpPorts)port == DoIpPorts::TLS_PORT); + } + + inline bool DoIpLayer::isDataValid(const uint8_t* data, size_t dataLen) + { + return (data && dataLen >= sizeof(doiphdr)); + } +} // namespace pcpp diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h new file mode 100644 index 0000000000..46db686c85 --- /dev/null +++ b/Packet++/header/DoIpLayerData.h @@ -0,0 +1,855 @@ +#pragma once + +#include +#include +#include +#include "Logger.h" +#include "GeneralUtils.h" +#include "DoIpEnumToString.h" + +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus library + */ +namespace pcpp +{ +/** + * @brief Length of the External Identifier (EID) field. + */ +#define DOIP_EID_LEN 6 + +/** + * @brief Length of the Group Identifier (GID) field. + */ +#define DOIP_GID_LEN 6 + +/** + * @brief Length of the Vehicle Identification Number (VIN) field. + */ +#define DOIP_VIN_LEN 17 + +/** + * @brief Length of the Reserved ISO field. + */ +#define DOIP_RESERVED_ISO_LEN 4 + +/** + * @brief Length of the Reserved OEM field. + */ +#define DOIP_RESERVED_OEM_LEN 4 + + // forward declaration for DoIpLayer class + class DoIpLayer; + + /** + * \brief A pure abstract class representing the basic structure of DoIP messages. + * + * This interface defines methods to retrieve the type, string representation, + * and binary data of DoIP messages. All DoIP message classes must implement this interface. + */ + class IDoIpMessageData + { + public: + virtual ~IDoIpMessageData() = default; + + /** + * \brief Returns the type of the DoIP message. + * \return The type of the message as a `DoIpPayloadTypes` enum. + */ + virtual DoIpPayloadTypes getType() const = 0; + + /** + * \brief Converts the message data to a human-readable string. + * \return The string representation of the message. + */ + virtual std::string toString() const = 0; + + /** + * \brief Retrieves the raw binary data of the message. + * \return The message data as a vector of bytes. + */ + virtual std::vector getData() const = 0; + + /** + * \brief build IDoIpMessageData from DoIpLayer + * @param[in] doipLayer pointer to doipLayer to retrieve data from + * \return true if encapsulating process is done successufly else false. + * + * @exception Logs an error and returns `false` if: + * - The input layer is null. + * - The payload type of doipLayer does not match the expected type for IDoIpMessageData. + * - The input data length is insufficient for parsing all required fields. + */ + virtual bool buildFromLayer(DoIpLayer* doipLayer) = 0; + }; + + /** + * @class RoutingActivationRequestData + * \brief Represents a Routing Activation Request message in DoIP. + * + * This class encapsulates data for a Routing Activation Request message, + * including source address, activation type, and reserved fields. + */ + class RoutingActivationRequestData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the RoutingActivationRequestData class. + * + * Initializes a `RoutingActivationRequestData` instance with default values: + * - `sourceAddress` is set to `0x0000`. + * - `activationType` is set to `DoIpActivationTypes::Default`. + * - `reservedIso` and `reservedOem` fields are zero-initialized. + * This constructor provides a default initialization state for routing activation request + * data, ensuring compliance with the DoIP protocol requirements. + */ + RoutingActivationRequestData(); + + uint16_t sourceAddress; /**< Source address of the message. */ + DoIpActivationTypes activationType; /**< The activation type (e.g., activate, deactivate). */ + std::array reservedIso; /**< Reserved ISO bytes. */ + std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Routing Activation Request message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Routing Activation Request data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Routing Activation Request payload type. It extracts the source address, activation + * type, reserved ISO bytes, and optionally reserved OEM bytes if present. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Routing Activation Request data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note This method overrides the base class implementation and adds specific parsing + * logic for the Routing Activation Request message. + * + * The following fields are parsed: + * - `sourceAddress`: The source address of the message. + * - `activationType`: The type of activation requested. + * - `reservedIso`: Reserved bytes as defined by ISO specifications. + * - `reservedOem`: Reserved bytes as defined by OEM specifications, only if present. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class RoutingActivationResponseData + * \brief Represents a Routing Activation Response message in DoIP. + * + * This class encapsulates data for a Routing Activation Response message, + * including logical address, source address, response code, and reserved fields. + */ + class RoutingActivationResponseData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the RoutingActivationResponseData class. + * Initializes a `RoutingActivationResponseData` instance with default values: + * - `logicalAddressExternalTester` is set to `0x0000`. + * - `sourceAddress` is set to `0x0000`. + * - `responseCode` is set to DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED. + * - `reservedIso` fields is zero-initialized. + * This constructor provides a default initialization state for routing activation response + * data, ensuring compliance with the DoIP protocol requirements. + */ + RoutingActivationResponseData(); + + uint16_t logicalAddressExternalTester; /**< Logical address of the external tester. */ + uint16_t sourceAddress; /**< Source address of the message. */ + DoIpRoutingResponseCodes responseCode; /**< Response code indicating success or failure. */ + std::array reservedIso; /**< Reserved ISO bytes. */ + std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Routing Activation Response message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + + std::vector getData() const override; + /** + * @brief Parses the Routing Activation Response data from a DoIpLayer. + * + * This method validates and extracts the necessary fields from the provided + * DoIpLayer. It ensures the layer corresponds to the Routing Activation Response + * payload type and parses fields including the logical tester address, source + * address, response code, and reserved fields. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Routing Activation Response data. + * @return `true` if parsing was successful, `false` otherwise. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class GenericHeaderNackData + * \brief Represents a Generic Header Negative Acknowledgment message in DoIP. + * + * This class encapsulates data for a Generic Header NACK message, including + * the NACK code to indicate the failure. + */ + class GenericHeaderNackData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the GenericHeaderNackData class. + * + * This constructor initializes a `GenericHeaderNackData` instance with default values: + * - `genericNackCode` is set to `DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH`. + */ + GenericHeaderNackData(); + + DoIpGenericHeaderNackCodes genericNackCode; /**< The NACK code indicating the error. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Generic Header NACK message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + + std::vector getData() const override; + /** + * @brief Parses and initializes the Generic Header NACK data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Generic Header NACK payload type. It extracts the `genericNackCode` field from the layer. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Generic Header NACK data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method checks for null pointers and verifies that the payload type matches + * `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. Logs an error in case of invalid data. + * + * The following field is parsed: + * - `genericNackCode`: The NACK code indicating the type of error. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class VehicleIdentificationRequestEIDData + * \brief Represents a Vehicle Identification Request with EID message in DoIP. + * + * This class encapsulates data for a Vehicle Identification Request message + * that includes the Electronic Identifier (EID). + */ + class VehicleIdentificationRequestEIDData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the VehicleIdentificationRequestEIDData class. + * + * This constructor initializes a `VehicleIdentificationRequestEIDData` instance with default values: + * - `eid` (Entity Identifier) is initialized to all zeros. + */ + VehicleIdentificationRequestEIDData(); + + std::array eid; /**< Electronic Identifier (EID). */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Vehicle Identification Request EID message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Vehicle Identification Request with EID data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Vehicle Identification Request with EID payload type. It extracts the EID field from the layer. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Identification Request with EID data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method checks for null pointers and verifies that the payload type matches + * `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. Logs an error if the data is invalid. + * + * The following field is parsed: + * - `eid`: The EID (Extended Identifier), extracted as a byte array of length `DOIP_EID_LEN`. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class VehicleIdentificationRequestVINData + * \brief Represents a Vehicle Identification Request with VIN message in DoIP. + * + * This class encapsulates data for a Vehicle Identification Request message + * that includes the Vehicle Identification Number (VIN). + */ + class VehicleIdentificationRequestVINData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the VehicleIdentificationRequestVINData class. + * + * This constructor initializes a `VehicleIdentificationRequestVINData` instance with default values: + * - `vin` (Vehicle Identification Number) is initialized to all zeros. + */ + VehicleIdentificationRequestVINData(); + + std::array vin; /**< Vehicle Identification Number (VIN). */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Vehicle Identification Request VIN message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Vehicle Identification Request with VIN data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Vehicle Identification Request with VIN payload type. It extracts the VIN (Vehicle Identification Number) + * field from the payload data and populates the class instance. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Identification Request with VIN data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. + * - Checks that the data length is sufficient to extract the VIN field. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following field is parsed: + * - `vin`: The Vehicle Identification Number (VIN), extracted as a byte array of length `DOIP_VIN_LEN`. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class VehicleAnnouncementData + * \brief Represents a Vehicle Announcement message in DoIP. + * + * This class encapsulates data for a Vehicle Announcement message, including + * VIN, logical address, EID, GID, and further action required. + */ + class VehicleAnnouncementData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the VehicleAnnouncementData class. + * + * This constructor initializes a `VehicleAnnouncementData` instance with default values: + * - `vin` is initialized to all zeros. + * - `logicalAddress` is set to `0`. + * - `eid` (Entity Identifier) is initialized to all zeros. + * - `gid` (Group Identifier) is initialized to all zeros. + * - `furtherActionRequired` is set to `DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED`. + * - `syncStatus` is set to `DoIpSyncStatus::NON_INITIALIZED`, indicating that the sync status is uninitialized. + */ + VehicleAnnouncementData(); + + std::array vin; /**< Vehicle Identification Number (VIN). */ + uint16_t logicalAddress; /**< Logical address of the vehicle. */ + std::array eid; /**< Electronic Identifier (EID). */ + std::array gid; /**< Group Identifier (GID). */ + DoIpActionCodes furtherActionRequired; /**< Action required after the announcement. */ + DoIpSyncStatus syncStatus; /**< version and invert version are synchronized */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Vehicle Announcement message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Vehicle Announcement data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Announcement Message payload type. It extracts fields such as VIN, logical address, EID, GID, + * further action required, and synchronization status from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Announcement data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. + * - Checks that the data length is sufficient to extract all required fields. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following fields are parsed: + * - `vin`: Vehicle Identification Number (VIN). + * - `logicalAddress`: Logical address of the vehicle. + * - `eid`: End Identifier. + * - `gid`: Group Identifier. + * - `furtherActionRequired`: Further action required code. + * - `syncStatus`: VIN/GID synchronization status (if present). + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class AliveCheckResponseData + * \brief Represents an Alive Check Response message in DoIP. + * + * This class encapsulates data for an Alive Check Response message, + * including the source address. + */ + class AliveCheckResponseData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the AliveCheckResponseData class. + * + * This constructor initializes an `AliveCheckResponseData` instance with default values: + * - `sourceAddress` is set to `0x0000`. + */ + AliveCheckResponseData(); + + uint16_t sourceAddress; /**< Source address of the Alive Check Response message. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Alive Check Response message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Alive Check Response data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Alive Check Response payload type. It extracts the `sourceAddress` field from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Alive Check Response data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. + * - Checks that the data length is sufficient to extract the `sourceAddress`. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following field is parsed: + * - `sourceAddress`: The source address of the response. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class DiagnosticPowerModeResponseData + * \brief Represents a Diagnostic Power Mode Response message in DoIP. + * + * This class encapsulates data for a Diagnostic Power Mode Response message, + * including a power mode code indicating the current power mode. + */ + class DiagnosticPowerModeResponseData : public IDoIpMessageData + { + public: + /** @brief Default constructor for the DiagnosticPowerModeResponseData class. + * + * Initializes a DiagnosticPowerModeResponseData instance with the power mode + * response code set to `NOT_READY`. This indicates that the system is not yet + * ready to respond to diagnostic power mode requests. + */ + DiagnosticPowerModeResponseData(); + + DoIpDiagnosticPowerModeCodes powerModeCode; /**< Code representing the power mode. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Diagnostic Power Mode Response message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Diagnostic Power Mode Response data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Diagnostic Power Mode Response payload type. It extracts the `powerModeCode` field from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Power Mode Response data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. + * - Checks that the data length is sufficient to extract the `powerModeCode`. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following field is parsed: + * - `powerModeCode`: The diagnostic power mode response code. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class EntityStatusResponseData + * \brief Represents an Entity Status Response message in DoIP. + * + * This class encapsulates data for an Entity Status Response message, + * including status, maximum concurrent sockets, open sockets, and maximum data size. + */ + class EntityStatusResponseData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the EntityStatusResponseData class. + * + * Initializes an `EntityStatusResponseData` instance with the following default values: + * - `status`: Set to `DoIpEntityStatus::GATEWAY`, indicating the entity is acting as a gateway. + * - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. + * - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. + * - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object + * creation by : + * @code + * EntityStatusResponseData data; + * data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, + * 0x03}) + */ + EntityStatusResponseData(); + + DoIpEntityStatus nodeType; /**< Status of the entity. */ + uint8_t maxConcurrentSockets; /**< Maximum number of concurrent sockets. */ + uint8_t currentlyOpenSockets; /**< Number of currently open sockets. */ + std::unique_ptr> + maxDataSize; /**< Maximum data size that can be handled (4 bytes optional). */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Entity Status Response message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Entity Status Response data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Entity Status Response payload type. It extracts fields such as `nodeType`, + * `maxConcurrentSockets`, `currentlyOpenSockets`, and optionally `maxDataSize` from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Entity Status Response data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. + * - Checks that the data length is sufficient for the fixed fields and optional `maxDataSize`. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following fields are parsed: + * - `nodeType`: Entity status indicating the role of the entity. + * - `maxConcurrentSockets`: Maximum allowed concurrent sockets. + * - `currentlyOpenSockets`: Number of currently open sockets. + * - `maxDataSize` (optional): Maximum data size supported (4 bytes). + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class DiagnosticMessageData + * \brief Represents a Diagnostic Message in DoIP. + * This class encapsulates data for a Diagnostic Message, including source + * and target addresses, as well as diagnostic data. + */ + class DiagnosticMessageData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the DiagnosticMessageData class. + * + * Initializes a `DiagnosticMessageData` instance with the following default values: + * - `sourceAddress`: Set to `0x0000`. + * - `targetAddress`: Set to `0x0000`. + * - `diagnosticData`: Initialized to `{0x22, 0xf1, 0x68}` as a default diagnostic payload. + */ + DiagnosticMessageData(); + + uint16_t sourceAddress; /**< Source address of the message. */ + uint16_t targetAddress; /**< Target address for the diagnostic message. */ + std::vector diagnosticData; /**< Diagnostic message data with dynamic length*/ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Diagnostic Message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Diagnostic Message data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Diagnostic Message payload type. It extracts fields such as `sourceAddress`, + * `targetAddress`, and `diagnosticData` from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Message data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. + * - Checks that the data length is sufficient for the fixed fields and dynamic `diagnosticData`. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following fields are parsed: + * - `sourceAddress`: Source address of the diagnostic message (2 bytes). + * - `targetAddress`: Target address of the diagnostic message (2 bytes). + * - `diagnosticData`: Variable length data representing the diagnostic payload. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class DiagnosticAckMessageData + * \brief Represents a Diagnostic Acknowledgment Message in DoIP. + * + * This class encapsulates data for a Diagnostic Acknowledgment Message, + * including source and target addresses, as well as the acknowledgment code. + */ + class DiagnosticAckMessageData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the DiagnosticAckMessageData class. + * + * Initializes a `DiagnosticAckMessageData` instance with the following default values: + * - `sourceAddress`: Set to `0x0000`. + * - `targetAddress`: Set to `0x0000`. + * - `ackCode`: Set to `DoIpDiagnosticAckCodes::ACK`. + * - `previousMessage`: Initialized to `{0x22, 0xf1, 0x01, 0x02}`. + */ + DiagnosticAckMessageData(); + + uint16_t sourceAddress; /**< Source address of the acknowledgment message. */ + uint16_t targetAddress; /**< Target address of the acknowledgment message. */ + DoIpDiagnosticAckCodes ackCode; /**< Acknowledgment code. */ + std::vector previousMessage; /**< Previous acknowlged message. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Diagnostic Acknowledgment Message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Parses and initializes the Diagnostic Acknowledgment Message data from a DoIpLayer. + * + * This method validates the provided DoIpLayer to ensure it corresponds to the + * Diagnostic Acknowledgment Message payload type. It extracts fields such as `sourceAddress`, + * `targetAddress`, `ackCode`, and `previousMessage` from the payload data. + * + * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Acknowledgment Message data. + * @return `true` if parsing and initialization were successful, `false` otherwise. + * + * @note The method performs the following checks: + * - Ensures the `doipLayer` is not null. + * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. + * - Checks that the data length is sufficient for the fixed fields and the dynamic `previousMessage`. + * + * Logs errors if the data is invalid or the payload is incompatible. + * + * The following fields are parsed: + * - `sourceAddress`: Source address of the acknowledgment message (2 bytes). + * - `targetAddress`: Target address of the acknowledgment message (2 bytes). + * - `ackCode`: Acknowledgment code (1 byte, converted from enum). + * - `previousMessage`: std::vector representing the previous message. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; + + /** + * @class DiagnosticNackMessageData + * \brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. + * + * This class encapsulates data for a Diagnostic Negative Acknowledgment + * Message, including source and target addresses, as well as the NACK code. + */ + class DiagnosticNackMessageData : public IDoIpMessageData + { + public: + /** + * @brief Default constructor for the DiagnosticNackMessageData class. + * + * Initializes a `DiagnosticNackMessageData` instance with default values: + * - `sourceAddress` is set to `0x0000`. + * - `targetAddress` is set to `0x0000`. + * - `nackCode` is set to `DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS`. + * - `previousMessage` is set to {0x22, 0xf1, 01, 0x02} as the non acknowledged diagnostic + * message starts with these four bytes + */ + DiagnosticNackMessageData(); + + uint16_t sourceAddress; /**< Source address of the NACK message. */ + uint16_t targetAddress; /**< Target address of the NACK message. */ + DoIpDiagnosticMessageNackCodes nackCode; /**< Negative acknowledgment code. */ + std::vector previousMessage; /**< Previous acknowlged message. */ + + /** + * \brief Returns the type of the message. + * \return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. + */ + DoIpPayloadTypes getType() const override; + + /** + * \brief Converts the message data to a human-readable string. + * \return A string representation of the Diagnostic Negative Acknowledgment Message. + */ + std::string toString() const override; + + /** + * \brief Retrieves the raw binary data of the message. + * \return A vector of bytes representing the message data. + */ + std::vector getData() const override; + + /** + * @brief Builds the message data from the given DoIpLayer. + * + * This method parses the `DoIpLayer` to extract the relevant message data, including: + * - sourceAddress + * - targetAddress + * - nackCode + * - previousMessage (optional) + * + * @param doipLayer The layer containing the message data to be parsed. + * @return `true` if the message was successfully built from the layer, `false` otherwise. + */ + bool buildFromLayer(DoIpLayer* doipLayer) override; + }; +} // namespace pcpp diff --git a/Packet++/header/HttpLayer.h b/Packet++/header/HttpLayer.h index cc22499b44..c9682a9901 100644 --- a/Packet++/header/HttpLayer.h +++ b/Packet++/header/HttpLayer.h @@ -437,7 +437,6 @@ namespace pcpp HttpResponseStatusCode() = default; - // cppcheck-suppress noExplicitConstructor /** * @brief Construct HttpResponseStatusCode from Value enum * @param[in] statusCode the status code enum diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index bb775fb9ff..9d6d13e5ae 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -247,6 +247,11 @@ namespace pcpp */ const ProtocolType ESP = 37; + /** + * Diagnostic over IP protocol (DOIP) + */ + const ProtocolType DOIP = 38; + /** * IPSec protocol family (AH and ESP protocols) */ diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp new file mode 100644 index 0000000000..fca1085f91 --- /dev/null +++ b/Packet++/src/DoIpLayer.cpp @@ -0,0 +1,193 @@ +#define LOG_MODULE PacketLogModuleDoipLayer + +#include "DoIpLayer.h" +#include "Packet.h" +#include "PayloadLayer.h" +#include "EndianPortable.h" +#include +#include +#include + +namespace pcpp +{ + DoIpLayer::DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data) + { + initLayer(); + setProtocolVersion(version); + setInvertProtocolVersion(~(static_cast(version))); + buildLayer(type, data); + } + DoIpLayer::DoIpLayer() + { + VehicleAnnouncementData data; + initLayer(); + setProtocolVersion(DoIpProtocolVersion::version03Iso2019); + setInvertProtocolVersion(~(static_cast(DoIpProtocolVersion::version03Iso2019))); + buildLayer(DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &data); + } + + DoIpProtocolVersion DoIpLayer::getProtocolVersion() const + { + return static_cast(getDoIpHeader()->protocolVersion); + } + + std::string DoIpLayer::getProtocolVersionAsStr() const + { + return DoIpEnumToStringProtocolVersion.at(getProtocolVersion()); + } + + void DoIpLayer::setProtocolVersion(DoIpProtocolVersion version) + { + getDoIpHeader()->protocolVersion = static_cast(version); + } + + uint8_t DoIpLayer::getInvertProtocolVersion() const + { + return getDoIpHeader()->invertProtocolVersion; + } + + void DoIpLayer::setInvertProtocolVersion(uint8_t iVersion) + { + getDoIpHeader()->invertProtocolVersion = iVersion; + } + + DoIpPayloadTypes DoIpLayer::getPayloadType() const + { + return static_cast(be16toh(getDoIpHeader()->payloadType)); + } + + void DoIpLayer::setPayloadType(DoIpPayloadTypes type) + { + getDoIpHeader()->payloadType = htobe16((uint16_t)type); + } + + std::string DoIpLayer::getPayloadTypeAsStr() const + { + return DoIpEnumToStringPayloadType.at(getPayloadType()); + } + + uint32_t DoIpLayer::getPayloadLength() const + { + return htobe32(getDoIpHeader()->payloadLength); + } + + void DoIpLayer::setPayloadength(uint32_t Payloadength) + { + getDoIpHeader()->payloadLength = be32toh(Payloadength); + } + + bool DoIpLayer::resolveProtocolVersion() const + { + DoIpProtocolVersion version = getProtocolVersion(); + uint8_t inVersion = getInvertProtocolVersion(); + DoIpPayloadTypes type = getPayloadType(); + + // Idea is token from wireshark + if (!(version == DoIpProtocolVersion::version01Iso2010 || version == DoIpProtocolVersion::version02Iso2012 || + version == DoIpProtocolVersion::version03Iso2019 || + version == DoIpProtocolVersion::version04Iso2019_AMD1 || + (version == DoIpProtocolVersion::defaultVersion && + (type >= DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST && + type <= DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN)))) + { + PCPP_LOG_ERROR("Invalid/unsupported DoIP version!"); + return false; + } + if ((uint8_t)(version) != (uint8_t) ~(inVersion)) + { + PCPP_LOG_ERROR("Version and invert version are not synchronised !"); + return false; + } + return true; + } + + bool DoIpLayer::resolvePayloadLength() const + { + uint32_t length = getPayloadLength(); + + if (m_DataLen < sizeof(doiphdr)) + { + PCPP_LOG_ERROR("Payload length is smaller than the minimum header size"); + return false; + } + + if (length != (m_DataLen - sizeof(doiphdr))) + { + PCPP_LOG_ERROR("Payload length does not match expected size"); + return false; + } + + return true; + } + bool DoIpLayer::resolveLayer() const + { + // Validate the protocol version and payload length + if (!resolveProtocolVersion() || !resolvePayloadLength()) + { + PCPP_LOG_ERROR("Failed to Parse DoIP layer"); + return false; + } + return true; + } + + std::string DoIpLayer::toString() const + { + std::stringstream os; + DoIpProtocolVersion version = getProtocolVersion(); + DoIpPayloadTypes type = getPayloadType(); + uint32_t length = getPayloadLength(); + + os << "DOIP Layer:" << std::endl; + os << "Protocol Version: " << DoIpEnumToStringProtocolVersion.at(version) << std::hex << " (0x" + << unsigned((uint8_t)version) << ")" << std::endl; + os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << htole16((uint16_t)type) << ")" + << std::endl; + os << std::dec << "Payload Length: " << length << std::endl; + + return os.str(); + } + + void DoIpLayer::serializeData(uint8_t* dest, std::vector data) + { + memcpy(dest, data.data(), data.size()); + } + + void DoIpLayer::initLayer() + { + m_DataLen = sizeof(doiphdr); + m_Protocol = DOIP; + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + } + + void DoIpLayer::buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data) + { + switch (type) + { + case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: + case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: + setPayloadType(type); + setPayloadength(0); + break; + default: + // Payload handling for rest of types + { + if (data == nullptr) + { + PCPP_LOG_ERROR("Cannot build Layer with empty Data"); + break; + } + size_t payloadSize = data->getData().size(); + size_t headerLength = sizeof(doiphdr); + + setPayloadType(data->getType()); + setPayloadength(payloadSize); + extendLayer(headerLength, payloadSize); + serializeData(m_Data + headerLength, data->getData()); + break; + } + } + } +} // namespace pcpp diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp new file mode 100644 index 0000000000..b480134daf --- /dev/null +++ b/Packet++/src/DoIpLayerData.cpp @@ -0,0 +1,850 @@ +#include "DoIpLayerData.h" +#include "DoIpLayer.h" +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib + */ +namespace pcpp +{ + RoutingActivationRequestData::RoutingActivationRequestData() + : sourceAddress(0x0000), activationType(DoIpActivationTypes::Default), reservedIso{}, reservedOem(nullptr) {}; + + DoIpPayloadTypes RoutingActivationRequestData::getType() const + { + return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; + } + + std::string RoutingActivationRequestData::toString() const + { + std::stringstream os; + os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "activation type: " << DoIpEnumToStringActivationTypes.at(activationType) << std::hex << " (0x" + << unsigned(activationType) << ")" << std::endl; + os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << std::endl; + if (reservedOem) + { + os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) << '\n'; + } + return os.str(); + } + + std::vector RoutingActivationRequestData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.push_back(static_cast(activationType)); // Convert enum to byte + data.insert(data.end(), reservedIso.begin(), reservedIso.end()); + if (reservedOem) + { + data.insert(data.end(), reservedOem->begin(), reservedOem->end()); + } + return data; + } + + // buildFromLayer implementation + bool RoutingActivationRequestData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input data buffer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve routing activation request data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + activationType = static_cast(dataPtr[2]); + std::copy(dataPtr + 3, dataPtr + 3 + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); + if (doipLayer->getDataLen() - sizeof(doiphdr) >= + sizeof(sourceAddress) + sizeof(activationType) + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN) + { + reservedOem = std::unique_ptr>( + new std::array()); + std::copy(dataPtr + 3 + DOIP_RESERVED_ISO_LEN, dataPtr + 3 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN, + reservedOem->begin()); + } + else + { + PCPP_LOG_DEBUG("Reserved OEM field is empty or has invalid size !"); + reservedOem.reset(); + } + return true; + } + + // Routing Response function definition + RoutingActivationResponseData::RoutingActivationResponseData() + : logicalAddressExternalTester(0x0000), sourceAddress(0x0000), + responseCode(DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED), reservedIso{}, reservedOem(nullptr) + {} + + DoIpPayloadTypes RoutingActivationResponseData::getType() const + { + return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE; + } + + std::string RoutingActivationResponseData::toString() const + { + std::stringstream os; + os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) + << std::endl; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "routing activation response code: " << DoIpEnumToStringRoutingResponseCodes.at(responseCode) << std::hex + << " (0x" << unsigned(responseCode) << ")" << std::endl; + os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << std::endl; + if (reservedOem) + { + os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) + << std::endl; + } + return os.str(); + } + std::vector RoutingActivationResponseData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&logicalAddressExternalTester), + reinterpret_cast(&logicalAddressExternalTester) + + sizeof(logicalAddressExternalTester)); + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.push_back(static_cast(responseCode)); // Convert enum to byte + data.insert(data.end(), reservedIso.begin(), reservedIso.end()); + if (reservedOem) + { + data.insert(data.end(), reservedOem->begin(), reservedOem->end()); + } + return data; + } + + bool RoutingActivationResponseData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input data buffer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve routing activation response data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + if (!dataPtr) + { + PCPP_LOG_ERROR("Data pointer is null"); + return false; + } + + logicalAddressExternalTester = static_cast(dataPtr[1] << 8 | dataPtr[0]); + sourceAddress = static_cast(dataPtr[3] << 8 | dataPtr[2]); + responseCode = static_cast(dataPtr[4]); + + std::copy(dataPtr + 5, dataPtr + 5 + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); + + if (doipLayer->getDataLen() - sizeof(doiphdr) >= 5 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN) + { + reservedOem = std::unique_ptr>( + new std::array()); + std::copy(dataPtr + 5 + DOIP_RESERVED_ISO_LEN, dataPtr + 5 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN, + reservedOem->begin()); + } + else + { + PCPP_LOG_DEBUG("Reserved OEM field is empty or has invalid size !"); + reservedOem.reset(); // Clear reservedOem if not present + } + + return true; + } + + // Generic header nack function definition + GenericHeaderNackData::GenericHeaderNackData() : genericNackCode(DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH) + {} + + DoIpPayloadTypes GenericHeaderNackData::getType() const + { + return DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK; + } + + std::string GenericHeaderNackData::toString() const + { + std::stringstream os; + os << "generic header nack code: " << DoIpEnumToStringGenericHeaderNackCodes.at(genericNackCode) << std::hex + << " (0x" << unsigned(genericNackCode) << ")" << std::endl; + ; + return os.str(); + } + std::vector GenericHeaderNackData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.push_back(static_cast(genericNackCode)); // Convert enum to byte + return data; + } + + // buildFromLayer fun implementation + bool GenericHeaderNackData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Generic Header NACK data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate data length (1 byte is expected for genericNackCode) + if (doipLayer->getDataLen() - sizeof(doiphdr) < 1) + { + PCPP_LOG_ERROR("Insufficient data length for Generic Header NACK payload"); + return false; + } + + // Extract the NACK code (1 byte) + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + genericNackCode = static_cast(dataPtr[0]); + + return true; + } + + // vehicle ideentification with EID functions definition + VehicleIdentificationRequestEIDData::VehicleIdentificationRequestEIDData() : eid{} + {} + DoIpPayloadTypes VehicleIdentificationRequestEIDData::getType() const + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID; + } + std::string VehicleIdentificationRequestEIDData::toString() const + { + std::stringstream os; + os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << std::endl; + return os.str(); + } + std::vector VehicleIdentificationRequestEIDData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), eid.begin(), eid.end()); + return data; + } + + bool VehicleIdentificationRequestEIDData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with EID data from " + + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate data length (must at least accommodate EID length) + if (doipLayer->getDataLen() - sizeof(doiphdr) < DOIP_EID_LEN) + { + PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); + return false; + } + + // Extract the EID + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + std::copy(dataPtr, dataPtr + DOIP_EID_LEN, eid.begin()); + + return true; + } + + // vehicle ideentification with VIN functions definition + VehicleIdentificationRequestVINData::VehicleIdentificationRequestVINData() : vin{} + {} + DoIpPayloadTypes VehicleIdentificationRequestVINData::getType() const + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN; + } + std::string VehicleIdentificationRequestVINData::toString() const + { + std::stringstream os; + os << "VIN: " << std::string(vin.data(), vin.end()) << std::endl; + return os.str(); + } + std::vector VehicleIdentificationRequestVINData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), vin.begin(), vin.end()); + return data; + } + + bool VehicleIdentificationRequestVINData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with VIN data from " + + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate data length (must at least accommodate VIN length) + if (doipLayer->getDataLen() - sizeof(doiphdr) < DOIP_VIN_LEN) + { + PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); + return false; + } + + // Extract the VIN + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); + + return true; + } + + // vehicle announcement functions definition + VehicleAnnouncementData::VehicleAnnouncementData() + : vin{}, // Initialize VIN to all zeros + logicalAddress(0), // Set logical address to 0 + eid{}, // Initialize EID to all zeros + gid{}, // Initialize GID to all zeros + furtherActionRequired(DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED), // No further action required + syncStatus(DoIpSyncStatus::NON_INITIALIZED) // not initialized sync status field + {}; + + DoIpPayloadTypes VehicleAnnouncementData::getType() const + { + return DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE; + } + + std::string VehicleAnnouncementData::toString() const + { + std::stringstream os; + os << "VIN: " << std::string(vin.data(), vin.end()) << std::endl; + os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << std::endl; + os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << std::endl; + os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << std::endl; + os << "further action required:" << DoIpEnumToStringActionCodes.at(furtherActionRequired) << std::hex << " (0x" + << unsigned(furtherActionRequired) << ")" << std::endl; + os << "VIN/GID sync status: " << DoIpEnumToStringSyncStatus.at(syncStatus) + << std::endl; // Convert enum to byte + return os.str(); + } + + std::vector VehicleAnnouncementData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), vin.begin(), vin.end()); + data.insert(data.end(), reinterpret_cast(&logicalAddress), + reinterpret_cast(&logicalAddress) + sizeof(logicalAddress)); + data.insert(data.end(), eid.begin(), eid.end()); + data.insert(data.end(), gid.begin(), gid.end()); + data.push_back(static_cast(furtherActionRequired)); // Convert enum to byte + // optional field can be non-initialised + if (syncStatus != DoIpSyncStatus::NON_INITIALIZED) + { + data.push_back(static_cast(syncStatus)); // Convert enum to byte + } + return data; + } + + bool VehicleAnnouncementData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Vehicle Announcement data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate minimum data length + size_t expectedMinLength = + DOIP_VIN_LEN + sizeof(logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + 1; // 1 for furtherActionRequired + if (doipLayer->getDataLen() - sizeof(doiphdr) < expectedMinLength) + { + PCPP_LOG_ERROR("Insufficient data length for Vehicle Announcement payload"); + return false; + } + + // Parse fields from payload + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + + // VIN + std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); + dataPtr += DOIP_VIN_LEN; + + // Logical Address + logicalAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + dataPtr += sizeof(logicalAddress); + + // EID + std::copy(dataPtr, dataPtr + DOIP_EID_LEN, eid.begin()); + dataPtr += DOIP_EID_LEN; + + // GID + std::copy(dataPtr, dataPtr + DOIP_GID_LEN, gid.begin()); + dataPtr += DOIP_GID_LEN; + + // Further Action Required + furtherActionRequired = static_cast(*dataPtr); + dataPtr += 1; + + // Optional Sync Status + if (doipLayer->getDataLen() - sizeof(doiphdr) > expectedMinLength) + { + syncStatus = static_cast(*dataPtr); + } + else + { + syncStatus = DoIpSyncStatus::NON_INITIALIZED; + } + + return true; + } + + // alive check response functions definition + AliveCheckResponseData::AliveCheckResponseData() : sourceAddress(0x0000) + {} + DoIpPayloadTypes AliveCheckResponseData::getType() const + { + return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE; + } + std::string AliveCheckResponseData::toString() const + { + std::stringstream os; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + return os.str(); + } + std::vector AliveCheckResponseData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + return data; + } + + bool AliveCheckResponseData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Alive Check Response data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate minimum data length + constexpr size_t requiredLength = sizeof(sourceAddress); + if (doipLayer->getDataLen() - sizeof(doiphdr) < requiredLength) + { + PCPP_LOG_ERROR("Insufficient data length for Alive Check Response payload"); + return false; + } + + // Parse sourceAddress from payload + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + sourceAddress = *reinterpret_cast(dataPtr); + + return true; + } + + // Diagnostic Power Mode Response functions definition + DiagnosticPowerModeResponseData::DiagnosticPowerModeResponseData() + : powerModeCode(DoIpDiagnosticPowerModeCodes::NOT_READY) + {} + + DoIpPayloadTypes DiagnosticPowerModeResponseData::getType() const + { + return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE; + } + + std::string DiagnosticPowerModeResponseData::toString() const + { + std::stringstream os; + os << "diagnostic power mode: " << DoIpEnumToStringDiagnosticPowerModeCodes.at(powerModeCode) << std::hex + << " (0x" << unsigned(powerModeCode) << ")" << std::endl; + return os.str(); + } + + std::vector DiagnosticPowerModeResponseData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.push_back(static_cast(powerModeCode)); // Convert enum to byte + return data; + } + + bool DiagnosticPowerModeResponseData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Diagnostic Power Mode Response data from " + + doipLayer->getPayloadTypeAsStr()); + return false; + } + + // Validate minimum data length + constexpr size_t requiredLength = sizeof(powerModeCode); + if (doipLayer->getDataLen() - sizeof(doiphdr) < requiredLength) + { + PCPP_LOG_ERROR("Insufficient data length for Diagnostic Power Mode Response payload"); + return false; + } + + // Parse powerModeCode from payload + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + powerModeCode = static_cast(dataPtr[0]); + + return true; + } + + // Entity status response functions definitions + EntityStatusResponseData::EntityStatusResponseData() + : nodeType(DoIpEntityStatus::GATEWAY), maxConcurrentSockets(0), currentlyOpenSockets(0), maxDataSize(nullptr) + {} + + DoIpPayloadTypes EntityStatusResponseData::getType() const + { + return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE; + } + + std::string EntityStatusResponseData::toString() const + { + std::stringstream os; + os << "Entity status: " << DoIpEnumToStringEntityStatusNodeTypes.at(nodeType) << std::hex << " (0x" + << unsigned(nodeType) << ")" << std::endl; + os << "maximum Concurrent Socket: " << unsigned(maxConcurrentSockets) << std::endl; + os << "currently Opened Socket: " << unsigned(currentlyOpenSockets) << std::endl; + if (maxDataSize) + { + os << "maximum Data Size: " + << "0x" << pcpp::byteArrayToHexString(maxDataSize->data(), 4) << std::endl; + } + + return os.str(); + } + + std::vector EntityStatusResponseData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.push_back(static_cast(nodeType)); // Convert enum to byte + data.push_back(static_cast(maxConcurrentSockets)); + data.push_back(static_cast(currentlyOpenSockets)); + // optional field + if (maxDataSize) + { + data.insert(data.end(), maxDataSize->begin(), maxDataSize->end()); + } + return data; + } + + bool EntityStatusResponseData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Entity Status Response data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + constexpr size_t fixedFieldLength = + sizeof(nodeType) + sizeof(maxConcurrentSockets) + sizeof(currentlyOpenSockets); + constexpr size_t optionalFieldLength = 4; // Length of maxDataSize field + size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + + if (totalDataLength < fixedFieldLength) + { + PCPP_LOG_ERROR("Insufficient data length for Entity Status Response fixed fields"); + return false; + } + + // Parse fixed fields + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + nodeType = static_cast(dataPtr[0]); + maxConcurrentSockets = dataPtr[1]; + currentlyOpenSockets = dataPtr[2]; + + // Parse optional maxDataSize field if present + if (totalDataLength >= fixedFieldLength + optionalFieldLength) + { + maxDataSize = std::unique_ptr>( + new std::array()); + std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + optionalFieldLength, + maxDataSize->begin()); + } + else + { + maxDataSize = nullptr; // Optional field not present + } + + return true; + } + + // Diagnostic Message functions definitions + DiagnosticMessageData::DiagnosticMessageData() + : sourceAddress(0x0000), targetAddress(0x0000), diagnosticData{ 0x22, 0xf1, 0x68 } + {} + DoIpPayloadTypes DiagnosticMessageData::getType() const + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; + } + std::string DiagnosticMessageData::toString() const + { + std::stringstream os; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; + return os.str(); + } + std::vector DiagnosticMessageData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.insert(data.end(), reinterpret_cast(&targetAddress), + reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.insert(data.end(), diagnosticData.data(), diagnosticData.data() + diagnosticData.size()); + return data; + } + + bool DiagnosticMessageData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Diagnostic Message data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + 2; // SI + DID + size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + + if (totalDataLength < fixedFieldLength) + { + PCPP_LOG_ERROR("Insufficient data length for Diagnostic Message fixed fields"); + return false; + } + + // Parse fixed fields + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + sourceAddress = *reinterpret_cast(dataPtr); + targetAddress = *reinterpret_cast(dataPtr + sizeof(sourceAddress)); + + // Parse diagnosticData field (remaining data after fixed fields) + size_t diagnosticDataLength = totalDataLength - fixedFieldLength; + diagnosticData.resize(diagnosticDataLength); + std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + diagnosticDataLength, + diagnosticData.begin()); + + return true; + } + + // Diagnostic Ack Message functions definitions + DiagnosticAckMessageData::DiagnosticAckMessageData() + : sourceAddress(0x0000), targetAddress(0x0000), ackCode(DoIpDiagnosticAckCodes::ACK), + previousMessage{ 0x22, 0xf1, 01, 0x02 } + {} + DoIpPayloadTypes DiagnosticAckMessageData::getType() const + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK; + } + std::string DiagnosticAckMessageData::toString() const + { + std::stringstream os; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; + os << "ack code: " << DoIpEnumToStringAckCode.at(ackCode) << " (0x" << unsigned(ackCode) << ")" << std::endl; + + return os.str(); + } + std::vector DiagnosticAckMessageData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.insert(data.end(), reinterpret_cast(&targetAddress), + reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.push_back(static_cast(ackCode)); + if (!previousMessage.empty()) + { + data.insert(data.end(), previousMessage.begin(), previousMessage.end()); + } + return data; + } + + bool DiagnosticAckMessageData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Diagnostic Acknowledgment Message data from " + + doipLayer->getPayloadTypeAsStr()); + return false; + } + + constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(ackCode); + size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + + if (totalDataLength < fixedFieldLength) + { + PCPP_LOG_ERROR("Insufficient data length for Diagnostic Acknowledgment Message fixed fields"); + return false; + } + + // Parse fixed fields + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + sourceAddress = (*reinterpret_cast(dataPtr)); + targetAddress = (*reinterpret_cast(dataPtr + sizeof(sourceAddress))); + ackCode = static_cast( + *reinterpret_cast(dataPtr + sizeof(sourceAddress) + sizeof(targetAddress))); + + // Check if there is any data left for the optional previousMessage field + size_t remainingDataLength = totalDataLength - fixedFieldLength; + if (remainingDataLength > 0) + { + previousMessage.resize(remainingDataLength); + std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + remainingDataLength, + previousMessage.begin()); + } + else + { + previousMessage.clear(); // Ensure previousMessage is empty when not provided + } + return true; + } + + // Diagnostic Nack Message functions definitions + DiagnosticNackMessageData::DiagnosticNackMessageData() + : sourceAddress(0x0000), targetAddress(0x0000), + nackCode(DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS), previousMessage{ 0x22, 0xf1, 01, 0x02 } + {} + DoIpPayloadTypes DiagnosticNackMessageData::getType() const + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK; + } + std::string DiagnosticNackMessageData::toString() const + { + std::stringstream os; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; + os << "nack code: " << DoIpEnumToStringDiagnosticNackCodes.at(nackCode) << std::hex << " (0x" + << unsigned(nackCode) << ")" << std::endl; + return os.str(); + } + std::vector DiagnosticNackMessageData::getData() const + { + std::vector data; + // Copy each field's data into the vector + data.insert(data.end(), reinterpret_cast(&sourceAddress), + reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.insert(data.end(), reinterpret_cast(&targetAddress), + reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.push_back(static_cast(nackCode)); + if (!previousMessage.empty()) + { + data.insert(data.end(), reinterpret_cast(&previousMessage), + reinterpret_cast(&previousMessage) + sizeof(previousMessage)); + } + return data; + } + + bool DiagnosticNackMessageData::buildFromLayer(DoIpLayer* doipLayer) + { + if (!doipLayer) + { + PCPP_LOG_ERROR("Input DoIpLayer is null"); + return false; + } + + if (doipLayer->getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot retrieve Diagnostic NACK Message data from " + doipLayer->getPayloadTypeAsStr()); + return false; + } + + constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(nackCode); + size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + + if (totalDataLength < fixedFieldLength) + { + PCPP_LOG_ERROR("Insufficient data length for Diagnostic NACK Message fixed fields"); + return false; + } + + // Parse fixed fields + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + sourceAddress = (*reinterpret_cast(dataPtr)); + targetAddress = (*reinterpret_cast(dataPtr + sizeof(sourceAddress))); + nackCode = static_cast( + *reinterpret_cast(dataPtr + sizeof(sourceAddress) + sizeof(targetAddress))); + + // Check if there is any data left for the optional previousMessage field + size_t remainingDataLength = totalDataLength - fixedFieldLength; + if (remainingDataLength > 0) + { + previousMessage.resize(remainingDataLength); + std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + remainingDataLength, + previousMessage.begin()); + } + else + { + previousMessage.clear(); // Ensure previousMessage is empty when not provided + } + + return true; + } + +} // namespace pcpp diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index d146efd589..49e5f7ab16 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -11,6 +11,7 @@ #include "BgpLayer.h" #include "SSHLayer.h" #include "DnsLayer.h" +#include "DoIpLayer.h" #include "TelnetLayer.h" #include "TpktLayer.h" #include "FtpLayer.h" @@ -365,8 +366,11 @@ namespace pcpp const uint16_t portSrc = getSrcPort(); const char* payloadChar = reinterpret_cast(payload); - if (HttpMessage::isHttpPort(portDst) && - HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) + if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && + (DoIpLayer::isDataValid(payload, payloadLen))) + m_NextLayer = new DoIpLayer(payload, payloadLen, this, m_Packet); + else if (HttpMessage::isHttpPort(portDst) && + HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) m_NextLayer = new HttpRequestLayer(payload, payloadLen, this, m_Packet); else if (HttpMessage::isHttpPort(portSrc) && HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown && diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 6261a54426..98a40aee0e 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -8,6 +8,7 @@ #include "DnsLayer.h" #include "DhcpLayer.h" #include "DhcpV6Layer.h" +#include "DoIpLayer.h" #include "VxlanLayer.h" #include "SipLayer.h" #include "RadiusLayer.h" @@ -127,6 +128,9 @@ namespace pcpp else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && (DhcpV6Layer::isDataValid(udpData, udpDataLen))) m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); + else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && + (DoIpLayer::isDataValid(udpData, udpDataLen))) + m_NextLayer = new DoIpLayer(udpData, udpDataLen, this, m_Packet); else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && NtpLayer::isDataValid(udpData, udpDataLen)) m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); diff --git a/Pcap++/src/PcapRemoteDeviceList.cpp b/Pcap++/src/PcapRemoteDeviceList.cpp index b725f3b817..891702097e 100644 --- a/Pcap++/src/PcapRemoteDeviceList.cpp +++ b/Pcap++/src/PcapRemoteDeviceList.cpp @@ -109,7 +109,6 @@ namespace pcpp auto pNewRemoteDevice = std::unique_ptr( new PcapRemoteDevice(currInterface, pRemoteAuthCopy, ipAddress, port)); // Release is called after pushback to prevent memory leaks if vector reallocation fails. - // cppcheck-suppress danglingLifetime devices.push_back(pNewRemoteDevice.get()); pNewRemoteDevice.release(); } diff --git a/Tests/Packet++Test/CMakeLists.txt b/Tests/Packet++Test/CMakeLists.txt index 0bcac69e63..8a100375e0 100644 --- a/Tests/Packet++Test/CMakeLists.txt +++ b/Tests/Packet++Test/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable( Tests/DhcpTests.cpp Tests/DhcpV6Tests.cpp Tests/DnsTests.cpp + Tests/DoIpTests.cpp Tests/EthAndArpTests.cpp Tests/FtpTests.cpp Tests/GreTests.cpp diff --git a/Tests/Packet++Test/PacketExamples/DoIpAliveCheckRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpAliveCheckRequestPacket.dat new file mode 100644 index 0000000000..02633241b4 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpAliveCheckRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff1434580010898202fd000700000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpAliveCheckResponsePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpAliveCheckResponsePacket.dat new file mode 100644 index 0000000000..150f3bac9e --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpAliveCheckResponsePacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000260001000040113aeca9fe75efa9fe75eeff1434580012897b02fd0008000000020000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat new file mode 100644 index 0000000000..371f162d4c --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee740800450000354de80000ff062e00a9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f3acc000002fd80020000000540100e8000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticMessagePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticMessagePacket.dat new file mode 100644 index 0000000000..0190992a5c --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticMessagePacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac15080045000036c274400040063873a9fe75efa9fe75eed25e3458ab87802f00191aa05018fadf4003000002fd8001000000060e8040101003 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat new file mode 100644 index 0000000000..a912a45f94 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee740800450000354de80000ff062e00a9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f3acc000002fd80030000000540100e8002 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpEntityStatusRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpEntityStatusRequestPacket.dat new file mode 100644 index 0000000000..56d6b5f811 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpEntityStatusRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff1434580010498802fd400100000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpEntityStatusResponsePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpEntityStatusResponsePacket.dat new file mode 100644 index 0000000000..3f5fd4c76f --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpEntityStatusResponsePacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee7408004500002b4db00000ff112e37a9fe75eea9fe75ef3458ff1400174a6102fd40020000000700010000000fff000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpGenericHeaderNackPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpGenericHeaderNackPacket.dat new file mode 100644 index 0000000000..2a603d53c8 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpGenericHeaderNackPacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee740800450000254dc10000ff112e2ca9fe75eea9fe75ef3458ff140011888602fd00000000000101000000000000000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpPowerModeRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpPowerModeRequestPacket.dat new file mode 100644 index 0000000000..76cccfe64b --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpPowerModeRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff1434580010498602fd400300000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpPowerModeResponsePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpPowerModeResponsePacket.dat new file mode 100644 index 0000000000..6b70489e04 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpPowerModeResponsePacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee740800450000254dc30000ff112e2aa9fe75eea9fe75ef3458ff140011498202fd40040000000100000000000000000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationRequestPacket.dat new file mode 100644 index 0000000000..daf6bcd5e3 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac1508004500003bf0e44000400609fea9fe75efa9fe75eed25a345849689c4200186ab95018faf04008000002fd00050000000b0e80000000000000000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationResponsePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationResponsePacket.dat new file mode 100644 index 0000000000..5bf7a68d79 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpRoutingActivationResponsePacket.dat @@ -0,0 +1 @@ +54e1ad6bac15001a37bfee740800450000394dd20000ff062e12a9fe75eea9fe75ef3458d25a00186ab949689c555018165da0a5000002fd0006000000090e8040101000000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleAnnouncementPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleAnnouncementPacket.dat new file mode 100644 index 0000000000..541bc2c052 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpVehicleAnnouncementPacket.dat @@ -0,0 +1 @@ +ffffffffffff001a37bfee740800450000444d7c0000ff11a441a9fe75eea9feffff345834580030df5e02fd0004000000204241554e4545344d5a31373034323430334010001a37bfee74001a37bfee7400 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat new file mode 100644 index 0000000000..275dbdd4f7 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat @@ -0,0 +1 @@ +00e0b149390200137225facd08004500002a000000008011c8c8ac16b2ea0a0a08f0ff14345800167a8002fd0002000000064241554e4545 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestPacket.dat new file mode 100644 index 0000000000..6e9951bb7e --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff1434580010898802fd000100000000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat new file mode 100644 index 0000000000..975980797d --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000350001000040113adda9fe75efa9fe75eeff14345800214b6d02fd0003000000114241554e4545344d5a3137303432343033 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index 05ffbbca24..9f1a568157 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -88,6 +88,40 @@ PTF_TEST_CASE(DnsOverTcpParsingTest); PTF_TEST_CASE(DnsOverTcpCreationTest); PTF_TEST_CASE(DnsLayerAddDnsKeyTest); +// Implemented in DoIpTests.cpp +PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing); +PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation); +PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing); +PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation); +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing); +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation); +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing); +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation); +PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing); +PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation); +PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing); +PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation); +PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing); +PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation); +PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing); +PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation); +PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing); +PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation); +PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing); +PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation); +PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing); +PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation); +PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing); +PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation); +PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing); +PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation); + // Implemented in IcmpTests.cpp PTF_TEST_CASE(IcmpParsingTest); PTF_TEST_CASE(IcmpCreationTest); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp new file mode 100644 index 0000000000..6214b4f8f8 --- /dev/null +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -0,0 +1,1330 @@ +#include "../TestDefinition.h" +#include "../Utils/TestUtils.h" +#include "EndianPortable.h" +#include "Packet.h" +#include "EthLayer.h" +#include "IPv4Layer.h" +#include "TcpLayer.h" +#include "UdpLayer.h" +#include "PayloadLayer.h" +#include "SystemUtils.h" +#include "PacketUtils.h" +#include "DeprecationUtils.h" +#include "DoIpLayer.h" +#include + +// ------------------ +// GenericHeaderNackPacket +PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpGenericHeaderNackPacket.dat"); + + pcpp::Packet GenericHeaderNack(&rawPacket1); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = GenericHeaderNack.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8886)); + + pcpp::DoIpLayer* doipLayer = GenericHeaderNack.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::GenericHeaderNackData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "generic header nack code: Unknown payload type (0x1)\n"); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0)\nPayload Length: 1\n") +} + +PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; + pcpp::GenericHeaderNackData data; + data.genericNackCode = pcpp::DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, &data); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Generic DOIP header Nack"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0)\nPayload Length: 1\n") +} +// DoIpVehicleIdentificationRequestPacketParsing +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestPacket.dat"); + + pcpp::Packet vehicleIdentificationRequest(&rawPacket1); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8988)); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x10)); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x1)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); + +} // DoIpVehicleIdentificationRequestPacketParsing + +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + + ipLayer.getIPv4Header()->ipId = htobe16(20370); + ipLayer.getIPv4Header()->timeToLive = 128; + pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; + + // vehIdentificationRequestArgs.args = std::monostate{}; + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x1)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); +} +// VehicleIdentificationWithVIN +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) +{ + // Dissect Vehicle identification Request with VIN + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat"); + + pcpp::Packet VehicleIdentificationRequestVIN(&rawPacket1); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4b6d)); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(33)); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::VehicleIdentificationRequestVINData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "VIN: BAUNEE4MZ17042403\n"); + // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, + enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x3)\nPayload Length: 17\n") + +} // DoIpVehicleIdentificationRequestVINPacketParsing + +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x3, 0x0, 0x0, 0x0, 0x11, 0x42, 0x41, 0x55, 0x4e, 0x45, + 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + + pcpp::VehicleIdentificationRequestVINData withVin; + withVin.vin = vin; + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withVin); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 25), bytes, 25); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, + enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 17); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x3)\nPayload Length: 17\n") +} +// VehicleIdentificationWithEID +PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) +{ + // Dissect Vehicle identification Request with EID + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat"); + + pcpp::Packet VehicleIdentificationRequestEID(&rawPacket1); + PTF_ASSERT_TRUE(VehicleIdentificationRequestEID.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestEID.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestEID.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestEID.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x7a80)); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x16)); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::VehicleIdentificationRequestEIDData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "EID: 4241554e4545\n"); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, + enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with EID"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x2)\nPayload Length: 6\n") + +} // DoIpVehicleIdentificationRequestVINPacketParsing + +PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; + std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; + + pcpp::VehicleIdentificationRequestEIDData withEID; + withEID.eid = eid; + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withEID); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 56); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (56 - 14), bytes, 14); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, + enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with EID"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x2)\nPayload Length: 6\n") +} +// VehicleAnnouncement +PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) +{ + // Dissect Vehicle Announcement message + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleAnnouncementPacket.dat"); + + pcpp::Packet VehicleAnnouncement(&rawPacket1); + PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = VehicleAnnouncement.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 13400); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0xdf5e)); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x30)); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = VehicleAnnouncement.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::VehicleAnnouncementData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL( + data.toString(), + "VIN: BAUNEE4MZ17042403\nlogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nfurther action required:No further action required (0x0)\nVIN/GID sync status: NULL\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), + "Vehicle announcement message / vehicle identification response message"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 32); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x4)\nPayload Length: 32\n") + +} // DoIpVehicleAnnouncementPacketParsing + +PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x4, 0x0, 0x0, 0x0, 0x21, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, + 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33, 0x40, 0x10, 0x0, + 0x1a, 0x37, 0xbf, 0xee, 0x74, 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74, 0x0, 0x0 }; + std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + + pcpp::VehicleAnnouncementData ann; + ann.gid = gid; + ann.eid = eid; + ann.vin = vin; + ann.logicalAddress = be16toh(0x4010); + ann.syncStatus = pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED; + ann.furtherActionRequired = pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED; + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &ann); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 83); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), + "Vehicle announcement message / vehicle identification response message"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 33); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x4)\nPayload Length: 33\n") +} +// RoutingActivationRequest +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) +{ + // Dissect Vehicle Announcement message + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationRequestPacket.dat"); + + pcpp::Packet RoutingActivationRequest(&rawPacket1); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::TcpLayer* tcpLayer = RoutingActivationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); + + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), 53850); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x4008)); + + pcpp::DoIpLayer* doipLayer = RoutingActivationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::RoutingActivationRequestData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + + PTF_ASSERT_EQUAL( + data.toString(), + "sourceAddress: 0xe80\nactivation type: Default (0x0)\nreserved by ISO: 00000000\nReserved by OEM: 00000000\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x5)\nPayload Length: 11\n") +} + +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + + tcpLayer.getTcpHeader()->windowSize = 64240; + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, 0xb, 0xe, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + pcpp::RoutingActivationRequestData routingData; + routingData.sourceAddress = be16toh(0x0e80); + routingData.activationType = pcpp::DoIpActivationTypes::Default; + routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; + routingData.reservedOem = std::unique_ptr>(new std::array()); + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, &routingData); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation request"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 11); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x5)\nPayload Length: 11\n") +} +// RoutingActivationResponse +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) +{ + // Dissect Vehicle Announcement message + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationResponsePacket.dat"); + + pcpp::Packet RoutingActivationResponse(&rawPacket1); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::DOIP)); + + pcpp::TcpLayer* tcpLayer = RoutingActivationResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); + + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53850); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0xa0a5)); + + pcpp::DoIpLayer* doipLayer = RoutingActivationResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::RoutingActivationResponseData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL( + data.toString(), + "logical address of external tester: 0xe80\nsource address: 0x4010\nrouting activation response code: Routing successfully activated (0x10)\nreserved by ISO: 00000000\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x6)\nPayload Length: 9\n") +} + +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + + tcpLayer.getTcpHeader()->windowSize = 64240; + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x6, 0x0, 0x0, 0x0, 0xd, 0xe, 0x80, 0x40, + 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + pcpp::RoutingActivationResponseData routingData; + routingData.logicalAddressExternalTester = be16toh(0x0e80); + routingData.sourceAddress = be16toh(0x4010); + routingData.responseCode = pcpp::DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED; + routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; + routingData.reservedOem = std::unique_ptr>(new std::array()); + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, &routingData); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 75); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation response"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 13); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x6)\nPayload Length: 13\n") +} +// --------------- +// AliveCheckRequestPacket +PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpAliveCheckRequestPacket.dat"); + + pcpp::Packet AliveCheckRequest(&rawPacket1); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = AliveCheckRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8982)); + + pcpp::DoIpLayer* doipLayer = AliveCheckRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x7)\nPayload Length: 0\n") +} + +PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x7)\nPayload Length: 0\n") +} +// --------------- +// AliveCheckResponsePacket +PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpAliveCheckResponsePacket.dat"); + + pcpp::Packet AliveCheckResponse(&rawPacket1); + PTF_ASSERT_TRUE(AliveCheckResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(AliveCheckResponse.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(AliveCheckResponse.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = AliveCheckResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x897b)); + + pcpp::DoIpLayer* doipLayer = AliveCheckResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // build doipData from existent layer + pcpp::AliveCheckResponseData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "source address: 0x0\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x8)\nPayload Length: 2\n") +} + +PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0 }; + pcpp::AliveCheckResponseData aliveCheckRespData; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, &aliveCheckRespData); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 52); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check response"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 2); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x8)\nPayload Length: 2\n") +} +// ------------------ +// EntityStatusRequestPacket +PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusRequestPacket.dat"); + + pcpp::Packet EntityStatusRequest(&rawPacket1); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = EntityStatusRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4988)); + + pcpp::DoIpLayer* doipLayer = EntityStatusRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status request (0x4001)\nPayload Length: 0\n") +} + +PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status request (0x4001)\nPayload Length: 0\n") +} +// ------------------ +// EntityStatusResponsePacket +PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusResponsePacket.dat"); + + pcpp::Packet EntityStatusResponse(&rawPacket1); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = EntityStatusResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4a61)); + + pcpp::DoIpLayer* doipLayer = EntityStatusResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::EntityStatusResponseData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL( + data.toString(), + "Entity status: DoIP gateway (0x0)\nmaximum Concurrent Socket: 1\ncurrently Opened Socket: 0\nmaximum Data Size: 0x00000fff\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status response (0x4002)\nPayload Length: 7\n") +} + +PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x2, 0x2, 0x0, 0x0, 0xf, 0xff }; + pcpp::EntityStatusResponseData entityResponseData; + entityResponseData.currentlyOpenSockets = 2; + entityResponseData.maxConcurrentSockets = 2; + entityResponseData.maxDataSize = + std::unique_ptr>(new std::array{ 0x0, 0x0, 0xf, 0xff }); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, &entityResponseData); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 57); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status response (0x4002)\nPayload Length: 7\n") +} +// ------------------ +// PowerModeRequestPacket +PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeRequestPacket.dat"); + + pcpp::Packet PowerModeRequest(&rawPacket1); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = PowerModeRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4986)); + + pcpp::DoIpLayer* doipLayer = PowerModeRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode request information (0x4003)\nPayload Length: 0\n") +} + +PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode request information (0x4003)\nPayload Length: 0\n") +} +// ------------------ +// PowerModeResponsePacket +PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeResponsePacket.dat"); + + pcpp::Packet PowerModeResponse(&rawPacket1); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = PowerModeResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + // PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x2e2a)); + + pcpp::DoIpLayer* doipLayer = PowerModeResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::DiagnosticPowerModeResponseData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "diagnostic power mode: not ready (0x0)\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode response information (0x4004)\nPayload Length: 1\n") +} + +PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0 }; + pcpp::DiagnosticPowerModeResponseData data; + data.powerModeCode = pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, &data); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode response information"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode response information (0x4004)\nPayload Length: 1\n") +} +// ------------------ +// DiagnosticMessagePacket +PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpDiagnosticMessagePacket.dat"); + + pcpp::Packet DiagnosticMessagePacket(&rawPacket1); + PTF_ASSERT_TRUE(DiagnosticMessagePacket.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(DiagnosticMessagePacket.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(DiagnosticMessagePacket.isPacketOfType(pcpp::DOIP)); + + pcpp::TcpLayer* tcpLayer = DiagnosticMessagePacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); + + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), 53854); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x4003)); + + pcpp::DoIpLayer* doipLayer = DiagnosticMessagePacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::DiagnosticMessageData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "source address: 0xe80\ntarget address: 0x4010\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 6); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message (0x8001)\nPayload Length: 6\n") +} + +PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0xe, 0x80, 0x40, 0x10, 0x10, 0x3 }; + std::vector diagnosticData{ 0x10, 0x03 }; + + pcpp::DiagnosticMessageData data; + data.sourceAddress = be16toh(0x0e80); + data.targetAddress = be16toh(0x4010); + data.diagnosticData = diagnosticData; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, &data); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 68); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message (0x8001)\nPayload Length: 6\n"); +} +// ------------------ +// DiagnosticAckMessagePacket +PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpDiagnosticAckMessagePacket.dat"); + + pcpp::Packet DiagnosticAckMessage(&rawPacket1); + PTF_ASSERT_TRUE(DiagnosticAckMessage.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(DiagnosticAckMessage.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(DiagnosticAckMessage.isPacketOfType(pcpp::DOIP)); + + pcpp::TcpLayer* tcpLayer = DiagnosticAckMessage.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); + + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x3acc)); + + pcpp::DoIpLayer* doipLayer = DiagnosticAckMessage.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::DiagnosticAckMessageData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 5); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 5\n") +} + +PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x2, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0xe, 0x80, 0x0 }; + + pcpp::DiagnosticAckMessageData data; + data.sourceAddress = be16toh(0x4010); + data.targetAddress = be16toh(0x0e80); + data.ackCode = pcpp::DoIpDiagnosticAckCodes::ACK; + // dont use previous message + data.previousMessage.clear(); + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, &data); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Ack"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 5\n"); +} +// ------------------ +// DiagnosticNackMessagePacket +PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpDiagnosticNackMessagePacket.dat"); + + pcpp::Packet DiagnosticNackMessage(&rawPacket1); + PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::DOIP)); + + pcpp::TcpLayer* tcpLayer = DiagnosticNackMessage.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); + + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x3acc)); + + pcpp::DoIpLayer* doipLayer = DiagnosticNackMessage.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + pcpp::DiagnosticNackMessageData data; + if (data.buildFromLayer(doipLayer)) + // std::cout << data.toString(); + PTF_ASSERT_EQUAL(data.toString(), + "source address: 0x4010\ntarget address: 0xe80\nnack code: Invalid source address (0x2)\n"); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 5); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 5\n") +} + +PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x3, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0xe, 0x80, 0x2 }; + + pcpp::DiagnosticNackMessageData data; + data.sourceAddress = be16toh(0x4010); + data.targetAddress = be16toh(0x0e80); + data.nackCode = pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS; + // dont use previous message + data.previousMessage.clear(); + + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, &data); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + doIpPacket.computeCalculateFields(); + + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // std::endl; + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Nack"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); + PTF_ASSERT_EQUAL( + _doipLayer2->toString(), + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 5\n"); +} +DISABLE_WARNING_POP diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index e74498bd94..9eef3d3ee5 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -186,6 +186,39 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DnsOverTcpCreationTest, "dns"); PTF_RUN_TEST(DnsLayerAddDnsKeyTest, "dns"); + PTF_RUN_TEST(DoIpGenericHeaderNackPacketParsing, "doip"); + PTF_RUN_TEST(DoIpGenericHeaderNackPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleAnnouncementPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleAnnouncementPacketCreation, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationResponsePacketCreation, "doip"); + PTF_RUN_TEST(DoIpAliveCheckRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpAliveCheckRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpAliveCheckResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpAliveCheckResponsePacketCreation, "doip"); + PTF_RUN_TEST(DoIpEntityStatusRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpEntityStatusRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpEntityStatusResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpEntityStatusResponsePacketCreation, "doip"); + PTF_RUN_TEST(DoIpPowerModeRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpPowerModeRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpPowerModeResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpPowerModeResponsePacketCreation, "doip"); + PTF_RUN_TEST(DoIpDiagnosticMessagePacketParsing, "doip"); + PTF_RUN_TEST(DoIpDiagnosticMessagePacketCreation, "doip"); + PTF_RUN_TEST(DoIpDiagnosticAckMessagePacketParsing, "doip"); + PTF_RUN_TEST(DoIpDiagnosticAckMessagePacketCreation, "doip"); + PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketParsing, "doip"); + PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketCreation, "doip"); + PTF_RUN_TEST(IcmpParsingTest, "icmp"); PTF_RUN_TEST(IcmpCreationTest, "icmp"); PTF_RUN_TEST(IcmpEditTest, "icmp"); diff --git a/Tests/Pcap++Test/Common/PcapFileNamesDef.h b/Tests/Pcap++Test/Common/PcapFileNamesDef.h index 41d724152b..d5ed769d31 100644 --- a/Tests/Pcap++Test/Common/PcapFileNamesDef.h +++ b/Tests/Pcap++Test/Common/PcapFileNamesDef.h @@ -34,3 +34,4 @@ #define EXAMPLE_PCAP_DESTRUCTOR2_PATH "PcapExamples/destructor2.pcap" #define EXAMPLE_PCAP_NANO_PATH "PcapExamples/nanosecs.pcap" #define EXAMPLE_PCAPNG_NANO_PATH "PcapExamples/nanosecs.pcapng" +#define EXAMPLE_PCAPNG_DOIP_PATH "PcapExamples/doip.pcap" diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index ccaaec4756..2f6ebf149e 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -62,6 +62,9 @@ PTF_TEST_CASE(TestHttpResponseParsing); PTF_TEST_CASE(TestPrintPacketAndLayers); PTF_TEST_CASE(TestDnsParsing); +// Implemented in DoIpTests.cpp +PTF_TEST_CASE(DoIpPacketParsing); + // Implemented in TcpReassemblyTests.cpp PTF_TEST_CASE(TestTcpReassemblySanity); PTF_TEST_CASE(TestTcpReassemblyRetran); diff --git a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp index a22fbb9437..cae1d41687 100644 --- a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp +++ b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp @@ -5,7 +5,9 @@ #include "Packet.h" #include "HttpLayer.h" #include "DnsLayer.h" +#include "DoIpLayer.h" #include "PcapFileDevice.h" +#include PTF_TEST_CASE(TestHttpRequestParsing) { @@ -473,3 +475,20 @@ PTF_TEST_CASE(TestDnsParsing) // wireshark filter: dns.count.add_rr > 0 and dns.resp.type == 47 PTF_ASSERT_EQUAL(additionalWithTypeNSEC, 14); } // TestDnsParsing + +PTF_TEST_CASE(DoIpPacketParsing) +{ + pcpp::PcapFileReaderDevice reader(EXAMPLE_PCAPNG_DOIP_PATH); + PTF_ASSERT_TRUE(reader.open()); + pcpp::RawPacket rawPacket; + while (reader.getNextPacket(rawPacket)) + { + pcpp::Packet packet(&rawPacket); + std::cout << packet.toString(); + // pcpp::DoIpLayer* doipLayer = packet.getLayerOfType(); + // PTF_ASSERT_TRUE(doipLayer->resolveProtocolVersion(doipLayer->getProtocolVersion(), + // doipLayer->getInvertProtocolVersion(), doipLayer->getPayloadType())); + // PTF_ASSERT_TRUE(doipLayer->resolvePayloadLength(doipLayer->getPayloadLength(), doipLayer->getPayloadType())); + pcpp::multiPlatformSleep(1); + } +} diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 784a9e0d6f..002f119c92 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -199,7 +199,7 @@ int main(int argc, char* argv[]) PTF_START_RUNNING_TESTS(userTagsInclude, userTagsExclude, configTags); testSetUp(); - + PTF_RUN_TEST(DoIpPacketParsing, "no_network"); PTF_RUN_TEST(TestIPAddress, "no_network;ip"); PTF_RUN_TEST(TestMacAddress, "no_network;mac"); PTF_RUN_TEST(TestLRUList, "no_network"); From 7966b061288adffca674ad4f000a5b644b3d7fd8 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 8 Dec 2024 19:05:27 -0500 Subject: [PATCH 02/43] Correct endianness handling for imported data to ensure consistent interpretation across systems. --- Packet++/header/DoIpEnumToString.h | 27 --------------------------- Packet++/header/DoIpLayerData.h | 1 + 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/Packet++/header/DoIpEnumToString.h b/Packet++/header/DoIpEnumToString.h index 42500b1061..d5bf03cb62 100644 --- a/Packet++/header/DoIpEnumToString.h +++ b/Packet++/header/DoIpEnumToString.h @@ -223,31 +223,4 @@ namespace pcpp { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, { DoIpSyncStatus::NON_INITIALIZED, "NULL" } }; - - /** - * @brief Mapping of DoIP Payload Types to their corresponding payload lengths. - * - * This unordered map associates each `DoIpPayloadType` enum value with a specific max payload length. - * It provides the needed length for each payload type, ensuring proper handling of message sizes - * when building DoIP messages. - - inline static const std::unordered_map DoIpMapPayloadTypeToPayloadLength{ - { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, 1 }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, 0 }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, 6 }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, 17 }, - { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, 40 }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, 11 }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, 9 }, - { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, 0 }, - { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, 2 }, - { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, 0 }, - { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, 7 }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, 0 }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, 1 }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, 1452 }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, 5 }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, 4 } - }; */ - } // namespace pcpp diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 46db686c85..5bad30dfcd 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -3,6 +3,7 @@ #include #include #include +#include "EndianPortable.h" #include "Logger.h" #include "GeneralUtils.h" #include "DoIpEnumToString.h" From d4658d72ab15954ff0425505c89fdbe905e40b9c Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 8 Dec 2024 23:39:23 -0500 Subject: [PATCH 03/43] Fix serval issues related to multi-cross platform --- Packet++/header/DoIpLayerData.h | 2 +- Packet++/src/DoIpLayer.cpp | 9 ++++- Packet++/src/DoIpLayerData.cpp | 2 +- Tests/Packet++Test/Tests/DoIpTests.cpp | 37 +++++++++---------- Tests/Pcap++Test/Common/PcapFileNamesDef.h | 1 - Tests/Pcap++Test/TestDefinition.h | 3 -- Tests/Pcap++Test/Tests/PacketParsingTests.cpp | 17 --------- Tests/Pcap++Test/main.cpp | 1 - 8 files changed, 27 insertions(+), 45 deletions(-) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 5bad30dfcd..1b3c3e8736 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -600,7 +600,7 @@ namespace pcpp * - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. * - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. * - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object - * creation by : + * * @code * EntityStatusResponseData data; * data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index fca1085f91..8a96cc3973 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -133,6 +133,11 @@ namespace pcpp std::string DoIpLayer::toString() const { std::stringstream os; + if (!resolveLayer()) + { + os << "Malformed doip Packet"; + return os.str(); + } DoIpProtocolVersion version = getProtocolVersion(); DoIpPayloadTypes type = getPayloadType(); uint32_t length = getPayloadLength(); @@ -140,8 +145,8 @@ namespace pcpp os << "DOIP Layer:" << std::endl; os << "Protocol Version: " << DoIpEnumToStringProtocolVersion.at(version) << std::hex << " (0x" << unsigned((uint8_t)version) << ")" << std::endl; - os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << htole16((uint16_t)type) << ")" - << std::endl; + os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << std::setw(4) << std::setfill('0') + << (uint16_t)type << ")" << std::endl; os << std::dec << "Payload Length: " << length << std::endl; return os.str(); diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index b480134daf..0a814e0653 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -281,7 +281,7 @@ namespace pcpp std::string VehicleIdentificationRequestVINData::toString() const { std::stringstream os; - os << "VIN: " << std::string(vin.data(), vin.end()) << std::endl; + os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << std::endl; return os.str(); } std::vector VehicleIdentificationRequestVINData::getData() const diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 6214b4f8f8..accc79c1bb 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -49,7 +49,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0)\nPayload Length: 1\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0000)\nPayload Length: 1\n") } PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) @@ -90,7 +90,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0)\nPayload Length: 1\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0000)\nPayload Length: 1\n") } // DoIpVehicleIdentificationRequestPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) @@ -124,7 +124,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x1)\nPayload Length: 0\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); } // DoIpVehicleIdentificationRequestPacketParsing @@ -161,7 +161,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x1)\nPayload Length: 0\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); } // VehicleIdentificationWithVIN @@ -195,7 +195,6 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "VIN: BAUNEE4MZ17042403\n"); - // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, @@ -204,7 +203,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x3)\nPayload Length: 17\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x0003)\nPayload Length: 17\n") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -248,7 +247,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 17); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x3)\nPayload Length: 17\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x0003)\nPayload Length: 17\n") } // VehicleIdentificationWithEID PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) @@ -289,7 +288,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x2)\nPayload Length: 6\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x0002)\nPayload Length: 6\n") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -335,7 +334,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x2)\nPayload Length: 6\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x0002)\nPayload Length: 6\n") } // VehicleAnnouncement PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) @@ -379,7 +378,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 32); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x4)\nPayload Length: 32\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x0004)\nPayload Length: 32\n") } // DoIpVehicleAnnouncementPacketParsing @@ -435,7 +434,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 33); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x4)\nPayload Length: 33\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x0004)\nPayload Length: 33\n") } // RoutingActivationRequest PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) @@ -477,7 +476,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x5)\nPayload Length: 11\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x0005)\nPayload Length: 11\n") } PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) @@ -524,7 +523,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 11); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x5)\nPayload Length: 11\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x0005)\nPayload Length: 11\n") } // RoutingActivationResponse PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) @@ -564,7 +563,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x6)\nPayload Length: 9\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x0006)\nPayload Length: 9\n") } PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) @@ -612,7 +611,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 13); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x6)\nPayload Length: 13\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x0006)\nPayload Length: 13\n") } // --------------- // AliveCheckRequestPacket @@ -645,7 +644,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x7)\nPayload Length: 0\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x0007)\nPayload Length: 0\n") } PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) @@ -685,7 +684,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x7)\nPayload Length: 0\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x0007)\nPayload Length: 0\n") } // --------------- // AliveCheckResponsePacket @@ -724,7 +723,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x8)\nPayload Length: 2\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x0008)\nPayload Length: 2\n") } PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) @@ -764,7 +763,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 2); PTF_ASSERT_EQUAL( _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x8)\nPayload Length: 2\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x0008)\nPayload Length: 2\n") } // ------------------ // EntityStatusRequestPacket diff --git a/Tests/Pcap++Test/Common/PcapFileNamesDef.h b/Tests/Pcap++Test/Common/PcapFileNamesDef.h index d5ed769d31..41d724152b 100644 --- a/Tests/Pcap++Test/Common/PcapFileNamesDef.h +++ b/Tests/Pcap++Test/Common/PcapFileNamesDef.h @@ -34,4 +34,3 @@ #define EXAMPLE_PCAP_DESTRUCTOR2_PATH "PcapExamples/destructor2.pcap" #define EXAMPLE_PCAP_NANO_PATH "PcapExamples/nanosecs.pcap" #define EXAMPLE_PCAPNG_NANO_PATH "PcapExamples/nanosecs.pcapng" -#define EXAMPLE_PCAPNG_DOIP_PATH "PcapExamples/doip.pcap" diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index 2f6ebf149e..ccaaec4756 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -62,9 +62,6 @@ PTF_TEST_CASE(TestHttpResponseParsing); PTF_TEST_CASE(TestPrintPacketAndLayers); PTF_TEST_CASE(TestDnsParsing); -// Implemented in DoIpTests.cpp -PTF_TEST_CASE(DoIpPacketParsing); - // Implemented in TcpReassemblyTests.cpp PTF_TEST_CASE(TestTcpReassemblySanity); PTF_TEST_CASE(TestTcpReassemblyRetran); diff --git a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp index cae1d41687..0c613f786e 100644 --- a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp +++ b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp @@ -475,20 +475,3 @@ PTF_TEST_CASE(TestDnsParsing) // wireshark filter: dns.count.add_rr > 0 and dns.resp.type == 47 PTF_ASSERT_EQUAL(additionalWithTypeNSEC, 14); } // TestDnsParsing - -PTF_TEST_CASE(DoIpPacketParsing) -{ - pcpp::PcapFileReaderDevice reader(EXAMPLE_PCAPNG_DOIP_PATH); - PTF_ASSERT_TRUE(reader.open()); - pcpp::RawPacket rawPacket; - while (reader.getNextPacket(rawPacket)) - { - pcpp::Packet packet(&rawPacket); - std::cout << packet.toString(); - // pcpp::DoIpLayer* doipLayer = packet.getLayerOfType(); - // PTF_ASSERT_TRUE(doipLayer->resolveProtocolVersion(doipLayer->getProtocolVersion(), - // doipLayer->getInvertProtocolVersion(), doipLayer->getPayloadType())); - // PTF_ASSERT_TRUE(doipLayer->resolvePayloadLength(doipLayer->getPayloadLength(), doipLayer->getPayloadType())); - pcpp::multiPlatformSleep(1); - } -} diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 002f119c92..ca6c2b50b4 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -199,7 +199,6 @@ int main(int argc, char* argv[]) PTF_START_RUNNING_TESTS(userTagsInclude, userTagsExclude, configTags); testSetUp(); - PTF_RUN_TEST(DoIpPacketParsing, "no_network"); PTF_RUN_TEST(TestIPAddress, "no_network;ip"); PTF_RUN_TEST(TestMacAddress, "no_network;mac"); PTF_RUN_TEST(TestLRUList, "no_network"); From dd26c31035aff533577d5f4f43ee636f00cccbfd Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Mon, 9 Dec 2024 01:22:29 -0500 Subject: [PATCH 04/43] other fix for DoIpLayerData --- Packet++/header/DoIpLayerData.h | 8 ++++---- Packet++/src/DoIpLayerData.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 1b3c3e8736..5c8d615962 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -414,7 +414,7 @@ namespace pcpp std::array eid; /**< Electronic Identifier (EID). */ std::array gid; /**< Group Identifier (GID). */ DoIpActionCodes furtherActionRequired; /**< Action required after the announcement. */ - DoIpSyncStatus syncStatus; /**< version and invert version are synchronized */ + DoIpSyncStatus syncStatus; /**< version and invert version are synchronized. */ /** * \brief Returns the type of the message. @@ -599,12 +599,12 @@ namespace pcpp * - `status`: Set to `DoIpEntityStatus::GATEWAY`, indicating the entity is acting as a gateway. * - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. * - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. - * - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object + * - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object creation. * * @code * EntityStatusResponseData data; * data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, - * 0x03}) + * 0x03}). */ EntityStatusResponseData(); @@ -679,7 +679,7 @@ namespace pcpp uint16_t sourceAddress; /**< Source address of the message. */ uint16_t targetAddress; /**< Target address for the diagnostic message. */ - std::vector diagnosticData; /**< Diagnostic message data with dynamic length*/ + std::vector diagnosticData; /**< Diagnostic message data with dynamic length. */ /** * \brief Returns the type of the message. diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 0a814e0653..32d06fdc9d 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -339,7 +339,7 @@ namespace pcpp std::string VehicleAnnouncementData::toString() const { std::stringstream os; - os << "VIN: " << std::string(vin.data(), vin.end()) << std::endl; + os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << std::endl; os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << std::endl; os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << std::endl; os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << std::endl; From 2ed8c0a4402cdbec08ce8bca8b862bd431e73806 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Mon, 6 Jan 2025 01:52:24 -0500 Subject: [PATCH 05/43] .add doipPackets.pcapng containg all doip packets. .improve maps searchs for doipEnumsToStrings .cover more uses cases based on codecov feedback --- Packet++/CMakeLists.txt | 2 +- Packet++/header/DoIpLayerData.h | 4 +- Packet++/header/ProtocolType.h | 10 +-- Packet++/src/DoIpLayer.cpp | 24 +++++- Packet++/src/DoIpLayerData.cpp | 15 +++- .../DoIpDiagnosticAckMessagePacket.dat | 2 +- .../DoIpDiagnosticNackMessagePacket.dat | 2 +- .../PacketExamples/doipPackets.pcapng | Bin 0 -> 1836 bytes Tests/Packet++Test/Tests/DoIpTests.cpp | 76 +++++++++++++++--- 9 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 Tests/Packet++Test/PacketExamples/doipPackets.pcapng diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index 331d1acc42..deb0b340c0 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -81,11 +81,11 @@ set(public_headers header/DnsLayer.h header/DnsResourceData.h header/DnsResource.h - header/EthDot3Layer.h header/DoIpEnumToString.h header/DoIpEnums.h header/DoIpLayer.h header/DoIpLayerData.h + header/EthDot3Layer.h header/EthLayer.h header/FtpLayer.h header/GreLayer.h diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 5c8d615962..614d105765 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -197,8 +197,8 @@ namespace pcpp * \brief Retrieves the raw binary data of the message. * \return A vector of bytes representing the message data. */ - std::vector getData() const override; + /** * @brief Parses the Routing Activation Response data from a DoIpLayer. * @@ -249,8 +249,8 @@ namespace pcpp * \brief Retrieves the raw binary data of the message. * \return A vector of bytes representing the message data. */ - std::vector getData() const override; + /** * @brief Parses and initializes the Generic Header NACK data from a DoIpLayer. * diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index 6349849306..86747b957e 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -247,11 +247,6 @@ namespace pcpp */ const ProtocolType ESP = 37; - /** - * Diagnostic over IP protocol (DOIP) - */ - const ProtocolType DOIP = 38; - /** * IPSec protocol family (AH and ESP protocols) */ @@ -362,6 +357,11 @@ namespace pcpp */ const ProtocolType GTPv2 = 57; + /** + * Diagnostic over IP protocol (DOIP) + */ + const ProtocolType DOIP = 58; + /** * An enum representing OSI model layers */ diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 8a96cc3973..ea35bbb809 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -33,7 +33,15 @@ namespace pcpp std::string DoIpLayer::getProtocolVersionAsStr() const { - return DoIpEnumToStringProtocolVersion.at(getProtocolVersion()); + auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); + if (it != DoIpEnumToStringProtocolVersion.end()) + { + return it->second; + } + else + { + return "Unknown Protocol Version"; + } } void DoIpLayer::setProtocolVersion(DoIpProtocolVersion version) @@ -63,7 +71,15 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { - return DoIpEnumToStringPayloadType.at(getPayloadType()); + auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); + if (it != DoIpEnumToStringPayloadType.end()) + { + return it->second; + } + else + { + return "Unknown Payload type"; + } } uint32_t DoIpLayer::getPayloadLength() const @@ -143,8 +159,8 @@ namespace pcpp uint32_t length = getPayloadLength(); os << "DOIP Layer:" << std::endl; - os << "Protocol Version: " << DoIpEnumToStringProtocolVersion.at(version) << std::hex << " (0x" - << unsigned((uint8_t)version) << ")" << std::endl; + os << "Protocol Version: " << getProtocolVersionAsStr() << std::hex << " (0x" << unsigned((uint8_t)version) + << ")" << std::endl; os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << std::setw(4) << std::setfill('0') << (uint16_t)type << ")" << std::endl; os << std::dec << "Payload Length: " << length << std::endl; diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 32d06fdc9d..5d98a30eb7 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -689,7 +689,7 @@ namespace pcpp // Diagnostic Ack Message functions definitions DiagnosticAckMessageData::DiagnosticAckMessageData() : sourceAddress(0x0000), targetAddress(0x0000), ackCode(DoIpDiagnosticAckCodes::ACK), - previousMessage{ 0x22, 0xf1, 01, 0x02 } + previousMessage{ 0x22, 0xf1, 0x01, 0x02 } {} DoIpPayloadTypes DiagnosticAckMessageData::getType() const { @@ -701,7 +701,11 @@ namespace pcpp os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; os << "ack code: " << DoIpEnumToStringAckCode.at(ackCode) << " (0x" << unsigned(ackCode) << ")" << std::endl; - + if (!previousMessage.empty()) + { + os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) + << std::endl; + } return os.str(); } std::vector DiagnosticAckMessageData::getData() const @@ -769,7 +773,7 @@ namespace pcpp // Diagnostic Nack Message functions definitions DiagnosticNackMessageData::DiagnosticNackMessageData() : sourceAddress(0x0000), targetAddress(0x0000), - nackCode(DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS), previousMessage{ 0x22, 0xf1, 01, 0x02 } + nackCode(DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS), previousMessage{ 0x22, 0xf1, 0x01, 0x02 } {} DoIpPayloadTypes DiagnosticNackMessageData::getType() const { @@ -782,6 +786,11 @@ namespace pcpp os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; os << "nack code: " << DoIpEnumToStringDiagnosticNackCodes.at(nackCode) << std::hex << " (0x" << unsigned(nackCode) << ")" << std::endl; + if (!previousMessage.empty()) + { + os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) + << std::endl; + } return os.str(); } std::vector DiagnosticNackMessageData::getData() const diff --git a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat index 371f162d4c..8e33eb555f 100644 --- a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat +++ b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticAckMessagePacket.dat @@ -1 +1 @@ -54e1ad6bac15001a37bfee740800450000354de80000ff062e00a9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f3acc000002fd80020000000540100e8000 \ No newline at end of file +54e1ad6bac15001a37bfee740800450000384de80000ff062dfda9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f49a2000002fd80020000000840100e800022f101 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat index a912a45f94..a77cf20b32 100644 --- a/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat +++ b/Tests/Packet++Test/PacketExamples/DoIpDiagnosticNackMessagePacket.dat @@ -1 +1 @@ -54e1ad6bac15001a37bfee740800450000354de80000ff062e00a9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f3acc000002fd80030000000540100e8002 \ No newline at end of file +54e1ad6bac15001a37bfee740800450000384de80000ff062dfda9fe75eea9fe75ef3458d25e00191aa0ab87803d5018164f47a1000002fd80030000000840100e800222f101 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/doipPackets.pcapng b/Tests/Packet++Test/PacketExamples/doipPackets.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..f7c5b3de21af8a1a191765b33790b959715d5485 GIT binary patch literal 1836 zcmbtVNoW&M7=E3$=^m3-yHR8Wmo6HUIBDZPwT&7zTDs7&w8dx&sa;7^m+B#S&=$N1 z9z}Z4gS3iz5PQ+8m&64mAXG%6;6YSsPaf15|L;wvTc}X{;h*| zGA&M(4f=qMz9+rVw;0pf7Fo7V z=dci!QG7BDbAAnXANd+YU%(S|RzCI1OxD>4G@apgNul~}Mjh)4e@6CFp{a(z*XaYY z!H^7W=x!y4A-|!wKY}}G4o~Ql3fEog6QijLc>s^3#8$F`18&ldx}_mkY(qC-s_~LI87eXZ3b-WEK0_*xHbj?%@fw+&=ROwaoZ~90NbxA}LPqwLPrx z{*Xdm6f6KcBE73Oy>hSWHrAZ<-_R6bJGp z?x}7%>~Kh~7E6^`vP$MHvO!%Qzp7l|RLEh7?bpNoAv?|C?880hR)OXD*8P0NIm_`d zU=6{e(RRgVwCo$3i%N z;R!XjVI`ei@3oq9t!obU5GH!mn2;ZS2BQVEzDlalv6DyNIg(fjtLYo0zn5=7?DzGZ u>hyGY#N%g0kNWcw=-|S)&5^silH>C!<((si=CAb-N5?!r+|)U);P?x~_vDrU literal 0 HcmV?d00001 diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index accc79c1bb..22d7bff69c 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -42,6 +42,11 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "generic header nack code: Unknown payload type (0x1)\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); @@ -195,6 +200,11 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "VIN: BAUNEE4MZ17042403\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, @@ -280,6 +290,11 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "EID: 4241554e4545\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, @@ -369,6 +384,10 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_EQUAL( data.toString(), "VIN: BAUNEE4MZ17042403\nlogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nfurther action required:No further action required (0x0)\nVIN/GID sync status: NULL\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -468,6 +487,10 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL( data.toString(), "sourceAddress: 0xe80\nactivation type: Default (0x0)\nreserved by ISO: 00000000\nReserved by OEM: 00000000\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationResponseData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -555,6 +578,10 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_EQUAL( data.toString(), "logical address of external tester: 0xe80\nsource address: 0x4010\nrouting activation response code: Routing successfully activated (0x10)\nreserved by ISO: 00000000\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -715,6 +742,10 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "source address: 0x0\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -867,6 +898,10 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL( data.toString(), "Entity status: DoIP gateway (0x0)\nmaximum Concurrent Socket: 1\ncurrently Opened Socket: 0\nmaximum Data Size: 0x00000fff\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1021,6 +1056,10 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "diagnostic power mode: not ready (0x0)\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1100,6 +1139,10 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "source address: 0xe80\ntarget address: 0x4010\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1174,7 +1217,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x3acc)); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x49a2)); pcpp::DoIpLayer* doipLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1182,16 +1225,22 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) pcpp::DiagnosticAckMessageData data; if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\n"); + PTF_ASSERT_EQUAL( + data.toString(), + "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\nprevious message: 22f101\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 5); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 5\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 8\n") } PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) @@ -1259,7 +1308,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x3acc)); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x47a1)); pcpp::DoIpLayer* doipLayer = DiagnosticNackMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1267,17 +1316,22 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) pcpp::DiagnosticNackMessageData data; if (data.buildFromLayer(doipLayer)) // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), - "source address: 0x4010\ntarget address: 0xe80\nnack code: Invalid source address (0x2)\n"); + PTF_ASSERT_EQUAL( + data.toString(), + "source address: 0x4010\ntarget address: 0xe80\nnack code: Invalid source address (0x2)\nprevious message: 22f101\n"); + // wrong build + PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; + PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 5); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); PTF_ASSERT_EQUAL( doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 5\n") + "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 8\n") } PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) @@ -1309,10 +1363,6 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); From 3ba3c71b6cb1bfce543e5ede1186665da67b39b0 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 9 Jan 2025 04:15:29 -0500 Subject: [PATCH 06/43] fix dioxygene and gersemi errors --- Packet++/CMakeLists.txt | 146 +++++++++--------- Packet++/header/DoIpLayerData.h | 3 +- Tests/Pcap++Test/Tests/PacketParsingTests.cpp | 2 - Tests/Pcap++Test/main.cpp | 1 + 4 files changed, 77 insertions(+), 75 deletions(-) diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index 0e98e963a5..c5266cbb1c 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -70,78 +70,80 @@ add_library( # Force hash-library pcapng to be link fully static ) -set(public_headers - header/ArpLayer.h - header/Asn1Codec.h - header/BgpLayer.h - header/CotpLayer.h - header/DhcpLayer.h - header/DhcpV6Layer.h - header/DnsLayerEnums.h - header/DnsLayer.h - header/DnsResourceData.h - header/DnsResource.h - header/DoIpEnumToString.h - header/DoIpEnums.h - header/DoIpLayer.h - header/DoIpLayerData.h - header/EthDot3Layer.h - header/EthLayer.h - header/FtpLayer.h - header/GreLayer.h - header/GtpLayer.h - header/HttpLayer.h - header/IcmpLayer.h - header/IcmpV6Layer.h - header/IgmpLayer.h - header/IPLayer.h - header/IPReassembly.h - header/IPSecLayer.h - header/IPv4Layer.h - header/IPv6Extensions.h - header/IPv6Layer.h - header/Layer.h - header/LdapLayer.h - header/LLCLayer.h - header/MplsLayer.h - header/NullLoopbackLayer.h - header/NdpLayer.h - header/NflogLayer.h - header/NtpLayer.h - header/Packet.h - header/PacketTrailerLayer.h - header/PacketUtils.h - header/PayloadLayer.h - header/PPPoELayer.h - header/ProtocolType.h - header/RadiusLayer.h - header/RawPacket.h - header/S7CommLayer.h - header/SdpLayer.h - header/SingleCommandTextProtocol.h - header/SipLayer.h - header/SllLayer.h - header/Sll2Layer.h - header/SmtpLayer.h - header/SomeIpLayer.h - header/SomeIpSdLayer.h - header/SSHLayer.h - header/SSLCommon.h - header/SSLHandshake.h - header/SSLLayer.h - header/StpLayer.h - header/TcpLayer.h - header/TcpReassembly.h - header/TelnetLayer.h - header/TextBasedProtocol.h - header/TLVData.h - header/TpktLayer.h - header/UdpLayer.h - header/VlanLayer.h - header/VrrpLayer.h - header/VxlanLayer.h - header/WakeOnLanLayer.h - header/WireGuardLayer.h) +set( + public_headers + header/ArpLayer.h + header/Asn1Codec.h + header/BgpLayer.h + header/CotpLayer.h + header/DhcpLayer.h + header/DhcpV6Layer.h + header/DnsLayerEnums.h + header/DnsLayer.h + header/DnsResourceData.h + header/DnsResource.h + header/DoIpEnums.h + header/DoIpEnumToString.h + header/DoIpLayer.h + header/DoIpLayerData.h + header/EthDot3Layer.h + header/EthLayer.h + header/FtpLayer.h + header/GreLayer.h + header/GtpLayer.h + header/HttpLayer.h + header/IcmpLayer.h + header/IcmpV6Layer.h + header/IgmpLayer.h + header/IPLayer.h + header/IPReassembly.h + header/IPSecLayer.h + header/IPv4Layer.h + header/IPv6Extensions.h + header/IPv6Layer.h + header/Layer.h + header/LdapLayer.h + header/LLCLayer.h + header/MplsLayer.h + header/NullLoopbackLayer.h + header/NdpLayer.h + header/NflogLayer.h + header/NtpLayer.h + header/Packet.h + header/PacketTrailerLayer.h + header/PacketUtils.h + header/PayloadLayer.h + header/PPPoELayer.h + header/ProtocolType.h + header/RadiusLayer.h + header/RawPacket.h + header/S7CommLayer.h + header/SdpLayer.h + header/SingleCommandTextProtocol.h + header/SipLayer.h + header/SllLayer.h + header/Sll2Layer.h + header/SmtpLayer.h + header/SomeIpLayer.h + header/SomeIpSdLayer.h + header/SSHLayer.h + header/SSLCommon.h + header/SSLHandshake.h + header/SSLLayer.h + header/StpLayer.h + header/TcpLayer.h + header/TcpReassembly.h + header/TelnetLayer.h + header/TextBasedProtocol.h + header/TLVData.h + header/TpktLayer.h + header/UdpLayer.h + header/VlanLayer.h + header/VrrpLayer.h + header/VxlanLayer.h + header/WakeOnLanLayer.h + header/WireGuardLayer.h +) # Don't use set_target_properties CMake limit to 50 elements set_property(TARGET Packet++ PROPERTY PUBLIC_HEADER ${public_headers}) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 614d105765..f821424f58 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -604,7 +604,8 @@ namespace pcpp * @code * EntityStatusResponseData data; * data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, - * 0x03}). + * 0x03}); + * @endcode */ EntityStatusResponseData(); diff --git a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp index 0c613f786e..a22fbb9437 100644 --- a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp +++ b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp @@ -5,9 +5,7 @@ #include "Packet.h" #include "HttpLayer.h" #include "DnsLayer.h" -#include "DoIpLayer.h" #include "PcapFileDevice.h" -#include PTF_TEST_CASE(TestHttpRequestParsing) { diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index ca6c2b50b4..784a9e0d6f 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -199,6 +199,7 @@ int main(int argc, char* argv[]) PTF_START_RUNNING_TESTS(userTagsInclude, userTagsExclude, configTags); testSetUp(); + PTF_RUN_TEST(TestIPAddress, "no_network;ip"); PTF_RUN_TEST(TestMacAddress, "no_network;mac"); PTF_RUN_TEST(TestLRUList, "no_network"); From 7896a9e37e51ef2b08bbf26ac06fba22eb64f095 Mon Sep 17 00:00:00 2001 From: Raissi Oussama <80215516+raissi-oussema@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:57:57 -0500 Subject: [PATCH 07/43] Update Packet++/header/DoIpLayer.h Co-authored-by: Dimitar Krastev --- Packet++/header/DoIpLayer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index cb5c67cb85..55401d7bb6 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -36,7 +36,7 @@ namespace pcpp #pragma pack(pop) /** - * @class DoipLayer + * @class DoIpLayer * Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported */ class DoIpLayer : public Layer From c159be901b0b6667e60976b564fa422678b9952c Mon Sep 17 00:00:00 2001 From: Raissi Oussama <80215516+raissi-oussema@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:36:42 -0500 Subject: [PATCH 08/43] Update Packet++/src/DoIpLayer.cpp Co-authored-by: Dimitar Krastev --- Packet++/src/DoIpLayer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index ea35bbb809..7b24094385 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -148,12 +148,11 @@ namespace pcpp std::string DoIpLayer::toString() const { - std::stringstream os; if (!resolveLayer()) { - os << "Malformed doip Packet"; - return os.str(); + return "Malformed doip Packet"; } + std::stringstream os; DoIpProtocolVersion version = getProtocolVersion(); DoIpPayloadTypes type = getPayloadType(); uint32_t length = getPayloadLength(); From 14bc5a5a76c52476bf722a0eae99b2739195c5a1 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 16 Jan 2025 01:40:37 -0500 Subject: [PATCH 09/43] add diff improvement and dioxygene style --- Packet++/header/DoIpEnumToString.h | 4 +- Packet++/header/DoIpEnums.h | 4 +- Packet++/header/DoIpLayer.h | 6 +- Packet++/header/DoIpLayerData.h | 190 ++++++++++++++--------------- Packet++/src/DoIpLayer.cpp | 21 ++-- Packet++/src/DoIpLayerData.cpp | 68 +++++------ 6 files changed, 145 insertions(+), 148 deletions(-) diff --git a/Packet++/header/DoIpEnumToString.h b/Packet++/header/DoIpEnumToString.h index d5bf03cb62..5f0965e6c3 100644 --- a/Packet++/header/DoIpEnumToString.h +++ b/Packet++/header/DoIpEnumToString.h @@ -6,8 +6,8 @@ /// @file /** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib + * @namespace pcpp + * @brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { diff --git a/Packet++/header/DoIpEnums.h b/Packet++/header/DoIpEnums.h index 78cc1648e0..43c20aa1e2 100644 --- a/Packet++/header/DoIpEnums.h +++ b/Packet++/header/DoIpEnums.h @@ -6,8 +6,8 @@ /// @file /** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib + * @namespace pcpp + * @brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 55401d7bb6..8128286ca0 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -12,8 +12,8 @@ /// @file /** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib + * @namespace pcpp + * @brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { @@ -155,7 +155,7 @@ namespace pcpp * Set the doip payload length * @param[in] length the doip payload length to set */ - void setPayloadength(uint32_t length); + void setPayloadLength(uint32_t length); /** * copy data from msgFields to dest diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index f821424f58..8c88d0ab04 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -11,8 +11,8 @@ /// @file /** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus library + * @namespace pcpp + * @brief The main namespace for the PcapPlusPlus library */ namespace pcpp { @@ -45,7 +45,7 @@ namespace pcpp class DoIpLayer; /** - * \brief A pure abstract class representing the basic structure of DoIP messages. + * @brief A pure abstract class representing the basic structure of DoIP messages. * * This interface defines methods to retrieve the type, string representation, * and binary data of DoIP messages. All DoIP message classes must implement this interface. @@ -56,27 +56,27 @@ namespace pcpp virtual ~IDoIpMessageData() = default; /** - * \brief Returns the type of the DoIP message. - * \return The type of the message as a `DoIpPayloadTypes` enum. + * @brief Returns the type of the DoIP message. + * @return The type of the message as a `DoIpPayloadTypes` enum. */ virtual DoIpPayloadTypes getType() const = 0; /** - * \brief Converts the message data to a human-readable string. - * \return The string representation of the message. + * @brief Converts the message data to a human-readable string. + * @return The string representation of the message. */ virtual std::string toString() const = 0; /** - * \brief Retrieves the raw binary data of the message. - * \return The message data as a vector of bytes. + * @brief Retrieves the raw binary data of the message. + * @return The message data as a vector of bytes. */ virtual std::vector getData() const = 0; /** - * \brief build IDoIpMessageData from DoIpLayer + * @brief build IDoIpMessageData from DoIpLayer * @param[in] doipLayer pointer to doipLayer to retrieve data from - * \return true if encapsulating process is done successufly else false. + * @return true if encapsulating process is done successufly else false. * * @exception Logs an error and returns `false` if: * - The input layer is null. @@ -88,7 +88,7 @@ namespace pcpp /** * @class RoutingActivationRequestData - * \brief Represents a Routing Activation Request message in DoIP. + * @brief Represents a Routing Activation Request message in DoIP. * * This class encapsulates data for a Routing Activation Request message, * including source address, activation type, and reserved fields. @@ -114,20 +114,20 @@ namespace pcpp std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Routing Activation Request message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Routing Activation Request message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -155,7 +155,7 @@ namespace pcpp /** * @class RoutingActivationResponseData - * \brief Represents a Routing Activation Response message in DoIP. + * @brief Represents a Routing Activation Response message in DoIP. * * This class encapsulates data for a Routing Activation Response message, * including logical address, source address, response code, and reserved fields. @@ -182,20 +182,20 @@ namespace pcpp std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Routing Activation Response message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Routing Activation Response message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -215,7 +215,7 @@ namespace pcpp /** * @class GenericHeaderNackData - * \brief Represents a Generic Header Negative Acknowledgment message in DoIP. + * @brief Represents a Generic Header Negative Acknowledgment message in DoIP. * * This class encapsulates data for a Generic Header NACK message, including * the NACK code to indicate the failure. @@ -234,20 +234,20 @@ namespace pcpp DoIpGenericHeaderNackCodes genericNackCode; /**< The NACK code indicating the error. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Generic Header NACK message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Generic Header NACK message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -271,7 +271,7 @@ namespace pcpp /** * @class VehicleIdentificationRequestEIDData - * \brief Represents a Vehicle Identification Request with EID message in DoIP. + * @brief Represents a Vehicle Identification Request with EID message in DoIP. * * This class encapsulates data for a Vehicle Identification Request message * that includes the Electronic Identifier (EID). @@ -290,20 +290,20 @@ namespace pcpp std::array eid; /**< Electronic Identifier (EID). */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Vehicle Identification Request EID message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Vehicle Identification Request EID message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -327,7 +327,7 @@ namespace pcpp /** * @class VehicleIdentificationRequestVINData - * \brief Represents a Vehicle Identification Request with VIN message in DoIP. + * @brief Represents a Vehicle Identification Request with VIN message in DoIP. * * This class encapsulates data for a Vehicle Identification Request message * that includes the Vehicle Identification Number (VIN). @@ -346,20 +346,20 @@ namespace pcpp std::array vin; /**< Vehicle Identification Number (VIN). */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Vehicle Identification Request VIN message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Vehicle Identification Request VIN message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -388,7 +388,7 @@ namespace pcpp /** * @class VehicleAnnouncementData - * \brief Represents a Vehicle Announcement message in DoIP. + * @brief Represents a Vehicle Announcement message in DoIP. * * This class encapsulates data for a Vehicle Announcement message, including * VIN, logical address, EID, GID, and further action required. @@ -417,20 +417,20 @@ namespace pcpp DoIpSyncStatus syncStatus; /**< version and invert version are synchronized. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Vehicle Announcement message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Vehicle Announcement message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -464,7 +464,7 @@ namespace pcpp /** * @class AliveCheckResponseData - * \brief Represents an Alive Check Response message in DoIP. + * @brief Represents an Alive Check Response message in DoIP. * * This class encapsulates data for an Alive Check Response message, * including the source address. @@ -483,20 +483,20 @@ namespace pcpp uint16_t sourceAddress; /**< Source address of the Alive Check Response message. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Alive Check Response message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Alive Check Response message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -524,7 +524,7 @@ namespace pcpp /** * @class DiagnosticPowerModeResponseData - * \brief Represents a Diagnostic Power Mode Response message in DoIP. + * @brief Represents a Diagnostic Power Mode Response message in DoIP. * * This class encapsulates data for a Diagnostic Power Mode Response message, * including a power mode code indicating the current power mode. @@ -543,20 +543,20 @@ namespace pcpp DoIpDiagnosticPowerModeCodes powerModeCode; /**< Code representing the power mode. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Diagnostic Power Mode Response message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Diagnostic Power Mode Response message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -584,7 +584,7 @@ namespace pcpp /** * @class EntityStatusResponseData - * \brief Represents an Entity Status Response message in DoIP. + * @brief Represents an Entity Status Response message in DoIP. * * This class encapsulates data for an Entity Status Response message, * including status, maximum concurrent sockets, open sockets, and maximum data size. @@ -616,20 +616,20 @@ namespace pcpp maxDataSize; /**< Maximum data size that can be handled (4 bytes optional). */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Entity Status Response message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Entity Status Response message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -661,7 +661,7 @@ namespace pcpp /** * @class DiagnosticMessageData - * \brief Represents a Diagnostic Message in DoIP. + * @brief Represents a Diagnostic Message in DoIP. * This class encapsulates data for a Diagnostic Message, including source * and target addresses, as well as diagnostic data. */ @@ -683,20 +683,20 @@ namespace pcpp std::vector diagnosticData; /**< Diagnostic message data with dynamic length. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Diagnostic Message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Diagnostic Message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -727,7 +727,7 @@ namespace pcpp /** * @class DiagnosticAckMessageData - * \brief Represents a Diagnostic Acknowledgment Message in DoIP. + * @brief Represents a Diagnostic Acknowledgment Message in DoIP. * * This class encapsulates data for a Diagnostic Acknowledgment Message, * including source and target addresses, as well as the acknowledgment code. @@ -752,20 +752,20 @@ namespace pcpp std::vector previousMessage; /**< Previous acknowlged message. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Diagnostic Acknowledgment Message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Diagnostic Acknowledgment Message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; @@ -797,7 +797,7 @@ namespace pcpp /** * @class DiagnosticNackMessageData - * \brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. + * @brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. * * This class encapsulates data for a Diagnostic Negative Acknowledgment * Message, including source and target addresses, as well as the NACK code. @@ -823,20 +823,20 @@ namespace pcpp std::vector previousMessage; /**< Previous acknowlged message. */ /** - * \brief Returns the type of the message. - * \return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. + * @brief Returns the type of the message. + * @return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. */ DoIpPayloadTypes getType() const override; /** - * \brief Converts the message data to a human-readable string. - * \return A string representation of the Diagnostic Negative Acknowledgment Message. + * @brief Converts the message data to a human-readable string. + * @return A string representation of the Diagnostic Negative Acknowledgment Message. */ std::string toString() const override; /** - * \brief Retrieves the raw binary data of the message. - * \return A vector of bytes representing the message data. + * @brief Retrieves the raw binary data of the message. + * @return A vector of bytes representing the message data. */ std::vector getData() const override; diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 7b24094385..e5fa22c7d1 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -66,7 +66,7 @@ namespace pcpp void DoIpLayer::setPayloadType(DoIpPayloadTypes type) { - getDoIpHeader()->payloadType = htobe16((uint16_t)type); + getDoIpHeader()->payloadType = htobe16(static_cast(type)); } std::string DoIpLayer::getPayloadTypeAsStr() const @@ -87,7 +87,7 @@ namespace pcpp return htobe32(getDoIpHeader()->payloadLength); } - void DoIpLayer::setPayloadength(uint32_t Payloadength) + void DoIpLayer::setPayloadLength(uint32_t Payloadength) { getDoIpHeader()->payloadLength = be32toh(Payloadength); } @@ -109,7 +109,7 @@ namespace pcpp PCPP_LOG_ERROR("Invalid/unsupported DoIP version!"); return false; } - if ((uint8_t)(version) != (uint8_t) ~(inVersion)) + if ((uint8_t)(version) != (uint8_t)~(inVersion)) { PCPP_LOG_ERROR("Version and invert version are not synchronised !"); return false; @@ -157,12 +157,12 @@ namespace pcpp DoIpPayloadTypes type = getPayloadType(); uint32_t length = getPayloadLength(); - os << "DOIP Layer:" << std::endl; + os << "DOIP Layer:" << "\n"; os << "Protocol Version: " << getProtocolVersionAsStr() << std::hex << " (0x" << unsigned((uint8_t)version) - << ")" << std::endl; + << ")" << "\n"; os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << std::setw(4) << std::setfill('0') - << (uint16_t)type << ")" << std::endl; - os << std::dec << "Payload Length: " << length << std::endl; + << (uint16_t)type << ")" << "\n"; + os << std::dec << "Payload Length: " << length << "\n"; return os.str(); } @@ -176,8 +176,7 @@ namespace pcpp { m_DataLen = sizeof(doiphdr); m_Protocol = DOIP; - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); + m_Data = new uint8_t[m_DataLen]{}; } void DoIpLayer::buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data) @@ -189,7 +188,7 @@ namespace pcpp case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: setPayloadType(type); - setPayloadength(0); + setPayloadLength(0); break; default: // Payload handling for rest of types @@ -203,7 +202,7 @@ namespace pcpp size_t headerLength = sizeof(doiphdr); setPayloadType(data->getType()); - setPayloadength(payloadSize); + setPayloadLength(payloadSize); extendLayer(headerLength, payloadSize); serializeData(m_Data + headerLength, data->getData()); break; diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 5d98a30eb7..3bbadf9672 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -19,10 +19,10 @@ namespace pcpp std::string RoutingActivationRequestData::toString() const { std::stringstream os; - os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "activation type: " << DoIpEnumToStringActivationTypes.at(activationType) << std::hex << " (0x" - << unsigned(activationType) << ")" << std::endl; - os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << std::endl; + << unsigned(activationType) << ")" << "\n"; + os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (reservedOem) { os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) << '\n'; @@ -94,15 +94,14 @@ namespace pcpp { std::stringstream os; os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) - << std::endl; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + << "\n"; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "routing activation response code: " << DoIpEnumToStringRoutingResponseCodes.at(responseCode) << std::hex - << " (0x" << unsigned(responseCode) << ")" << std::endl; - os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << std::endl; + << " (0x" << unsigned(responseCode) << ")" << "\n"; + os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (reservedOem) { - os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) - << std::endl; + os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) << "\n"; } return os.str(); } @@ -180,7 +179,7 @@ namespace pcpp { std::stringstream os; os << "generic header nack code: " << DoIpEnumToStringGenericHeaderNackCodes.at(genericNackCode) << std::hex - << " (0x" << unsigned(genericNackCode) << ")" << std::endl; + << " (0x" << unsigned(genericNackCode) << ")" << "\n"; ; return os.str(); } @@ -231,7 +230,7 @@ namespace pcpp std::string VehicleIdentificationRequestEIDData::toString() const { std::stringstream os; - os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << std::endl; + os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; return os.str(); } std::vector VehicleIdentificationRequestEIDData::getData() const @@ -281,7 +280,7 @@ namespace pcpp std::string VehicleIdentificationRequestVINData::toString() const { std::stringstream os; - os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << std::endl; + os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << "\n"; return os.str(); } std::vector VehicleIdentificationRequestVINData::getData() const @@ -339,14 +338,13 @@ namespace pcpp std::string VehicleAnnouncementData::toString() const { std::stringstream os; - os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << std::endl; - os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << std::endl; - os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << std::endl; - os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << std::endl; + os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << "\n"; + os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << "\n"; + os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; + os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << "\n"; os << "further action required:" << DoIpEnumToStringActionCodes.at(furtherActionRequired) << std::hex << " (0x" - << unsigned(furtherActionRequired) << ")" << std::endl; - os << "VIN/GID sync status: " << DoIpEnumToStringSyncStatus.at(syncStatus) - << std::endl; // Convert enum to byte + << unsigned(furtherActionRequired) << ")" << "\n"; + os << "VIN/GID sync status: " << DoIpEnumToStringSyncStatus.at(syncStatus) << "\n"; // Convert enum to byte return os.str(); } @@ -437,7 +435,7 @@ namespace pcpp std::string AliveCheckResponseData::toString() const { std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; return os.str(); } std::vector AliveCheckResponseData::getData() const @@ -492,7 +490,7 @@ namespace pcpp { std::stringstream os; os << "diagnostic power mode: " << DoIpEnumToStringDiagnosticPowerModeCodes.at(powerModeCode) << std::hex - << " (0x" << unsigned(powerModeCode) << ")" << std::endl; + << " (0x" << unsigned(powerModeCode) << ")" << "\n"; return os.str(); } @@ -548,13 +546,13 @@ namespace pcpp { std::stringstream os; os << "Entity status: " << DoIpEnumToStringEntityStatusNodeTypes.at(nodeType) << std::hex << " (0x" - << unsigned(nodeType) << ")" << std::endl; - os << "maximum Concurrent Socket: " << unsigned(maxConcurrentSockets) << std::endl; - os << "currently Opened Socket: " << unsigned(currentlyOpenSockets) << std::endl; + << unsigned(nodeType) << ")" << "\n"; + os << "maximum Concurrent Socket: " << unsigned(maxConcurrentSockets) << "\n"; + os << "currently Opened Socket: " << unsigned(currentlyOpenSockets) << "\n"; if (maxDataSize) { os << "maximum Data Size: " - << "0x" << pcpp::byteArrayToHexString(maxDataSize->data(), 4) << std::endl; + << "0x" << pcpp::byteArrayToHexString(maxDataSize->data(), 4) << "\n"; } return os.str(); @@ -633,8 +631,8 @@ namespace pcpp std::string DiagnosticMessageData::toString() const { std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; return os.str(); } std::vector DiagnosticMessageData::getData() const @@ -698,13 +696,13 @@ namespace pcpp std::string DiagnosticAckMessageData::toString() const { std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; - os << "ack code: " << DoIpEnumToStringAckCode.at(ackCode) << " (0x" << unsigned(ackCode) << ")" << std::endl; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; + os << "ack code: " << DoIpEnumToStringAckCode.at(ackCode) << " (0x" << unsigned(ackCode) << ")" << "\n"; if (!previousMessage.empty()) { os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) - << std::endl; + << "\n"; } return os.str(); } @@ -782,14 +780,14 @@ namespace pcpp std::string DiagnosticNackMessageData::toString() const { std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << std::endl; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << std::endl; + os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; + os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; os << "nack code: " << DoIpEnumToStringDiagnosticNackCodes.at(nackCode) << std::hex << " (0x" - << unsigned(nackCode) << ")" << std::endl; + << unsigned(nackCode) << ")" << "\n"; if (!previousMessage.empty()) { os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) - << std::endl; + << "\n"; } return os.str(); } From 0545afe07f635e2bc6aa5ea8ff293dbdbf2c9bfd Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sat, 18 Jan 2025 05:42:23 -0500 Subject: [PATCH 10/43] . make safe search in enumsToString, add parseNextLayer for UDS layer as generic PayloadLayeruse byte shifting instead of reinterprete_cast for field crafting --- Packet++/header/DoIpEnums.h | 5 + Packet++/header/DoIpLayer.h | 4 +- Packet++/src/DoIpLayer.cpp | 12 ++ Packet++/src/DoIpLayerData.cpp | 281 +++++++++++++++++++++++---------- 4 files changed, 216 insertions(+), 86 deletions(-) diff --git a/Packet++/header/DoIpEnums.h b/Packet++/header/DoIpEnums.h index 43c20aa1e2..990c1f14af 100644 --- a/Packet++/header/DoIpEnums.h +++ b/Packet++/header/DoIpEnums.h @@ -570,6 +570,11 @@ namespace pcpp NODE = 0x01U }; + /** + * @brief Enum representing DoIP sync status (ISO 13400). + * + * These codes are used to indicate whether GID and VIN are synchronized or not. + */ enum class DoIpSyncStatus : uint8_t { /** diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 8128286ca0..cf3dd94782 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -3,6 +3,7 @@ #include #include #include "Layer.h" +#include "PayloadLayer.h" #include "IpAddress.h" #include "MacAddress.h" #include "Logger.h" @@ -215,8 +216,7 @@ namespace pcpp /** * TODO, parse UDS layer */ - void parseNextLayer() override - {} + void parseNextLayer() override; /** * @return The size of @ref doiphdr + attached fields length diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index e5fa22c7d1..64053be002 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -209,4 +209,16 @@ namespace pcpp } } } + + void DoIpLayer::parseNextLayer() + { + DiagnosticMessageData diagnosticMessage; + + if (diagnosticMessage.buildFromLayer(this)) + { + // handle UDS layer as generic PayloadLayer for now. + m_NextLayer = new PayloadLayer(diagnosticMessage.diagnosticData.data(), + diagnosticMessage.diagnosticData.size(), this, m_Packet); + } + } } // namespace pcpp diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 3bbadf9672..6e9e33aeee 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -20,8 +20,15 @@ namespace pcpp { std::stringstream os; os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - os << "activation type: " << DoIpEnumToStringActivationTypes.at(activationType) << std::hex << " (0x" - << unsigned(activationType) << ")" << "\n"; + auto it = DoIpEnumToStringActivationTypes.find(activationType); + if (it != DoIpEnumToStringActivationTypes.end()) + { + os << "activation type: " << it->second << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; + } + else + { + os << "activation type: Unknown" << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; + } os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (reservedOem) { @@ -34,9 +41,9 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); - data.push_back(static_cast(activationType)); // Convert enum to byte + data.push_back(static_cast(sourceAddress & 0xFF)); + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + data.push_back(static_cast(activationType)); data.insert(data.end(), reservedIso.begin(), reservedIso.end()); if (reservedOem) { @@ -59,17 +66,30 @@ namespace pcpp PCPP_LOG_ERROR("Cannot retrieve routing activation request data from " + doipLayer->getPayloadTypeAsStr()); return false; } + + constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(activationType) + DOIP_RESERVED_ISO_LEN; + + if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) + { + PCPP_LOG_ERROR("Insufficient data length for routing activation request payload"); + return false; + } + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - activationType = static_cast(dataPtr[2]); - std::copy(dataPtr + 3, dataPtr + 3 + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); - if (doipLayer->getDataLen() - sizeof(doiphdr) >= - sizeof(sourceAddress) + sizeof(activationType) + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN) + dataPtr += sizeof(sourceAddress); + + activationType = static_cast(dataPtr[0]); + dataPtr += sizeof(activationType); + + std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); + dataPtr += DOIP_RESERVED_ISO_LEN; + + if (doipLayer->getDataLen() - (sizeof(doiphdr) + fixedFieldLength) == DOIP_RESERVED_OEM_LEN) { reservedOem = std::unique_ptr>( new std::array()); - std::copy(dataPtr + 3 + DOIP_RESERVED_ISO_LEN, dataPtr + 3 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN, - reservedOem->begin()); + std::copy(dataPtr, dataPtr + DOIP_RESERVED_OEM_LEN, reservedOem->begin()); } else { @@ -96,8 +116,17 @@ namespace pcpp os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) << "\n"; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - os << "routing activation response code: " << DoIpEnumToStringRoutingResponseCodes.at(responseCode) << std::hex - << " (0x" << unsigned(responseCode) << ")" << "\n"; + auto it = DoIpEnumToStringRoutingResponseCodes.find(responseCode); + if (it != DoIpEnumToStringRoutingResponseCodes.end()) + { + os << "routing activation response code: " << it->second << std::hex << " (0x" << unsigned(responseCode) + << ")" << "\n"; + } + else + { + os << "routing activation response code: Unknown" << std::hex << " (0x" << unsigned(responseCode) << ")" + << "\n"; + } os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (reservedOem) { @@ -109,11 +138,12 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&logicalAddressExternalTester), - reinterpret_cast(&logicalAddressExternalTester) + - sizeof(logicalAddressExternalTester)); - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + data.push_back(static_cast(logicalAddressExternalTester & 0xFF)); + data.push_back(static_cast((logicalAddressExternalTester >> 8) & 0xFF)); + + data.push_back(static_cast(sourceAddress & 0xFF)); + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + data.push_back(static_cast(responseCode)); // Convert enum to byte data.insert(data.end(), reservedIso.begin(), reservedIso.end()); if (reservedOem) @@ -137,25 +167,33 @@ namespace pcpp return false; } - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); - if (!dataPtr) + if (doipLayer->getDataLen() - sizeof(doiphdr) < + sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) { - PCPP_LOG_ERROR("Data pointer is null"); + PCPP_LOG_ERROR("Insufficient data length for routing activation response payload"); return false; } + uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); logicalAddressExternalTester = static_cast(dataPtr[1] << 8 | dataPtr[0]); - sourceAddress = static_cast(dataPtr[3] << 8 | dataPtr[2]); - responseCode = static_cast(dataPtr[4]); + dataPtr += sizeof(logicalAddressExternalTester); + + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + dataPtr += sizeof(sourceAddress); - std::copy(dataPtr + 5, dataPtr + 5 + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); + responseCode = static_cast(dataPtr[0]); + dataPtr += sizeof(responseCode); - if (doipLayer->getDataLen() - sizeof(doiphdr) >= 5 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN) + std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); + dataPtr += DOIP_RESERVED_ISO_LEN; + + if (doipLayer->getDataLen() - (sizeof(doiphdr) + sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + + sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) == + DOIP_RESERVED_OEM_LEN) { reservedOem = std::unique_ptr>( new std::array()); - std::copy(dataPtr + 5 + DOIP_RESERVED_ISO_LEN, dataPtr + 5 + DOIP_RESERVED_ISO_LEN + DOIP_RESERVED_OEM_LEN, - reservedOem->begin()); + std::copy(dataPtr, dataPtr + DOIP_RESERVED_OEM_LEN, reservedOem->begin()); } else { @@ -178,9 +216,16 @@ namespace pcpp std::string GenericHeaderNackData::toString() const { std::stringstream os; - os << "generic header nack code: " << DoIpEnumToStringGenericHeaderNackCodes.at(genericNackCode) << std::hex - << " (0x" << unsigned(genericNackCode) << ")" << "\n"; - ; + auto it = DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); + if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) + { + os << "generic header nack code: " << it->second << std::hex << " (0x" << unsigned(genericNackCode) << ")" + << "\n"; + } + else + { + os << "generic header nack code: Unknown" << std::hex << " (0x" << unsigned(genericNackCode) << ")" << "\n"; + } return os.str(); } std::vector GenericHeaderNackData::getData() const @@ -257,7 +302,7 @@ namespace pcpp } // Validate data length (must at least accommodate EID length) - if (doipLayer->getDataLen() - sizeof(doiphdr) < DOIP_EID_LEN) + if (doipLayer->getDataLen() - sizeof(doiphdr) != DOIP_EID_LEN) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); return false; @@ -307,7 +352,7 @@ namespace pcpp } // Validate data length (must at least accommodate VIN length) - if (doipLayer->getDataLen() - sizeof(doiphdr) < DOIP_VIN_LEN) + if (doipLayer->getDataLen() - sizeof(doiphdr) != DOIP_VIN_LEN) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); return false; @@ -342,9 +387,28 @@ namespace pcpp os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << "\n"; os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << "\n"; - os << "further action required:" << DoIpEnumToStringActionCodes.at(furtherActionRequired) << std::hex << " (0x" - << unsigned(furtherActionRequired) << ")" << "\n"; - os << "VIN/GID sync status: " << DoIpEnumToStringSyncStatus.at(syncStatus) << "\n"; // Convert enum to byte + auto it = DoIpEnumToStringActionCodes.find(furtherActionRequired); + if (it != DoIpEnumToStringActionCodes.end()) + { + os << "further action required:" << it->second << std::hex << " (0x" << unsigned(furtherActionRequired) + << ")" << "\n"; + } + else + { + os << "further action required: Unknown" << std::hex << " (0x" << unsigned(furtherActionRequired) << ")" + << "\n"; + } + + auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); + if (it_ != DoIpEnumToStringSyncStatus.end()) + { + os << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte + } + else + { + os << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(syncStatus) << ")" << "\n"; + } + return os.str(); } @@ -381,9 +445,9 @@ namespace pcpp } // Validate minimum data length - size_t expectedMinLength = + size_t fixedFieldLength = DOIP_VIN_LEN + sizeof(logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + 1; // 1 for furtherActionRequired - if (doipLayer->getDataLen() - sizeof(doiphdr) < expectedMinLength) + if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Announcement payload"); return false; @@ -410,10 +474,10 @@ namespace pcpp // Further Action Required furtherActionRequired = static_cast(*dataPtr); - dataPtr += 1; + dataPtr += sizeof(furtherActionRequired); // Optional Sync Status - if (doipLayer->getDataLen() - sizeof(doiphdr) > expectedMinLength) + if (doipLayer->getDataLen() - sizeof(doiphdr) > fixedFieldLength) { syncStatus = static_cast(*dataPtr); } @@ -441,9 +505,10 @@ namespace pcpp std::vector AliveCheckResponseData::getData() const { std::vector data; - // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); + + data.push_back(static_cast(sourceAddress & 0xFF)); + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + return data; } @@ -462,8 +527,8 @@ namespace pcpp } // Validate minimum data length - constexpr size_t requiredLength = sizeof(sourceAddress); - if (doipLayer->getDataLen() - sizeof(doiphdr) < requiredLength) + constexpr size_t fixedFieldLength = sizeof(sourceAddress); + if (doipLayer->getDataLen() - sizeof(doiphdr) != fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Alive Check Response payload"); return false; @@ -471,7 +536,7 @@ namespace pcpp // Parse sourceAddress from payload uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); - sourceAddress = *reinterpret_cast(dataPtr); + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); return true; } @@ -489,8 +554,16 @@ namespace pcpp std::string DiagnosticPowerModeResponseData::toString() const { std::stringstream os; - os << "diagnostic power mode: " << DoIpEnumToStringDiagnosticPowerModeCodes.at(powerModeCode) << std::hex - << " (0x" << unsigned(powerModeCode) << ")" << "\n"; + auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); + if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) + { + os << "diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(powerModeCode) << ")" + << "\n"; + } + else + { + os << "diagnostic power mode: Unknown" << std::hex << " (0x" << unsigned(powerModeCode) << ")" << "\n"; + } return os.str(); } @@ -518,8 +591,8 @@ namespace pcpp } // Validate minimum data length - constexpr size_t requiredLength = sizeof(powerModeCode); - if (doipLayer->getDataLen() - sizeof(doiphdr) < requiredLength) + constexpr size_t fixedFieldLength = sizeof(powerModeCode); + if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Diagnostic Power Mode Response payload"); return false; @@ -545,8 +618,15 @@ namespace pcpp std::string EntityStatusResponseData::toString() const { std::stringstream os; - os << "Entity status: " << DoIpEnumToStringEntityStatusNodeTypes.at(nodeType) << std::hex << " (0x" - << unsigned(nodeType) << ")" << "\n"; + auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); + if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) + { + os << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; + } + else + { + os << "Node Type: Unknown" << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; + } os << "maximum Concurrent Socket: " << unsigned(maxConcurrentSockets) << "\n"; os << "currently Opened Socket: " << unsigned(currentlyOpenSockets) << "\n"; if (maxDataSize) @@ -562,9 +642,10 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.push_back(static_cast(nodeType)); // Convert enum to byte + data.push_back(static_cast(nodeType)); data.push_back(static_cast(maxConcurrentSockets)); data.push_back(static_cast(currentlyOpenSockets)); + // optional field if (maxDataSize) { @@ -605,7 +686,7 @@ namespace pcpp currentlyOpenSockets = dataPtr[2]; // Parse optional maxDataSize field if present - if (totalDataLength >= fixedFieldLength + optionalFieldLength) + if (totalDataLength == (fixedFieldLength + optionalFieldLength)) { maxDataSize = std::unique_ptr>( new std::array()); @@ -639,11 +720,14 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); - data.insert(data.end(), reinterpret_cast(&targetAddress), - reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.push_back(static_cast(sourceAddress & 0xFF)); + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + + data.push_back(static_cast(targetAddress & 0xFF)); + data.push_back(static_cast((targetAddress >> 8) & 0xFF)); + data.insert(data.end(), diagnosticData.data(), diagnosticData.data() + diagnosticData.size()); + return data; } @@ -672,14 +756,17 @@ namespace pcpp // Parse fixed fields uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); - sourceAddress = *reinterpret_cast(dataPtr); - targetAddress = *reinterpret_cast(dataPtr + sizeof(sourceAddress)); + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + + dataPtr += sizeof(sourceAddress); + targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + + dataPtr += sizeof(targetAddress); // Parse diagnosticData field (remaining data after fixed fields) size_t diagnosticDataLength = totalDataLength - fixedFieldLength; diagnosticData.resize(diagnosticDataLength); - std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + diagnosticDataLength, - diagnosticData.begin()); + std::copy(dataPtr, dataPtr + diagnosticDataLength, diagnosticData.begin()); return true; } @@ -698,7 +785,15 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - os << "ack code: " << DoIpEnumToStringAckCode.at(ackCode) << " (0x" << unsigned(ackCode) << ")" << "\n"; + auto it = DoIpEnumToStringAckCode.find(ackCode); + if (it != DoIpEnumToStringAckCode.end()) + { + os << "ack code: " << it->second << " (0x" << unsigned(ackCode) << ")" << "\n"; + } + else + { + os << "Ack code: Unknown" << std::hex << " (0x" << unsigned(ackCode) << ")" << "\n"; + } if (!previousMessage.empty()) { os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) @@ -710,11 +805,14 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); - data.insert(data.end(), reinterpret_cast(&targetAddress), - reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.push_back(static_cast(sourceAddress & 0xFF)); // Low byte + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + + data.push_back(static_cast(targetAddress & 0xFF)); + data.push_back(static_cast((targetAddress >> 8) & 0xFF)); + data.push_back(static_cast(ackCode)); + if (!previousMessage.empty()) { data.insert(data.end(), previousMessage.begin(), previousMessage.end()); @@ -748,18 +846,21 @@ namespace pcpp // Parse fixed fields uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); - sourceAddress = (*reinterpret_cast(dataPtr)); - targetAddress = (*reinterpret_cast(dataPtr + sizeof(sourceAddress))); - ackCode = static_cast( - *reinterpret_cast(dataPtr + sizeof(sourceAddress) + sizeof(targetAddress))); + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + + dataPtr += sizeof(sourceAddress); + targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + dataPtr += sizeof(targetAddress); + ackCode = static_cast(dataPtr[0]); + + dataPtr += sizeof(ackCode); // Check if there is any data left for the optional previousMessage field size_t remainingDataLength = totalDataLength - fixedFieldLength; if (remainingDataLength > 0) { previousMessage.resize(remainingDataLength); - std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + remainingDataLength, - previousMessage.begin()); + std::copy(dataPtr, dataPtr + remainingDataLength, previousMessage.begin()); } else { @@ -782,8 +883,15 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - os << "nack code: " << DoIpEnumToStringDiagnosticNackCodes.at(nackCode) << std::hex << " (0x" - << unsigned(nackCode) << ")" << "\n"; + auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); + if (it != DoIpEnumToStringDiagnosticNackCodes.end()) + { + os << "nack code: " << it->second << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; + } + else + { + os << "nack code: Unknown" << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; + } if (!previousMessage.empty()) { os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) @@ -795,10 +903,12 @@ namespace pcpp { std::vector data; // Copy each field's data into the vector - data.insert(data.end(), reinterpret_cast(&sourceAddress), - reinterpret_cast(&sourceAddress) + sizeof(sourceAddress)); - data.insert(data.end(), reinterpret_cast(&targetAddress), - reinterpret_cast(&targetAddress) + sizeof(targetAddress)); + data.push_back(static_cast(sourceAddress & 0xFF)); + data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); + + data.push_back(static_cast(targetAddress & 0xFF)); + data.push_back(static_cast((targetAddress >> 8) & 0xFF)); + data.push_back(static_cast(nackCode)); if (!previousMessage.empty()) { @@ -833,18 +943,21 @@ namespace pcpp // Parse fixed fields uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); - sourceAddress = (*reinterpret_cast(dataPtr)); - targetAddress = (*reinterpret_cast(dataPtr + sizeof(sourceAddress))); - nackCode = static_cast( - *reinterpret_cast(dataPtr + sizeof(sourceAddress) + sizeof(targetAddress))); + sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + + dataPtr += sizeof(sourceAddress); + targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); + + dataPtr += sizeof(targetAddress); + nackCode = static_cast(dataPtr[0]); + dataPtr += sizeof(nackCode); // Check if there is any data left for the optional previousMessage field size_t remainingDataLength = totalDataLength - fixedFieldLength; if (remainingDataLength > 0) { previousMessage.resize(remainingDataLength); - std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + remainingDataLength, - previousMessage.begin()); + std::copy(dataPtr, dataPtr + remainingDataLength, previousMessage.begin()); } else { From 14c9842cd4e8d47020d5425504e2afa84d1cc94d Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 19 Jan 2025 00:57:59 -0500 Subject: [PATCH 11/43] remove buildFromLayer from IDoIpMessageData --- Packet++/header/DoIpLayer.h | 1 + Packet++/header/DoIpLayerData.h | 36 ++--- Packet++/src/DoIpLayer.cpp | 3 +- Packet++/src/DoIpLayerData.cpp | 207 ++++++++----------------- Tests/Packet++Test/Tests/DoIpTests.cpp | 72 ++++----- 5 files changed, 116 insertions(+), 203 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index cf3dd94782..ebcd43b470 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -35,6 +35,7 @@ namespace pcpp uint32_t payloadLength; }; #pragma pack(pop) + static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes."); /** * @class DoIpLayer diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 8c88d0ab04..0573700ccb 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -72,18 +72,6 @@ namespace pcpp * @return The message data as a vector of bytes. */ virtual std::vector getData() const = 0; - - /** - * @brief build IDoIpMessageData from DoIpLayer - * @param[in] doipLayer pointer to doipLayer to retrieve data from - * @return true if encapsulating process is done successufly else false. - * - * @exception Logs an error and returns `false` if: - * - The input layer is null. - * - The payload type of doipLayer does not match the expected type for IDoIpMessageData. - * - The input data length is insufficient for parsing all required fields. - */ - virtual bool buildFromLayer(DoIpLayer* doipLayer) = 0; }; /** @@ -150,7 +138,7 @@ namespace pcpp * - `reservedIso`: Reserved bytes as defined by ISO specifications. * - `reservedOem`: Reserved bytes as defined by OEM specifications, only if present. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -210,7 +198,7 @@ namespace pcpp * @param[in] doipLayer Pointer to the DoIpLayer containing the Routing Activation Response data. * @return `true` if parsing was successful, `false` otherwise. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -266,7 +254,7 @@ namespace pcpp * The following field is parsed: * - `genericNackCode`: The NACK code indicating the type of error. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -322,7 +310,7 @@ namespace pcpp * The following field is parsed: * - `eid`: The EID (Extended Identifier), extracted as a byte array of length `DOIP_EID_LEN`. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -383,7 +371,7 @@ namespace pcpp * The following field is parsed: * - `vin`: The Vehicle Identification Number (VIN), extracted as a byte array of length `DOIP_VIN_LEN`. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -459,7 +447,7 @@ namespace pcpp * - `furtherActionRequired`: Further action required code. * - `syncStatus`: VIN/GID synchronization status (if present). */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -519,7 +507,7 @@ namespace pcpp * The following field is parsed: * - `sourceAddress`: The source address of the response. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -579,7 +567,7 @@ namespace pcpp * The following field is parsed: * - `powerModeCode`: The diagnostic power mode response code. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -656,7 +644,7 @@ namespace pcpp * - `currentlyOpenSockets`: Number of currently open sockets. * - `maxDataSize` (optional): Maximum data size supported (4 bytes). */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -722,7 +710,7 @@ namespace pcpp * - `targetAddress`: Target address of the diagnostic message (2 bytes). * - `diagnosticData`: Variable length data representing the diagnostic payload. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -792,7 +780,7 @@ namespace pcpp * - `ackCode`: Acknowledgment code (1 byte, converted from enum). * - `previousMessage`: std::vector representing the previous message. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; /** @@ -852,6 +840,6 @@ namespace pcpp * @param doipLayer The layer containing the message data to be parsed. * @return `true` if the message was successfully built from the layer, `false` otherwise. */ - bool buildFromLayer(DoIpLayer* doipLayer) override; + bool buildFromLayer(const DoIpLayer& doipLayer); }; } // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 64053be002..b4a0df722b 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -213,8 +213,7 @@ namespace pcpp void DoIpLayer::parseNextLayer() { DiagnosticMessageData diagnosticMessage; - - if (diagnosticMessage.buildFromLayer(this)) + if (diagnosticMessage.buildFromLayer(*this)) { // handle UDS layer as generic PayloadLayer for now. m_NextLayer = new PayloadLayer(diagnosticMessage.diagnosticData.data(), diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 6e9e33aeee..3432add231 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -53,29 +53,23 @@ namespace pcpp } // buildFromLayer implementation - bool RoutingActivationRequestData::buildFromLayer(DoIpLayer* doipLayer) + bool RoutingActivationRequestData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Input data buffer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve routing activation request data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve routing activation request data from " + doipLayer.getPayloadTypeAsStr()); return false; } constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(activationType) + DOIP_RESERVED_ISO_LEN; - if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) + if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for routing activation request payload"); return false; } - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); dataPtr += sizeof(sourceAddress); @@ -85,7 +79,7 @@ namespace pcpp std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); dataPtr += DOIP_RESERVED_ISO_LEN; - if (doipLayer->getDataLen() - (sizeof(doiphdr) + fixedFieldLength) == DOIP_RESERVED_OEM_LEN) + if (doipLayer.getDataLen() - (sizeof(doiphdr) + fixedFieldLength) == DOIP_RESERVED_OEM_LEN) { reservedOem = std::unique_ptr>( new std::array()); @@ -153,28 +147,22 @@ namespace pcpp return data; } - bool RoutingActivationResponseData::buildFromLayer(DoIpLayer* doipLayer) + bool RoutingActivationResponseData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input data buffer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Cannot retrieve routing activation response data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve routing activation response data from " + doipLayer.getPayloadTypeAsStr()); return false; } - if (doipLayer->getDataLen() - sizeof(doiphdr) < + if (doipLayer.getDataLen() - sizeof(doiphdr) < sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) { PCPP_LOG_ERROR("Insufficient data length for routing activation response payload"); return false; } - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); logicalAddressExternalTester = static_cast(dataPtr[1] << 8 | dataPtr[0]); dataPtr += sizeof(logicalAddressExternalTester); @@ -187,8 +175,8 @@ namespace pcpp std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); dataPtr += DOIP_RESERVED_ISO_LEN; - if (doipLayer->getDataLen() - (sizeof(doiphdr) + sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + - sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) == + if (doipLayer.getDataLen() - (sizeof(doiphdr) + sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + + sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) == DOIP_RESERVED_OEM_LEN) { reservedOem = std::unique_ptr>( @@ -237,29 +225,23 @@ namespace pcpp } // buildFromLayer fun implementation - bool GenericHeaderNackData::buildFromLayer(DoIpLayer* doipLayer) + bool GenericHeaderNackData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Generic Header NACK data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Generic Header NACK data from " + doipLayer.getPayloadTypeAsStr()); return false; } // Validate data length (1 byte is expected for genericNackCode) - if (doipLayer->getDataLen() - sizeof(doiphdr) < 1) + if (doipLayer.getDataLen() - sizeof(doiphdr) < 1) { PCPP_LOG_ERROR("Insufficient data length for Generic Header NACK payload"); return false; } // Extract the NACK code (1 byte) - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); genericNackCode = static_cast(dataPtr[0]); return true; @@ -280,36 +262,28 @@ namespace pcpp } std::vector VehicleIdentificationRequestEIDData::getData() const { - std::vector data; // Copy each field's data into the vector - data.insert(data.end(), eid.begin(), eid.end()); - return data; + return std::vector(eid.begin(), eid.end()); } - bool VehicleIdentificationRequestEIDData::buildFromLayer(DoIpLayer* doipLayer) + bool VehicleIdentificationRequestEIDData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with EID data from " + - doipLayer->getPayloadTypeAsStr()); + doipLayer.getPayloadTypeAsStr()); return false; } // Validate data length (must at least accommodate EID length) - if (doipLayer->getDataLen() - sizeof(doiphdr) != DOIP_EID_LEN) + if (doipLayer.getDataLen() - sizeof(doiphdr) != DOIP_EID_LEN) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); return false; } // Extract the EID - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); std::copy(dataPtr, dataPtr + DOIP_EID_LEN, eid.begin()); return true; @@ -330,36 +304,28 @@ namespace pcpp } std::vector VehicleIdentificationRequestVINData::getData() const { - std::vector data; // Copy each field's data into the vector - data.insert(data.end(), vin.begin(), vin.end()); - return data; + return std::vector(vin.begin(), vin.end()); } - bool VehicleIdentificationRequestVINData::buildFromLayer(DoIpLayer* doipLayer) + bool VehicleIdentificationRequestVINData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with VIN data from " + - doipLayer->getPayloadTypeAsStr()); + doipLayer.getPayloadTypeAsStr()); return false; } // Validate data length (must at least accommodate VIN length) - if (doipLayer->getDataLen() - sizeof(doiphdr) != DOIP_VIN_LEN) + if (doipLayer.getDataLen() - sizeof(doiphdr) != DOIP_VIN_LEN) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); return false; } // Extract the VIN - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); return true; @@ -430,31 +396,25 @@ namespace pcpp return data; } - bool VehicleAnnouncementData::buildFromLayer(DoIpLayer* doipLayer) + bool VehicleAnnouncementData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Vehicle Announcement data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Vehicle Announcement data from " + doipLayer.getPayloadTypeAsStr()); return false; } // Validate minimum data length size_t fixedFieldLength = DOIP_VIN_LEN + sizeof(logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + 1; // 1 for furtherActionRequired - if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) + if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Vehicle Announcement payload"); return false; } // Parse fields from payload - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); // VIN std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); @@ -477,7 +437,7 @@ namespace pcpp dataPtr += sizeof(furtherActionRequired); // Optional Sync Status - if (doipLayer->getDataLen() - sizeof(doiphdr) > fixedFieldLength) + if (doipLayer.getDataLen() - sizeof(doiphdr) > fixedFieldLength) { syncStatus = static_cast(*dataPtr); } @@ -512,30 +472,24 @@ namespace pcpp return data; } - bool AliveCheckResponseData::buildFromLayer(DoIpLayer* doipLayer) + bool AliveCheckResponseData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Cannot retrieve Alive Check Response data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Alive Check Response data from " + doipLayer.getPayloadTypeAsStr()); return false; } // Validate minimum data length constexpr size_t fixedFieldLength = sizeof(sourceAddress); - if (doipLayer->getDataLen() - sizeof(doiphdr) != fixedFieldLength) + if (doipLayer.getDataLen() - sizeof(doiphdr) != fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Alive Check Response payload"); return false; } // Parse sourceAddress from payload - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); return true; @@ -575,31 +529,25 @@ namespace pcpp return data; } - bool DiagnosticPowerModeResponseData::buildFromLayer(DoIpLayer* doipLayer) + bool DiagnosticPowerModeResponseData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { PCPP_LOG_ERROR("Cannot retrieve Diagnostic Power Mode Response data from " + - doipLayer->getPayloadTypeAsStr()); + doipLayer.getPayloadTypeAsStr()); return false; } // Validate minimum data length constexpr size_t fixedFieldLength = sizeof(powerModeCode); - if (doipLayer->getDataLen() - sizeof(doiphdr) < fixedFieldLength) + if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) { PCPP_LOG_ERROR("Insufficient data length for Diagnostic Power Mode Response payload"); return false; } // Parse powerModeCode from payload - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); powerModeCode = static_cast(dataPtr[0]); return true; @@ -654,24 +602,18 @@ namespace pcpp return data; } - bool EntityStatusResponseData::buildFromLayer(DoIpLayer* doipLayer) + bool EntityStatusResponseData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Cannot retrieve Entity Status Response data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Entity Status Response data from " + doipLayer.getPayloadTypeAsStr()); return false; } constexpr size_t fixedFieldLength = sizeof(nodeType) + sizeof(maxConcurrentSockets) + sizeof(currentlyOpenSockets); constexpr size_t optionalFieldLength = 4; // Length of maxDataSize field - size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); if (totalDataLength < fixedFieldLength) { @@ -680,7 +622,7 @@ namespace pcpp } // Parse fixed fields - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); nodeType = static_cast(dataPtr[0]); maxConcurrentSockets = dataPtr[1]; currentlyOpenSockets = dataPtr[2]; @@ -731,22 +673,16 @@ namespace pcpp return data; } - bool DiagnosticMessageData::buildFromLayer(DoIpLayer* doipLayer) + bool DiagnosticMessageData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic Message data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Diagnostic Message data from " + doipLayer.getPayloadTypeAsStr()); return false; } constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + 2; // SI + DID - size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); if (totalDataLength < fixedFieldLength) { @@ -755,7 +691,7 @@ namespace pcpp } // Parse fixed fields - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); dataPtr += sizeof(sourceAddress); @@ -820,23 +756,17 @@ namespace pcpp return data; } - bool DiagnosticAckMessageData::buildFromLayer(DoIpLayer* doipLayer) + bool DiagnosticAckMessageData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { PCPP_LOG_ERROR("Cannot retrieve Diagnostic Acknowledgment Message data from " + - doipLayer->getPayloadTypeAsStr()); + doipLayer.getPayloadTypeAsStr()); return false; } constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(ackCode); - size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); if (totalDataLength < fixedFieldLength) { @@ -845,7 +775,7 @@ namespace pcpp } // Parse fixed fields - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); dataPtr += sizeof(sourceAddress); @@ -918,22 +848,17 @@ namespace pcpp return data; } - bool DiagnosticNackMessageData::buildFromLayer(DoIpLayer* doipLayer) + bool DiagnosticNackMessageData::buildFromLayer(const DoIpLayer& doipLayer) { - if (!doipLayer) - { - PCPP_LOG_ERROR("Input DoIpLayer is null"); - return false; - } - if (doipLayer->getPayloadType() != getType()) + if (doipLayer.getPayloadType() != getType()) { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic NACK Message data from " + doipLayer->getPayloadTypeAsStr()); + PCPP_LOG_ERROR("Cannot retrieve Diagnostic NACK Message data from " + doipLayer.getPayloadTypeAsStr()); return false; } constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(nackCode); - size_t totalDataLength = doipLayer->getDataLen() - sizeof(doiphdr); + size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); if (totalDataLength < fixedFieldLength) { @@ -942,7 +867,7 @@ namespace pcpp } // Parse fixed fields - uint8_t* dataPtr = doipLayer->getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); dataPtr += sizeof(sourceAddress); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 22d7bff69c..f1a61d78c4 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -39,13 +39,13 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) // build doipData from existent layer pcpp::GenericHeaderNackData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "generic header nack code: Unknown payload type (0x1)\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -197,13 +197,13 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) // build doipData from existent layer pcpp::VehicleIdentificationRequestVINData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "VIN: BAUNEE4MZ17042403\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -287,13 +287,13 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) // build doipData from existent layer pcpp::VehicleIdentificationRequestEIDData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "EID: 4241554e4545\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -379,15 +379,15 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) // build doipData from existent layer pcpp::VehicleAnnouncementData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "VIN: BAUNEE4MZ17042403\nlogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nfurther action required:No further action required (0x0)\nVIN/GID sync status: NULL\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -481,16 +481,16 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) // build doipData from existent layer pcpp::RoutingActivationRequestData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "sourceAddress: 0xe80\nactivation type: Default (0x0)\nreserved by ISO: 00000000\nReserved by OEM: 00000000\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationResponseData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -573,15 +573,15 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::RoutingActivationResponseData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "logical address of external tester: 0xe80\nsource address: 0x4010\nrouting activation response code: Routing successfully activated (0x10)\nreserved by ISO: 00000000\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -739,13 +739,13 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) // build doipData from existent layer pcpp::AliveCheckResponseData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "source address: 0x0\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -893,15 +893,15 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::EntityStatusResponseData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "Entity status: DoIP gateway (0x0)\nmaximum Concurrent Socket: 1\ncurrently Opened Socket: 0\nmaximum Data Size: 0x00000fff\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1053,13 +1053,13 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::DiagnosticPowerModeResponseData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "diagnostic power mode: not ready (0x0)\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1136,13 +1136,13 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::DiagnosticMessageData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "source address: 0xe80\ntarget address: 0x4010\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1223,15 +1223,15 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::DiagnosticAckMessageData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\nprevious message: 22f101\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1314,15 +1314,15 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); pcpp::DiagnosticNackMessageData data; - if (data.buildFromLayer(doipLayer)) + if (data.buildFromLayer(*doipLayer)) // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "source address: 0x4010\ntarget address: 0xe80\nnack code: Invalid source address (0x2)\nprevious message: 22f101\n"); // wrong build - PTF_ASSERT_FALSE(data.buildFromLayer(nullptr)); + pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(doipLayer)); + PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); From c4b8baaa5b4f270d3d18e07e16ce5812e41cb218 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 19 Jan 2025 01:23:47 -0500 Subject: [PATCH 12/43] fix dioxygene pipeline --- Packet++/header/DoIpLayer.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index ebcd43b470..e9f591c46c 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -58,7 +58,9 @@ namespace pcpp /** * A constructor that creates an generic doip layer and set header and payload fields - * @param[in] Fields DoIpMessageFields contains all doipMessage specification based on its payload type + * @param[in] version DoIpProtocolVersion specify the doip protocol version + * @param[in] type DoIpPayloadTypes indicating the doip payload type + * @param[in] data IDoIpMessageData contains all doipMessage specification based on its payload type */ DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); From 326ae50971687ae0f6889380aeed317a98b24175 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 19 Jan 2025 02:03:28 -0500 Subject: [PATCH 13/43] change doc from pointer to const ref --- Packet++/header/DoIpLayerData.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 0573700ccb..91ad475e61 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -126,7 +126,7 @@ namespace pcpp * Routing Activation Request payload type. It extracts the source address, activation * type, reserved ISO bytes, and optionally reserved OEM bytes if present. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Routing Activation Request data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Request data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note This method overrides the base class implementation and adds specific parsing @@ -195,7 +195,7 @@ namespace pcpp * payload type and parses fields including the logical tester address, source * address, response code, and reserved fields. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Routing Activation Response data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Response data. * @return `true` if parsing was successful, `false` otherwise. */ bool buildFromLayer(const DoIpLayer& doipLayer); @@ -245,7 +245,7 @@ namespace pcpp * This method validates the provided DoIpLayer to ensure it corresponds to the * Generic Header NACK payload type. It extracts the `genericNackCode` field from the layer. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Generic Header NACK data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Generic Header NACK data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method checks for null pointers and verifies that the payload type matches @@ -301,7 +301,8 @@ namespace pcpp * This method validates the provided DoIpLayer to ensure it corresponds to the * Vehicle Identification Request with EID payload type. It extracts the EID field from the layer. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Identification Request with EID data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with EID + * data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method checks for null pointers and verifies that the payload type matches @@ -358,7 +359,8 @@ namespace pcpp * Vehicle Identification Request with VIN payload type. It extracts the VIN (Vehicle Identification Number) * field from the payload data and populates the class instance. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Identification Request with VIN data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with VIN + * data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -429,7 +431,7 @@ namespace pcpp * Announcement Message payload type. It extracts fields such as VIN, logical address, EID, GID, * further action required, and synchronization status from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Vehicle Announcement data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Announcement data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -494,7 +496,7 @@ namespace pcpp * This method validates the provided DoIpLayer to ensure it corresponds to the * Alive Check Response payload type. It extracts the `sourceAddress` field from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Alive Check Response data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Alive Check Response data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -554,7 +556,7 @@ namespace pcpp * This method validates the provided DoIpLayer to ensure it corresponds to the * Diagnostic Power Mode Response payload type. It extracts the `powerModeCode` field from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Power Mode Response data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Power Mode Response data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -628,7 +630,7 @@ namespace pcpp * Entity Status Response payload type. It extracts fields such as `nodeType`, * `maxConcurrentSockets`, `currentlyOpenSockets`, and optionally `maxDataSize` from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Entity Status Response data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Entity Status Response data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -695,7 +697,7 @@ namespace pcpp * Diagnostic Message payload type. It extracts fields such as `sourceAddress`, * `targetAddress`, and `diagnosticData` from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Message data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Message data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: @@ -764,7 +766,7 @@ namespace pcpp * Diagnostic Acknowledgment Message payload type. It extracts fields such as `sourceAddress`, * `targetAddress`, `ackCode`, and `previousMessage` from the payload data. * - * @param[in] doipLayer Pointer to the DoIpLayer containing the Diagnostic Acknowledgment Message data. + * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Acknowledgment Message data. * @return `true` if parsing and initialization were successful, `false` otherwise. * * @note The method performs the following checks: From 9d97fceeb43ed30607a1da593fdf456ed838cce6 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 19 Jan 2025 02:42:34 -0500 Subject: [PATCH 14/43] try fix dioxygene --- Packet++/header/DoIpLayer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index e9f591c46c..3fdc831243 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -164,7 +164,7 @@ namespace pcpp /** * copy data from msgFields to dest * @param[in] dest pointer to where start copying - * @param[in] msgFields the doip Fields to copy + * @param[in] data the doip Fields to copy */ void serializeData(uint8_t* dest, std::vector data); From 031b36c4375217415c6556746d6e01daf7cc33d2 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 21 Jan 2025 23:44:00 -0500 Subject: [PATCH 15/43] try resolve doxygene --- Packet++/header/DoIpLayer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 3fdc831243..3a3238d07e 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -127,7 +127,7 @@ namespace pcpp /** * Set the invert protocol version of DOIP protocol - * @param[in] version the invert version of DOIP protocol to set + * @param[in] iVersion the invert version of DOIP protocol to set */ void setInvertProtocolVersion(uint8_t iVersion); From 929287b92f810e5ed2ef2b7f4813b3fcec98a2b9 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 23 Jan 2025 02:17:26 -0500 Subject: [PATCH 16/43] move maps to internal namespace --- Packet++/header/DoIpEnumToString.h | 410 +++++++++++++++-------------- Packet++/src/DoIpLayer.cpp | 8 +- Packet++/src/DoIpLayerData.cpp | 36 +-- 3 files changed, 230 insertions(+), 224 deletions(-) diff --git a/Packet++/header/DoIpEnumToString.h b/Packet++/header/DoIpEnumToString.h index 5f0965e6c3..e8b79053b9 100644 --- a/Packet++/header/DoIpEnumToString.h +++ b/Packet++/header/DoIpEnumToString.h @@ -11,216 +11,222 @@ */ namespace pcpp { - /** - * @brief Mapping of DoIP Protocol Versions to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each version of the - * DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values - * to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringProtocolVersion{ - { DoIpProtocolVersion::defaultVersion, "Default value for vehicle identification request messages" }, - { DoIpProtocolVersion::version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, - { DoIpProtocolVersion::version02Iso2012, "DoIP ISO 13400-2:2012" }, - { DoIpProtocolVersion::version03Iso2019, "DoIP ISO 13400-2:2019" }, - { DoIpProtocolVersion::version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, - { DoIpProtocolVersion::reservedVersion, "Reserved" }, - }; + namespace internal + { + /** + * @brief Mapping of DoIP Protocol Versions to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each version of the + * DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values + * to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringProtocolVersion{ + { DoIpProtocolVersion::defaultVersion, "Default value for vehicle identification request messages" }, + { DoIpProtocolVersion::version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, + { DoIpProtocolVersion::version02Iso2012, "DoIP ISO 13400-2:2012" }, + { DoIpProtocolVersion::version03Iso2019, "DoIP ISO 13400-2:2019" }, + { DoIpProtocolVersion::version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, + { DoIpProtocolVersion::reservedVersion, "Reserved" }, + }; - /** - * @brief Mapping of DoIP Payload Types to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each payload type - * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values - * to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringPayloadType{ - { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, - { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, - "Vehicle announcement message / vehicle identification response message" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, - { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, - { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, - { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, - { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } - }; + /** + * @brief Mapping of DoIP Payload Types to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each payload type + * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values + * to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringPayloadType{ + { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, + { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, + "Vehicle announcement message / vehicle identification response message" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, + { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, + { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, + { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, + { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } + }; - /** - * @brief Mapping of DoIP Activation Types to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each activation type - * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values - * to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringActivationTypes{ - { DoIpActivationTypes::Default, "Default" }, - { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, - { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, - }; + /** + * @brief Mapping of DoIP Activation Types to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each activation type + * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values + * to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringActivationTypes{ + { DoIpActivationTypes::Default, "Default" }, + { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, + { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, + }; - /** - * @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each Nack code related to - * the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum - * values to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ - { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, - { DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, - { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, - { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, - { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, - }; + /** + * @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each Nack code related to + * the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum + * values to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ + { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, + { DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, + { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, + { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, + { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, + }; - /** - * @brief Mapping of DoIP Action Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each action code related to - * the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum - * values to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringActionCodes{ - { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, - { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } - }; + /** + * @brief Mapping of DoIP Action Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each action code related to + * the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum + * values to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringActionCodes{ + { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, + { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } + }; - /** - * @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each routing response code - * related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` enum - * values to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ - { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, "Routing activation denied due to unknown source address" }, - { DoIpRoutingResponseCodes::NO_FREE_SOCKET, - "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, - { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, - "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, - { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, - "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, - { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, "Routing activation denied due to missing authentication" }, - { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, "Routing activation denied due to rejected confirmation" }, - { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, - "Routing activation denied due to unsupported routing activation type" }, - { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, - "Routing activation denied due to request for encrypted connection via TLS" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, - { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } - }; + /** + * @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each routing response code + * related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` enum + * values to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ + { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, + "Routing activation denied due to unknown source address" }, + { DoIpRoutingResponseCodes::NO_FREE_SOCKET, + "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, + { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, + "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, + { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, + "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, + { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, + "Routing activation denied due to missing authentication" }, + { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, + "Routing activation denied due to rejected confirmation" }, + { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, + "Routing activation denied due to unsupported routing activation type" }, + { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, + "Routing activation denied due to request for encrypted connection via TLS" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, + { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } + }; - /** - * @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code - * related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum - * values to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, - { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, - { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, - { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, - { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, - { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, - { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, - }; + /** + * @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code + * related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum + * values to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, + { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, + { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, + { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, + { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, + { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, + { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, + }; - /** - * @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each power mode code - * related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum - * values to their corresponding descriptions. - */ - static const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ - { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, - { DoIpDiagnosticPowerModeCodes::READY, "ready" }, - { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, - }; + /** + * @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for each power mode code + * related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum + * values to their corresponding descriptions. + */ + const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ + { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, + { DoIpDiagnosticPowerModeCodes::READY, "ready" }, + { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, + }; - /** - * @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for the entity status codes - * in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values - * to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." - */ - static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatus::NODE, "DoIp node" }, - { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, - }; + /** + * @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. + * + * This unordered map provides human-readable descriptions for the entity status codes + * in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values + * to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." + */ + const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatus::NODE, "DoIp node" }, + { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, + }; - /** - * @brief Mapping of DoIP Acknowledgement Codes to their string representations. - * - * This unordered map provides a human-readable description for the DoIP acknowledgement - * code `ACK`, which is used to confirm the successful reception or processing of a message. - */ - static const std::unordered_map DoIpEnumToStringAckCode{ - { DoIpDiagnosticAckCodes::ACK, "ACK" }, - }; + /** + * @brief Mapping of DoIP Acknowledgement Codes to their string representations. + * + * This unordered map provides a human-readable description for the DoIP acknowledgement + * code `ACK`, which is used to confirm the successful reception or processing of a message. + */ + const std::unordered_map DoIpEnumToStringAckCode{ + { DoIpDiagnosticAckCodes::ACK, "ACK" }, + }; - /** - * @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. - * - * This unordered map provides a human-readable string for each synchronization status - * defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status - * values to their respective descriptions for logging or display purposes. - */ - static const std::unordered_map DoIpEnumToStringSyncStatus{ - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, - { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, - { DoIpSyncStatus::NON_INITIALIZED, "NULL" } - }; + /** + * @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. + * + * This unordered map provides a human-readable string for each synchronization status + * defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status + * values to their respective descriptions for logging or display purposes. + */ + const std::unordered_map DoIpEnumToStringSyncStatus{ + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, + { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, + { DoIpSyncStatus::NON_INITIALIZED, "NULL" } + }; + } // namespace internal } // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index b4a0df722b..9a74d77b9f 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -33,8 +33,8 @@ namespace pcpp std::string DoIpLayer::getProtocolVersionAsStr() const { - auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); - if (it != DoIpEnumToStringProtocolVersion.end()) + auto it = internal::DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); + if (it != internal::DoIpEnumToStringProtocolVersion.end()) { return it->second; } @@ -71,8 +71,8 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { - auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); - if (it != DoIpEnumToStringPayloadType.end()) + auto it = internal::DoIpEnumToStringPayloadType.find(getPayloadType()); + if (it != internal::DoIpEnumToStringPayloadType.end()) { return it->second; } diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 3432add231..2262489388 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -20,8 +20,8 @@ namespace pcpp { std::stringstream os; os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = DoIpEnumToStringActivationTypes.find(activationType); - if (it != DoIpEnumToStringActivationTypes.end()) + auto it = internal::DoIpEnumToStringActivationTypes.find(activationType); + if (it != internal::DoIpEnumToStringActivationTypes.end()) { os << "activation type: " << it->second << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; } @@ -110,8 +110,8 @@ namespace pcpp os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) << "\n"; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = DoIpEnumToStringRoutingResponseCodes.find(responseCode); - if (it != DoIpEnumToStringRoutingResponseCodes.end()) + auto it = internal::DoIpEnumToStringRoutingResponseCodes.find(responseCode); + if (it != internal::DoIpEnumToStringRoutingResponseCodes.end()) { os << "routing activation response code: " << it->second << std::hex << " (0x" << unsigned(responseCode) << ")" << "\n"; @@ -204,8 +204,8 @@ namespace pcpp std::string GenericHeaderNackData::toString() const { std::stringstream os; - auto it = DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); - if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) + auto it = internal::DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); + if (it != internal::DoIpEnumToStringGenericHeaderNackCodes.end()) { os << "generic header nack code: " << it->second << std::hex << " (0x" << unsigned(genericNackCode) << ")" << "\n"; @@ -353,8 +353,8 @@ namespace pcpp os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << "\n"; os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << "\n"; - auto it = DoIpEnumToStringActionCodes.find(furtherActionRequired); - if (it != DoIpEnumToStringActionCodes.end()) + auto it = internal::DoIpEnumToStringActionCodes.find(furtherActionRequired); + if (it != internal::DoIpEnumToStringActionCodes.end()) { os << "further action required:" << it->second << std::hex << " (0x" << unsigned(furtherActionRequired) << ")" << "\n"; @@ -365,8 +365,8 @@ namespace pcpp << "\n"; } - auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); - if (it_ != DoIpEnumToStringSyncStatus.end()) + auto it_ = internal::DoIpEnumToStringSyncStatus.find(syncStatus); + if (it_ != internal::DoIpEnumToStringSyncStatus.end()) { os << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte } @@ -508,8 +508,8 @@ namespace pcpp std::string DiagnosticPowerModeResponseData::toString() const { std::stringstream os; - auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); - if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) + auto it = internal::DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); + if (it != internal::DoIpEnumToStringDiagnosticPowerModeCodes.end()) { os << "diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(powerModeCode) << ")" << "\n"; @@ -566,8 +566,8 @@ namespace pcpp std::string EntityStatusResponseData::toString() const { std::stringstream os; - auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); - if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) + auto it = internal::DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); + if (it != internal::DoIpEnumToStringEntityStatusNodeTypes.end()) { os << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; } @@ -721,8 +721,8 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = DoIpEnumToStringAckCode.find(ackCode); - if (it != DoIpEnumToStringAckCode.end()) + auto it = internal::DoIpEnumToStringAckCode.find(ackCode); + if (it != internal::DoIpEnumToStringAckCode.end()) { os << "ack code: " << it->second << " (0x" << unsigned(ackCode) << ")" << "\n"; } @@ -813,8 +813,8 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); - if (it != DoIpEnumToStringDiagnosticNackCodes.end()) + auto it = internal::DoIpEnumToStringDiagnosticNackCodes.find(nackCode); + if (it != internal::DoIpEnumToStringDiagnosticNackCodes.end()) { os << "nack code: " << it->second << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; } From 5b18d910f2a896f43aa1b171c097667950469368 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 4 Feb 2025 02:11:36 -0500 Subject: [PATCH 17/43] fix log errors --- Common++/header/Logger.h | 1 + Packet++/src/DoIpLayer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Common++/header/Logger.h b/Common++/header/Logger.h index df9ce372ee..1958a5faa5 100644 --- a/Common++/header/Logger.h +++ b/Common++/header/Logger.h @@ -99,6 +99,7 @@ namespace pcpp PacketLogModuleWakeOnLanLayer, ///< WakeOnLanLayer module (Packet++) PacketLogModuleSmtpLayer, ///< SmtpLayer module (Packet++) PacketLogModuleWireGuardLayer, ///< WireGuardLayer module (Packet++) + PacketLogModuleDoIpLayer, ///< DoipLayer module (Packet++) PcapLogModuleWinPcapLiveDevice, ///< WinPcapLiveDevice module (Pcap++) PcapLogModuleRemoteDevice, ///< WinPcapRemoteDevice module (Pcap++) PcapLogModuleLiveDevice, ///< PcapLiveDevice module (Pcap++) diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 9a74d77b9f..ded3f0ab1b 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -1,11 +1,11 @@ -#define LOG_MODULE PacketLogModuleDoipLayer +#define LOG_MODULE PacketLogModuleDoIpLayer #include "DoIpLayer.h" #include "Packet.h" #include "PayloadLayer.h" #include "EndianPortable.h" -#include #include +#include #include namespace pcpp From f2054838b4c3bc9c49663f153bc7271ee51d00fb Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 4 Feb 2025 03:33:10 -0500 Subject: [PATCH 18/43] revert suppress checks --- 3rdParty/json/include/json.hpp | 4 +++- Packet++/header/ProtocolType.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/3rdParty/json/include/json.hpp b/3rdParty/json/include/json.hpp index f7859fdc29..8b72ea6539 100644 --- a/3rdParty/json/include/json.hpp +++ b/3rdParty/json/include/json.hpp @@ -3406,7 +3406,7 @@ NLOHMANN_JSON_NAMESPACE_END template class AllocatorType = std::allocator, template class JSONSerializer = adl_serializer, - class BinaryType = std::vector, + class BinaryType = std::vector, // cppcheck-suppress syntaxError class CustomBaseClass = void> class basic_json; @@ -4251,6 +4251,7 @@ inline std::size_t concat_length(const char /*c*/, const Args& ... rest) template inline std::size_t concat_length(const char* cstr, const Args& ... rest) { + // cppcheck-suppress ignoredReturnValue return ::strlen(cstr) + concat_length(rest...); } @@ -19990,6 +19991,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #if JSON_DIAGNOSTICS JSON_TRY { + // cppcheck-suppress assertWithSideEffect JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) { return j.m_parent == this; diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index f899b119ac..da7cd93dd1 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -217,7 +217,7 @@ namespace pcpp /// GTPv2 protocol const ProtocolType GTPv2 = 57; - /// Diagnostic over IP protocol (DOIP) + /// Diagnostic over IP protocol (DOIP) const ProtocolType DOIP = 58; /// An enum representing OSI model layers From 5725fbb44c77b319097c695e447d119a8bf8a95b Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 4 Feb 2025 03:37:53 -0500 Subject: [PATCH 19/43] revert cpp checks --- Pcap++/src/PcapRemoteDeviceList.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Pcap++/src/PcapRemoteDeviceList.cpp b/Pcap++/src/PcapRemoteDeviceList.cpp index 913e27eb0b..ca8629c8f3 100644 --- a/Pcap++/src/PcapRemoteDeviceList.cpp +++ b/Pcap++/src/PcapRemoteDeviceList.cpp @@ -108,6 +108,7 @@ namespace pcpp auto pNewRemoteDevice = std::unique_ptr( new PcapRemoteDevice(currInterface, pRemoteAuthCopy, ipAddress, port)); // Release is called after pushback to prevent memory leaks if vector reallocation fails. + // cppcheck-suppress danglingLifetime devices.push_back(pNewRemoteDevice.get()); pNewRemoteDevice.release(); } From 4986248da82611aea0ce42408c278bc3b2b93a1c Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 20 Mar 2025 21:50:48 -0400 Subject: [PATCH 20/43] . Change comment style from /** */ to /// . remove DoIpEnums.h file and move all enums classes to DoIpLayer.h . remove DoIpEnumsToString.h file and move all maps to DoIpLayerData.cpp . typo errors fixing. . Changing access specifier for void initLayer(), doiphdr* getDoIpHeader() const, bool isPayloadLengthValid() const; and bool isProtocolVersionValid() const; . DoIpLayer destructor fixing and funct naming improvement . Improve logic on isProtocolVersionValid() --- Packet++/CMakeLists.txt | 2 - Packet++/header/DoIpEnumToString.h | 232 ---- Packet++/header/DoIpEnums.h | 711 ----------- Packet++/header/DoIpLayer.h | 746 ++++++++--- Packet++/header/DoIpLayerData.h | 1100 +++++++---------- Packet++/src/DoIpLayer.cpp | 63 +- Packet++/src/DoIpLayerData.cpp | 241 +++- ...tificationRequestWithDefaultVersPacket.dat | 1 + Tests/Packet++Test/TestDefinition.h | 1 + Tests/Packet++Test/Tests/DoIpTests.cpp | 138 ++- Tests/Packet++Test/main.cpp | 1 + 11 files changed, 1394 insertions(+), 1842 deletions(-) delete mode 100644 Packet++/header/DoIpEnumToString.h delete mode 100644 Packet++/header/DoIpEnums.h create mode 100644 Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWithDefaultVersPacket.dat diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index c5266cbb1c..ee42654182 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -82,8 +82,6 @@ set( header/DnsLayer.h header/DnsResourceData.h header/DnsResource.h - header/DoIpEnums.h - header/DoIpEnumToString.h header/DoIpLayer.h header/DoIpLayerData.h header/EthDot3Layer.h diff --git a/Packet++/header/DoIpEnumToString.h b/Packet++/header/DoIpEnumToString.h deleted file mode 100644 index e8b79053b9..0000000000 --- a/Packet++/header/DoIpEnumToString.h +++ /dev/null @@ -1,232 +0,0 @@ -#pragma once - -#include -#include "DoIpEnums.h" - -/// @file - -/** - * @namespace pcpp - * @brief The main namespace for the PcapPlusPlus lib - */ -namespace pcpp -{ - namespace internal - { - /** - * @brief Mapping of DoIP Protocol Versions to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each version of the - * DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values - * to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringProtocolVersion{ - { DoIpProtocolVersion::defaultVersion, "Default value for vehicle identification request messages" }, - { DoIpProtocolVersion::version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, - { DoIpProtocolVersion::version02Iso2012, "DoIP ISO 13400-2:2012" }, - { DoIpProtocolVersion::version03Iso2019, "DoIP ISO 13400-2:2019" }, - { DoIpProtocolVersion::version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, - { DoIpProtocolVersion::reservedVersion, "Reserved" }, - }; - - /** - * @brief Mapping of DoIP Payload Types to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each payload type - * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values - * to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringPayloadType{ - { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, - { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, - "Vehicle announcement message / vehicle identification response message" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, - { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, - { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, - { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, - { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } - }; - - /** - * @brief Mapping of DoIP Activation Types to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each activation type - * defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values - * to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringActivationTypes{ - { DoIpActivationTypes::Default, "Default" }, - { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, - { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, - }; - - /** - * @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each Nack code related to - * the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum - * values to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ - { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, - { DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, - { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, - { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, - { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, - }; - - /** - * @brief Mapping of DoIP Action Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each action code related to - * the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum - * values to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringActionCodes{ - { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, - { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } - }; - - /** - * @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each routing response code - * related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` enum - * values to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ - { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, - "Routing activation denied due to unknown source address" }, - { DoIpRoutingResponseCodes::NO_FREE_SOCKET, - "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, - { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, - "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, - { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, - "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, - { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, - "Routing activation denied due to missing authentication" }, - { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, - "Routing activation denied due to rejected confirmation" }, - { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, - "Routing activation denied due to unsupported routing activation type" }, - { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, - "Routing activation denied due to request for encrypted connection via TLS" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, - { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } - }; - - /** - * @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code - * related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum - * values to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, - { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, - { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, - { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, - { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, - { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, - { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, - }; - - /** - * @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for each power mode code - * related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum - * values to their corresponding descriptions. - */ - const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ - { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, - { DoIpDiagnosticPowerModeCodes::READY, "ready" }, - { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, - }; - - /** - * @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. - * - * This unordered map provides human-readable descriptions for the entity status codes - * in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values - * to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." - */ - const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatus::NODE, "DoIp node" }, - { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, - }; - - /** - * @brief Mapping of DoIP Acknowledgement Codes to their string representations. - * - * This unordered map provides a human-readable description for the DoIP acknowledgement - * code `ACK`, which is used to confirm the successful reception or processing of a message. - */ - const std::unordered_map DoIpEnumToStringAckCode{ - { DoIpDiagnosticAckCodes::ACK, "ACK" }, - }; - - /** - * @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. - * - * This unordered map provides a human-readable string for each synchronization status - * defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status - * values to their respective descriptions for logging or display purposes. - */ - const std::unordered_map DoIpEnumToStringSyncStatus{ - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, - { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, - { DoIpSyncStatus::NON_INITIALIZED, "NULL" } - }; - } // namespace internal -} // namespace pcpp diff --git a/Packet++/header/DoIpEnums.h b/Packet++/header/DoIpEnums.h deleted file mode 100644 index 990c1f14af..0000000000 --- a/Packet++/header/DoIpEnums.h +++ /dev/null @@ -1,711 +0,0 @@ -#pragma once - -#include -#include - -/// @file - -/** - * @namespace pcpp - * @brief The main namespace for the PcapPlusPlus lib - */ -namespace pcpp -{ - /** - * @brief Represents the DoIP (Diagnostics over IP) protocol versions. - */ - enum class DoIpProtocolVersion : uint8_t - { - /** - * @brief Reserved protocol version. - * This value is used when the version is not specified or invalid. - */ - reservedVersion = 0x00U, - - /** - * @brief Protocol version 1, based on ISO 2010 specification. - */ - version01Iso2010 = 0x01U, - - /** - * @brief Protocol version 2, based on ISO 2012 specification. - */ - version02Iso2012 = 0x02U, - - /** - * @brief Protocol version 3, based on ISO 2019 specification. - */ - version03Iso2019 = 0x03U, - - /** - * @brief Protocol version 4, based on ISO 2019 AMD1 (Amendment 1) specification. - */ - version04Iso2019_AMD1 = 0x04U, - - /** - * @brief Default protocol version. - * Used for broadcast Vehicle Identification Request Messages. - */ - defaultVersion = 0xFFU - }; - - /** - * @brief Enum representing DoIP routing activation types. - * These values specify the type of routing activation used in DoIP (Diagnostic over IP). - */ - enum class DoIpActivationTypes : uint8_t - { - /** - * Default routing activation type. - * Used when no specific type is required. - */ - Default = 0x00U, - - /** - * WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. - * Used for vehicle diagnostics in compliance with WWH-OBD standards. - */ - WWH_OBD = 0x01U, - - /** - * Central security routing activation type. - * Used for secure communications involving a central security system. - */ - CENTRAL_SECURITY = 0xE0U - }; - - /** - * @brief Enum representing DoIP payload types. - * - * These payload types are defined as part of the DoIP (Diagnostic over IP) protocol - * and specify the type of message being transmitted. - */ - enum class DoIpPayloadTypes : uint16_t - { - /** - * Generic header negative acknowledgment. - * Indicates a failure or error in processing the generic header. - */ - GENERIC_HEADER_NEG_ACK = 0x0000U, - - /** - * Vehicle identification request. - * Used to request identification details of a vehicle. - */ - VEHICLE_IDENTIFICATION_REQUEST = 0x0001U, - - /** - * Vehicle identification request with EID. - * Requests identification using an external identifier (EID). - */ - VEHICLE_IDENTIFICATION_REQUEST_WITH_EID = 0x0002U, - - /** - * Vehicle identification request with VIN. - * Requests identification using the vehicle's VIN (Vehicle Identification Number). - */ - VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN = 0x0003U, - - /** - * Announcement message. - * Sent to announce the availability of a DoIP entity. - */ - ANNOUNCEMENT_MESSAGE = 0x0004U, - - /** - * Routing activation request. - * Initiates a routing activation procedure. - */ - ROUTING_ACTIVATION_REQUEST = 0x0005U, - - /** - * Routing activation response. - * Response to a routing activation request. - */ - ROUTING_ACTIVATION_RESPONSE = 0x0006U, - - /** - * Alive check request. - * Sent to verify that a DoIP entity is still operational. - */ - ALIVE_CHECK_REQUEST = 0x0007U, - - /** - * Alive check response. - * Response to an alive check request. - */ - ALIVE_CHECK_RESPONSE = 0x0008U, - - /** - * Entity status request. - * Used to request the status of a DoIP entity. - */ - ENTITY_STATUS_REQUEST = 0x4001U, - - /** - * Entity status response. - * Response to an entity status request. - */ - ENTITY_STATUS_RESPONSE = 0x4002U, - - /** - * Diagnostic power mode request. - * Requests the current power mode of a DoIP entity. - */ - DIAGNOSTIC_POWER_MODE_REQUEST = 0x4003U, - - /** - * Diagnostic power mode response. - * Response to a diagnostic power mode request. - */ - DIAGNOSTIC_POWER_MODE_RESPONSE = 0x4004U, - - /** - * Diagnostic message type. - * Represents a generic diagnostic message. - */ - DIAGNOSTIC_MESSAGE_TYPE = 0x8001U, - - /** - * Diagnostic message positive acknowledgment. - * Indicates successful processing of a diagnostic message. - */ - DIAGNOSTIC_MESSAGE_POS_ACK = 0x8002U, - - /** - * Diagnostic message negative acknowledgment. - * Indicates an error in processing a diagnostic message. - */ - DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U, - }; - - /** - * @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). - * - * These codes are used to indicate specific errors in the DoIP Generic Header. - */ - enum class DoIpGenericHeaderNackCodes : uint8_t - { - /** - * Incorrect pattern detected in the header. - * Indicates that the header does not follow the expected pattern. - */ - INCORRECT_PATTERN = 0x00U, - - /** - * Unknown payload type. - * The payload type in the message is not recognized. - */ - INKNOWN_PAYLOAD_TYPE = 0x01U, - - /** - * Message too large. - * The message size exceeds the allowed limit. - */ - MESSAGE_TOO_LARGE = 0x02U, - - /** - * Out of memory. - * There is insufficient memory available to process the message. - */ - OUT_OF_MEMORY = 0x03U, - - /** - * Invalid payload length. - * The payload length specified in the header is invalid. - */ - INVALID_PAYLOAD_LENGTH = 0x04U, - }; - - /** - * @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). - * - * These action codes specify the next steps required after receiving a DoIP announcement message. - * Some codes are reserved for future use by ISO standards. - */ - enum class DoIpActionCodes : uint8_t - { - /** - * No further action required. - * Indicates that no additional steps are needed after the announcement. - */ - NO_FURTHER_ACTION_REQUIRED = 0x00U, - - /** - * Reserved for ISO (0x01). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x01 = 0x01U, - - /** - * Reserved for ISO (0x02). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x02 = 0x02U, - - /** - * Reserved for ISO (0x03). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x03 = 0x03U, - - /** - * Reserved for ISO (0x04). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x04 = 0x04U, - - /** - * Reserved for ISO (0x05). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x05 = 0x05U, - - /** - * Reserved for ISO (0x06). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x06 = 0x06U, - - /** - * Reserved for ISO (0x07). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x07 = 0x07U, - - /** - * Reserved for ISO (0x08). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x08 = 0x08U, - - /** - * Reserved for ISO (0x09). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x09 = 0x09U, - - /** - * Reserved for ISO (0x0A). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0A = 0x0AU, - - /** - * Reserved for ISO (0x0B). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0B = 0x0BU, - - /** - * Reserved for ISO (0x0C). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0C = 0x0CU, - - /** - * Reserved for ISO (0x0D). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0D = 0x0DU, - - /** - * Reserved for ISO (0x0E). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0E = 0x0EU, - - /** - * Reserved for ISO (0x0F). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0F = 0x0FU, - - /** - * Routing activation required. - * Indicates that routing activation is needed after the announcement message. - */ - ROUTING_ACTIVATION_REQUIRED = 0x10U, - }; - - /** - * @brief Enum representing DoIP routing activation response codes (ISO 13400). - * - * These codes are used in response to routing activation requests, providing status - * or error information related to the request. - */ - enum class DoIpRoutingResponseCodes : uint8_t - { - /** - * Unknown source address. - * The source address provided in the request is not recognized. - */ - UNKNOWN_SOURCE_ADDRESS = 0x00U, - - /** - * No free socket. - * There are no available sockets to establish the connection. - */ - NO_FREE_SOCKET = 0x01U, - - /** - * Wrong source address. - * The source address provided in the request is invalid. - */ - WRONG_SOURCE_ADDRESS = 0x02U, - - /** - * Source address already registered. - * The provided source address has already been activated. - */ - SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, - - /** - * Missing authentication. - * The request is missing required authentication credentials. - */ - MISSING_AUTHENTICATION = 0x04U, - - /** - * Rejected confirmation. - * The confirmation of routing activation was rejected. - */ - REJECTED_CONFIRMATION = 0x05U, - - /** - * Unsupported activation type. - * The requested routing activation type is not supported. - */ - UNSUPPORTED_ACTIVATION_TYPE = 0x06U, - - /** - * Encrypted connection required (TLS). - * Indicates that the routing activation requires a secure TLS connection. - */ - ENCRYPTED_CONNECTION_TLS = 0x07U, - - /** - * Reserved for ISO (0x08). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x08 = 0x08U, - - /** - * Reserved for ISO (0x09). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x09 = 0x09U, - - /** - * Reserved for ISO (0x0A). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0A = 0x0AU, - - /** - * Reserved for ISO (0x0B). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0B = 0x0BU, - - /** - * Reserved for ISO (0x0C). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0C = 0x0CU, - - /** - * Reserved for ISO (0x0D). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0D = 0x0DU, - - /** - * Reserved for ISO (0x0E). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0E = 0x0EU, - - /** - * Reserved for ISO (0x0F). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0F = 0x0FU, - - /** - * Routing successfully activated. - * The routing activation request was processed successfully. - */ - ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, - - /** - * Confirmation required. - * Additional confirmation is required to complete the routing activation. - */ - CONFIRMATION_REQUIRED = 0x11U, - }; - - /** - * @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). - * - * These codes indicate reasons for rejecting or failing to process a diagnostic message - * in the DoIP protocol. - */ - enum class DoIpDiagnosticMessageNackCodes : uint8_t - { - /** - * Reserved for ISO (0x00). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x00 = 0x00U, - - /** - * Reserved for ISO (0x01). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x01 = 0x01U, - - /** - * Invalid source address. - * The source address specified in the message is invalid. - */ - INVALID_SOURCE_ADDRESS = 0x02U, - - /** - * Invalid target address. - * The target address specified in the message is invalid. - */ - INVALID_TARGET_ADDRESS = 0x03U, - - /** - * Message too large. - * The size of the message exceeds the maximum allowed limit. - */ - MESSAGE_TOO_LARGE = 0x04U, - - /** - * Out of memory. - * There is insufficient memory available to process the message. - */ - OUT_OF_MEMORY = 0x05U, - - /** - * Target unreachable. - * The specified target address cannot be reached. - */ - TARGET_UNREACHABLE = 0x06U, - - /** - * Unknown network. - * The message references a network that is not recognized or supported. - */ - UNKNOWN_NETWORK = 0x07U, - - /** - * Transport protocol error. - * An error occurred at the transport protocol level, preventing the message from being processed. - */ - TRANSPORT_PROTOCOL_ERROR = 0x08U, - }; - - /** - * @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). - * - * These codes indicate the diagnostic power mode status of a DoIP entity, - * providing information about its readiness for diagnostic operations. - */ - enum class DoIpDiagnosticPowerModeCodes : uint8_t - { - /** - * Not ready. - * The DoIP entity is not ready to perform diagnostic operations. - */ - NOT_READY = 0x00U, - - /** - * Ready. - * The DoIP entity is ready to perform diagnostic operations. - */ - READY = 0x01U, - - /** - * Not supported. - * The DoIP entity does not support diagnostic power mode reporting. - */ - NOT_SUPPORTED = 0x02U - }; - - /** - * @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). - * - * These codes are used to acknowledge the receipt or processing of diagnostic messages - * in the DoIP protocol. - */ - enum class DoIpDiagnosticAckCodes : uint8_t - { - /** - * Acknowledgment. - * Indicates successful receipt or acknowledgment of a diagnostic message. - */ - ACK = 0x00U - }; - - /** - * @brief Enum representing DoIP entity status response codes (ISO 13400). - * - * These codes are used to indicate the role or type of a DoIP entity in the network. - */ - enum class DoIpEntityStatus : uint8_t - { - /** - * Gateway. - * The entity functions as a gateway, facilitating communication between networks. - */ - GATEWAY = 0x00U, - - /** - * Node. - * The entity functions as an individual node within the DoIP network. - */ - NODE = 0x01U - }; - - /** - * @brief Enum representing DoIP sync status (ISO 13400). - * - * These codes are used to indicate whether GID and VIN are synchronized or not. - */ - enum class DoIpSyncStatus : uint8_t - { - /** - * VIN and/or GID are synchronized. - */ - VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, - - /** - * Reserved for ISO (0x01). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x01 = 0x01U, - - /** - * Reserved for ISO (0x02). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x02 = 0x02U, - - /** - * Reserved for ISO (0x03). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x03 = 0x03U, - - /** - * Reserved for ISO (0x04). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x04 = 0x04U, - - /** - * Reserved for ISO (0x05). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x05 = 0x05U, - - /** - * Reserved for ISO (0x06). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x06 = 0x06U, - - /** - * Reserved for ISO (0x07). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x07 = 0x07U, - - /** - * Reserved for ISO (0x08). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x08 = 0x08U, - - /** - * Reserved for ISO (0x09). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x09 = 0x09U, - - /** - * Reserved for ISO (0x0A). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0A = 0x0AU, - - /** - * Reserved for ISO (0x0B). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0B = 0x0BU, - /** - * Reserved for ISO (0x0C). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0C = 0x0CU, - - /** - * Reserved for ISO (0x0D). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0D = 0x0DU, - - /** - * Reserved for ISO (0x0E). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0E = 0x0EU, - - /** - * Reserved for ISO (0x08). - * Reserved for future use as per ISO standards. - */ - RESERVED_ISO_0x0F = 0x0FU, - - /** - * VIN and/or GID are not synchronized. - */ - VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, - - /** - * Check whether this field is initialised or not - */ - NON_INITIALIZED - }; - - /** - * @brief Enum representing DoIP diagnostic ports (ISO 13400). - * - * These ports are used for communication in the DoIP protocol over different transport layers. - */ - enum class DoIpPorts : uint16_t - { - /** - * UDP Port. - * The standard port for DoIP communication over UDP. - */ - UDP_PORT = 13400U, - - /** - * TCP Port. - * The standard port for DoIP communication over TCP. - */ - TCP_PORT = 13400U, - - /** - * TLS Port. - * The standard port for DoIP communication over a secure TLS connection. - */ - TLS_PORT = 3496U - }; - -} // namespace pcpp diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 3a3238d07e..d450b96490 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -7,223 +7,628 @@ #include "IpAddress.h" #include "MacAddress.h" #include "Logger.h" -#include "GeneralUtils.h" -#include "DoIpLayerData.h" /// @file -/** - * @namespace pcpp - * @brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /** - * @struct doiphdr - * Represents an DoIP protocol header - */ + class IDoIpMessageData; + + enum class DoIpPayloadTypes : uint16_t; + enum class DoIpProtocolVersion : uint8_t; + + extern const std::unordered_map DoIpEnumToStringPayloadType; + extern const std::unordered_map DoIpEnumToStringProtocolVersion; + + /// @brief Represents the DoIP (Diagnostics over IP) protocol versions. + enum class DoIpProtocolVersion : uint8_t + { + /// @brief Reserved protocol version. + /// This value is used when the version is not specified. + ReservedVersion = 0x00U, + + /// @brief Protocol version 1, based on ISO 2010 specification. + Version01Iso2010 = 0x01U, + + /// @brief Protocol version 2, based on ISO 2012 specification. + Version02Iso2012 = 0x02U, + + /// @brief Protocol version 3, based on ISO 2019 specification. + Version03Iso2019 = 0x03U, + + /// @brief Protocol version 4, based on ISO 2019 AMD1 (Amendment 1) specification. + Version04Iso2019_AMD1 = 0x04U, + + /// @brief Default protocol version. + /// Used for broadcast Vehicle Identification Request Messages. + DefaultVersion = 0xFFU, + + /// @brief Represents an unknown or unsupported protocol version + UnknownVersion = 0xEF + }; + + /// @brief Enum representing DoIP routing activation types. + /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). + enum class DoIpActivationTypes : uint8_t + { + /// Default routing activation type. + /// Used when no specific type is required. + Default = 0x00U, + + /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. + /// Used for vehicle diagnostics in compliance with WWH-OBD standards. + WWH_OBD = 0x01U, + + /// Central security routing activation type. + /// Used for secure communications involving a central security system. + CENTRAL_SECURITY = 0xE0U + }; + + /// @brief Enum representing DoIP payload types. + /// These payload types are defined as part of theDoIP(Diagnostic over IP) protocol + /// and specify the type of message being transmitted. + enum class DoIpPayloadTypes : uint16_t + { + /// Generic header negative acknowledgment. + /// Indicates a failure or error in processing the generic header. + GENERIC_HEADER_NEG_ACK = 0x0000U, + + /// Vehicle identification request. + /// Used to request identification details of a vehicle. + VEHICLE_IDENTIFICATION_REQUEST = 0x0001U, + + /// Vehicle identification request with EID. + /// Requests identification using an external identifier(EID). + VEHICLE_IDENTIFICATION_REQUEST_WITH_EID = 0x0002U, + + /// Vehicle identification request with VIN. + /// Requests identification using the vehicle's VIN (Vehicle Identification Number). + VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN = 0x0003U, + + /// Announcement message. + /// Sent to announce the availability of a DoIP entity. + ANNOUNCEMENT_MESSAGE = 0x0004U, + + /// Routing activation request. + /// Initiates a routing activation procedure. + ROUTING_ACTIVATION_REQUEST = 0x0005U, + + /// Routing activation response. + /// Response to a routing activation request. + ROUTING_ACTIVATION_RESPONSE = 0x0006U, + + /// Alive check request. + /// Sent to verify that a DoIP entity is still operational. + ALIVE_CHECK_REQUEST = 0x0007U, + + /// Alive check response. + /// Response to an alive check request. + ALIVE_CHECK_RESPONSE = 0x0008U, + + /// Entity status request. + /// Used to request the status of a DoIP entity. + ENTITY_STATUS_REQUEST = 0x4001U, + + /// Entity status response. + /// Response to an entity status request. + ENTITY_STATUS_RESPONSE = 0x4002U, + + /// Diagnostic power mode request. + /// Requests the current power mode of a DoIP entity. + DIAGNOSTIC_POWER_MODE_REQUEST = 0x4003U, + + /// Diagnostic power mode response. + /// Response to a diagnostic power mode request. + DIAGNOSTIC_POWER_MODE_RESPONSE = 0x4004U, + + /// Diagnostic message type. + /// Represents a generic diagnostic message. + DIAGNOSTIC_MESSAGE_TYPE = 0x8001U, + + /// Diagnostic message positive acknowledgment. + /// Indicates successful processing of a diagnostic message. + DIAGNOSTIC_MESSAGE_POS_ACK = 0x8002U, + + /// Diagnostic message negative acknowledgment. + /// Indicates an error in processing a diagnostic message. + DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U, + }; + + /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). + /// These codes are used to indicate specific errors in the DoIP Generic Header. + enum class DoIpGenericHeaderNackCodes : uint8_t + { + /// Incorrect pattern detected in the header. + /// Indicates that the header does not follow the expected pattern. + INCORRECT_PATTERN = 0x00U, + + /// Unknown payload type. + /// The payload type in the message is not recognized. + UNKNOWN_PAYLOAD_TYPE = 0x01U, + + /// Message too large. + /// The message size exceeds the allowed limit. + MESSAGE_TOO_LARGE = 0x02U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x03U, + + /// Invalid payload length. + /// The payload length specified in the header is invalid. + INVALID_PAYLOAD_LENGTH = 0x04U, + }; + + /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). + /// These action codes specify the next steps required after receiving a DoIP announcement message. + /// Some codes are reserved for future use by ISO standards. + enum class DoIpActionCodes : uint8_t + { + + /// No further action required. + /// Indicates that no additional steps are needed after the announcement. + NO_FURTHER_ACTION_REQUIRED = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing activation required. + /// Indicates that routing activation is needed after the announcement message. + ROUTING_ACTIVATION_REQUIRED = 0x10U, + }; + + /// @brief Enum representing DoIP routing activation response codes (ISO 13400). + /// These codes are used in response to routing activation requests, providing status + /// or error information related to the request. + enum class DoIpRoutingResponseCodes : uint8_t + { + /// Unknown source address. + /// The source address provided in the request is not recognized. + UNKNOWN_SOURCE_ADDRESS = 0x00U, + + /// No free socket. + /// There are no available sockets to establish the connection. + NO_FREE_SOCKET = 0x01U, + + /// Wrong source address. + /// The source address provided in the request is invalid. + WRONG_SOURCE_ADDRESS = 0x02U, + + /// Source address already registered. + /// The provided source address has already been activated. + SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, + + /// Missing authentication. + /// The request is missing required authentication credentials. + MISSING_AUTHENTICATION = 0x04U, + + /// Rejected confirmation. + /// The confirmation of routing activation was rejected. + REJECTED_CONFIRMATION = 0x05U, + + /// Unsupported activation type. + /// The requested routing activation type is not supported. + + UNSUPPORTED_ACTIVATION_TYPE = 0x06U, + + /// Encrypted connection required(TLS). + /// Indicates that the routing activation requires a secure TLS connection. + ENCRYPTED_CONNECTION_TLS = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing successfully activated. + /// The routing activation request was processed successfully. + ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, + + /// Confirmation required. + /// Additional confirmation is required to complete the routing activation. + CONFIRMATION_REQUIRED = 0x11U, + }; + + /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). + /// These codes indicate reasons for rejecting or failing to process a diagnostic message + /// in the DoIP protocol. + enum class DoIpDiagnosticMessageNackCodes : uint8_t + { + + /// Reserved for ISO (0x00). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x00 = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Invalid source address. + /// The source address specified in the message is invalid. + INVALID_SOURCE_ADDRESS = 0x02U, + + /// Invalid target address. + /// The target address specified in the message is invalid. + INVALID_TARGET_ADDRESS = 0x03U, + + /// Message too large. + /// The size of the message exceeds the maximum allowed limit. + MESSAGE_TOO_LARGE = 0x04U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x05U, + + /// Target unreachable. + /// The specified target address cannot be reached. + TARGET_UNREACHABLE = 0x06U, + + /// Unknown network. + /// The message references a network that is not recognized or supported. + UNKNOWN_NETWORK = 0x07U, + + /// Transport protocol error. + /// An error occurred at the transport protocol level, preventing the message from being processed. + TRANSPORT_PROTOCOL_ERROR = 0x08U, + }; + + /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). + /// These codes indicate the diagnostic power mode status of a DoIP entity, + /// providing information about its readiness for diagnostic operations. + enum class DoIpDiagnosticPowerModeCodes : uint8_t + { + + /// Not ready. + /// The DoIP entity is not ready to perform diagnostic operations. + NOT_READY = 0x00U, + + /// Ready. + /// The DoIP entity is ready to perform diagnostic operations. + READY = 0x01U, + + /// Not supported. + /// The DoIP entity does not support diagnostic power mode reporting. + NOT_SUPPORTED = 0x02U + }; + + /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). + /// These codes are used to acknowledge the receipt or processing of diagnostic messages + /// in the DoIP protocol. + enum class DoIpDiagnosticAckCodes : uint8_t + { + + /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. + + ACK = 0x00U + }; + + /// @brief Enum representing DoIP entity status response codes (ISO 13400). + /// These codes are used to indicate the role or type of a DoIP entity in the network. + enum class DoIpEntityStatus : uint8_t + { + /// Gateway. + /// The entity functions as a gateway, + /// facilitating communication between networks. + GATEWAY = 0x00U, + + /// Node. + /// The entity functions as an individual node within the DoIP network. + NODE = 0x01U + }; + + /// @brief Enum representing DoIP sync status (ISO 13400). + /// These codes are used to indicate whether GID and VIN are synchronized or not. + enum class DoIpSyncStatus : uint8_t + { + + /// VIN and or GID are synchronized. + VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// VIN and or GID are not synchronized. + VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, + + /// Check whether this field is initialised or not + NON_INITIALIZED + }; + + /// @brief Enum representing DoIP diagnostic ports (ISO 13400). + /// These ports are used for communication in the DoIP protocol over different transport layers. + + enum class DoIpPorts : uint16_t + { + + /// UDP Port. + /// The standard port for DoIP communication over UDP. + UDP_PORT = 13400U, + + /// TCP Port. + /// The standard port for DoIP communication over TCP. + TCP_PORT = 13400U, + + /// TLS Port. + /// The standard port for DoIP communication over a secure TLS connection. + TLS_PORT = 3496U + }; + +/// @struct doiphdr +/// Represents an DoIP protocol header #pragma pack(push, 1) struct doiphdr { - /** DoIP version (DOIPV) */ + /// DoIP version (DOIPV) uint8_t protocolVersion; - /** DoIP invert version (DOIPIV). Inverse of protocol version */ + /// DoIP invert version (DOIPIV). Inverse of protocol version uint8_t invertProtocolVersion; - /** DoIP payload type (DOIPT)*/ + /// DoIP payload type (DOIPT) uint16_t payloadType; - /** DoIP content payload length (DOIPL)*/ + /// DoIP content payload length (DOIPL) uint32_t payloadLength; }; #pragma pack(pop) static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes."); - /** - * @class DoIpLayer - * Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported - */ + /// @class DoIpLayer + /// Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported class DoIpLayer : public Layer { - // class DoIpLayerData; public: - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data (will be casted to @ref doiphdr) - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ + /// A constructor that creates the layer from an existing packet raw data + /// @param[in] data A pointer to the raw data (will be casted to @ref doiphdr) + /// @param[in] dataLen Size of the data in bytes + /// @param[in] prevLayer A pointer to the previous layer + /// @param[in] packet A pointer to the Packet instance where layer will be stored in DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet, DOIP) {} - /** - * A constructor that creates an generic doip layer and set header and payload fields - * @param[in] version DoIpProtocolVersion specify the doip protocol version - * @param[in] type DoIpPayloadTypes indicating the doip payload type - * @param[in] data IDoIpMessageData contains all doipMessage specification based on its payload type - */ + /// A constructor that creates an generic doip layer and set header and payload fields + /// @param[in] version DoIpProtocolVersion specify the doip protocol version + /// @param[in] type DoIpPayloadTypes indicating the doip payload type + /// @param[in] data IDoIpMessageData contains all doipMessage specification based on its payload type DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); - /** - * A constructor that create a doip announcement message with all - * zeros for vin, eid, gid and no further action required - */ + /// A constructor that create a doip announcement message with all + /// zeros for vin, eid, gid and no further action required DoIpLayer(); - /** - * init doip layer with all zeros with size of doip header - */ - void initLayer(); - - /** - * A destructor for DoIpLayer class - */ - ~DoIpLayer() override {}; + /// A destructor for DoIpLayer class + virtual ~DoIpLayer() override = default; - /** - * Get a pointer to the DoIP header. Notice this points directly to the data, so every change will change the - * actual packet data - * @return A pointer to the @ref doiphdr - */ - doiphdr* getDoIpHeader() const - { - return reinterpret_cast(m_Data); - } - /** - * Check the integrity of protocol version in doip header - * @return true if version has no integration errors - */ - bool resolveProtocolVersion() const; - - /** - * Check the integrity of length field in doip header - * @return true if length represent the exact payload arg struct size - */ - bool resolvePayloadLength() const; - - /** - * Get the version of DOIP protocol - * @return DoIpProtocolVersion presenting the used protocol version (DOIPV) - */ + /// Get the version of DOIP protocol + /// @return DoIpProtocolVersion presenting the used protocol version (DOIPV) DoIpProtocolVersion getProtocolVersion() const; - /** - * Get the version of DOIP protocol - * @return string presentation the used protocol version (DOIPV) - */ + /// Get the version of DOIP protocol + /// @return string presentation the used protocol version (DOIPV) std::string getProtocolVersionAsStr() const; - /** - * Set the version of DOIP protocol - * @param[in] version the version of DOIP protocol to set, restricted to existent doip version - */ + /// Set the version of DOIP protocol + /// @param[in] version the version of DOIP protocol to set, restricted to existent doip version void setProtocolVersion(DoIpProtocolVersion version); - /** - * Get the invert version of DOIP protocol - * @return A uint8_t presenting the used protocol invert version (DOIPV) - */ + /// Get the invert version of DOIP protocol + /// @return A uint8_t presenting the used protocol invert version (DOIPV) uint8_t getInvertProtocolVersion() const; - /** - * Set the invert protocol version of DOIP protocol - * @param[in] iVersion the invert version of DOIP protocol to set - */ + /// Set the invert protocol version of DOIP protocol + /// @param[in] iVersion the invert version of DOIP protocol to set void setInvertProtocolVersion(uint8_t iVersion); - /** - * Get the doip payload type - * @return DoIpPayloadTypes presenting the message doip payload type - */ + /// Get the doip payload type + /// @return DoIpPayloadTypes presenting the message doip payload type DoIpPayloadTypes getPayloadType() const; - /** - * Get the doip payload type as string - * @return uint16_t presenting the message doip payload type as string - */ + /// Get the doip payload type as string + /// @return uint16_t presenting the message doip payload type as string std::string getPayloadTypeAsStr() const; - /** - * Set the doip payload type - * @param[in] payloadType the payload type to set - */ + /// Set the doip payload type + /// @param[in] payloadType the payload type to set void setPayloadType(DoIpPayloadTypes payloadType); - /** - * Get the doip payload length - * @return uint32_t presenting the length of doip paylad not including the header - */ + /// Get the doip payload length + /// @return uint32_t presenting the length of doip paylad not including the header uint32_t getPayloadLength() const; - /** - * Set the doip payload length - * @param[in] length the doip payload length to set - */ - void setPayloadLength(uint32_t length); - - /** - * copy data from msgFields to dest - * @param[in] dest pointer to where start copying - * @param[in] data the doip Fields to copy - */ + /// Set the doip payload length + /// @param[in] length the doip payload length to set + void setPayloadLength(uint32_t length) const; + + /// copy data from msgFields to dest + /// @param[in] dest pointer to where start copying + /// @param[in] data the doip Fields to copy void serializeData(uint8_t* dest, std::vector data); - /** - * A static method that checks whether a port is considered as a DOIP port - * @param[in] port The port number to check - * @return True if this is a DOIP port number, false otherwise - */ + /// A static method that checks whether a port is considered as a DOIP port + /// @param[in] port The port number to check + /// @return True if this is a DOIP port number, false otherwise static inline bool isDoIpPort(uint16_t port); - /** - * A static method that validates the input data - * @param[in] data The pointer to the beginning of a byte stream of an DOIP layer - * @param[in] dataLen The length of the byte stream - * @return True if the data is valid and can represent an DOIP layer - */ + /// A static method that validates the input data + /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer + /// @param[in] dataLen The length of the byte stream + /// @return True if the data is valid and can represent an DOIP layer static inline bool isDataValid(const uint8_t* data, size_t dataLen); - /** - * @brief Builds the DoIP layer based on the payload type and provided data. - * - * This function configures the DoIP layer with the appropriate payload type, payload length, - * and data, depending on the specified payload type. If the payload type does not require - * additional data, the payload length is set to zero. For payloads that require data, the data - * is serialized and added to the layer. - * - * @param type The DoIP payload type to set for this layer. - * @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. - * This parameter can be nullptr for payload types that do not require additional data. - * - * @note If the payload type requires data and the `data` parameter is `nullptr`, an error message - * is logged, and the function does not build the layer. - */ + /// @brief Builds the DoIP layer based on the payload type and provided data. + /// + /// This function configures the DoIP layer with the appropriate payload type, payload length, + /// and data, depending on the specified payload type. If the payload type does not require + /// additional data, the payload length is set to zero. For payloads that require data, the data + /// is serialized and added to the layer. + /// + /// @param type The DoIP payload type to set for this layer. + /// @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. + /// This parameter can be nullptr for payload types that do not require additional data. + /// + /// @note If the payload type requires data and the `data` parameter is `nullptr`, an error message + /// is logged, and the function does not build the layer. void buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); - /** - * @brief Resolves and validates the DoIP layer. - * - * This function validates the protocol version and payload length of the DoIP layer. - * If either validation fails, an error is logged, and the function returns `false`. - * - * @return `true` if both the protocol version and payload length are valid; - * otherwise, `false`. - * - * @note This function is typically used to ensure the integrity of the DoIP layer - * before further processing or transmission. - */ - bool resolveLayer() const; + /// @brief Resolves and validates the DoIP layer. + /// + /// This function validates the protocol version and payload length of the DoIP layer. + /// If either validation fails, an error is logged, and the function returns `false`. + /// + /// @return `true` if both the protocol version and payload length are valid; + /// otherwise, `false`. + /// + /// @note This function is typically used to ensure the integrity of the DoIP layer + /// before further processing or transmission. + bool isLayerDataValid() const; // implement abstract methods - /** - * TODO, parse UDS layer - */ + /// parse UDS layer void parseNextLayer() override; - /** - * @return The size of @ref doiphdr + attached fields length - */ + /// @return The size of @ref doiphdr + attached fields length size_t getHeaderLen() const override { return m_DataLen; @@ -237,13 +642,34 @@ namespace pcpp { return OsiModelTransportLayer; } + + private: + /// init doip layer with all zeros with size of doip header. + void initLayer(); + + /// Get a pointer to the DoIP header. Notice this points directly to the data, so every change will change the + /// actual packet data + /// @return A pointer to the @ref doiphdr + doiphdr* getDoIpHeader() const + { + return reinterpret_cast(m_Data); + } + + /// Check the integrity of length field in doip header + /// @return true if length represent the exact payload arg struct size + bool isPayloadLengthValid() const; + + /// Check the integrity of protocol version in doip header + /// @return true if version has no integration errors + bool isProtocolVersionValid() const; }; // inline methods definition inline bool DoIpLayer::isDoIpPort(uint16_t port) { - return ((DoIpPorts)port == DoIpPorts::UDP_PORT || (DoIpPorts)port == DoIpPorts::TCP_PORT || - (DoIpPorts)port == DoIpPorts::TLS_PORT); + return (static_cast(port) == DoIpPorts::UDP_PORT || + static_cast(port) == DoIpPorts::TCP_PORT || + static_cast(port) == DoIpPorts::TLS_PORT); } inline bool DoIpLayer::isDataValid(const uint8_t* data, size_t dataLen) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 91ad475e61..aabc0eaaa7 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -5,843 +5,677 @@ #include #include "EndianPortable.h" #include "Logger.h" -#include "GeneralUtils.h" -#include "DoIpEnumToString.h" +#include "DoIpLayer.h" /// @file -/** - * @namespace pcpp - * @brief The main namespace for the PcapPlusPlus library - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus library namespace pcpp { -/** - * @brief Length of the External Identifier (EID) field. - */ +/// @brief Length of the External Identifier (EID) field. #define DOIP_EID_LEN 6 -/** - * @brief Length of the Group Identifier (GID) field. - */ +/// @brief Length of the Group Identifier (GID) field. #define DOIP_GID_LEN 6 -/** - * @brief Length of the Vehicle Identification Number (VIN) field. - */ +/// @brief Length of the Vehicle Identification Number (VIN) field. #define DOIP_VIN_LEN 17 -/** - * @brief Length of the Reserved ISO field. - */ +/// @brief Length of the Reserved ISO field. #define DOIP_RESERVED_ISO_LEN 4 -/** - * @brief Length of the Reserved OEM field. - */ +/// @brief Length of the Reserved OEM field. #define DOIP_RESERVED_OEM_LEN 4 - // forward declaration for DoIpLayer class - class DoIpLayer; - - /** - * @brief A pure abstract class representing the basic structure of DoIP messages. - * - * This interface defines methods to retrieve the type, string representation, - * and binary data of DoIP messages. All DoIP message classes must implement this interface. - */ + /// @brief A pure abstract class representing the basic structure of DoIP messages. + /// + /// This interface defines methods to retrieve the type, string representation, + /// and binary data of DoIP messages. All DoIP message classes must implement this interface. class IDoIpMessageData { public: virtual ~IDoIpMessageData() = default; - /** - * @brief Returns the type of the DoIP message. - * @return The type of the message as a `DoIpPayloadTypes` enum. - */ + /// @brief Returns the type of the DoIP message. + /// @return The type of the message as a `DoIpPayloadTypes` enum. virtual DoIpPayloadTypes getType() const = 0; - /** - * @brief Converts the message data to a human-readable string. - * @return The string representation of the message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return The string representation of the message. virtual std::string toString() const = 0; - /** - * @brief Retrieves the raw binary data of the message. - * @return The message data as a vector of bytes. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return The message data as a vector of bytes. virtual std::vector getData() const = 0; }; - /** - * @class RoutingActivationRequestData - * @brief Represents a Routing Activation Request message in DoIP. - * - * This class encapsulates data for a Routing Activation Request message, - * including source address, activation type, and reserved fields. - */ + /// @class RoutingActivationRequestData + /// @brief Represents a Routing Activation Request message in DoIP. + /// + /// This class encapsulates data for a Routing Activation Request message, + /// including source address, activation type, and reserved fields. class RoutingActivationRequestData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the RoutingActivationRequestData class. - * - * Initializes a `RoutingActivationRequestData` instance with default values: - * - `sourceAddress` is set to `0x0000`. - * - `activationType` is set to `DoIpActivationTypes::Default`. - * - `reservedIso` and `reservedOem` fields are zero-initialized. - * This constructor provides a default initialization state for routing activation request - * data, ensuring compliance with the DoIP protocol requirements. - */ + /// @brief Default constructor for the RoutingActivationRequestData class. + /// + /// Initializes a `RoutingActivationRequestData` instance with default values: + /// - `sourceAddress` is set to `0x0000`. + /// - `activationType` is set to `DoIpActivationTypes::Default`. + /// - `reservedIso` and `reservedOem` fields are zero-initialized. + /// This constructor provides a default initialization state for routing activation request + /// data, ensuring compliance with the DoIP protocol requirements. RoutingActivationRequestData(); - uint16_t sourceAddress; /**< Source address of the message. */ - DoIpActivationTypes activationType; /**< The activation type (e.g., activate, deactivate). */ - std::array reservedIso; /**< Reserved ISO bytes. */ - std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ + uint16_t sourceAddress; /// < Source address of the message. + DoIpActivationTypes activationType; /// < The activation type (e.g., activate, deactivate). + std::array reservedIso; /// < Reserved ISO bytes. + std::unique_ptr> reservedOem; /// < Reserved OEM bytes. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Routing Activation Request message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Routing Activation Request message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Routing Activation Request data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Routing Activation Request payload type. It extracts the source address, activation - * type, reserved ISO bytes, and optionally reserved OEM bytes if present. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Request data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note This method overrides the base class implementation and adds specific parsing - * logic for the Routing Activation Request message. - * - * The following fields are parsed: - * - `sourceAddress`: The source address of the message. - * - `activationType`: The type of activation requested. - * - `reservedIso`: Reserved bytes as defined by ISO specifications. - * - `reservedOem`: Reserved bytes as defined by OEM specifications, only if present. - */ + /// @brief Parses and initializes the Routing Activation Request data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Routing Activation Request payload type. It extracts the source address, activation + /// type, reserved ISO bytes, and optionally reserved OEM bytes if present. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Request data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note This method overrides the base class implementation and adds specific parsing + /// logic for the Routing Activation Request message. + /// + /// The following fields are parsed: + /// - `sourceAddress`: The source address of the message. + /// - `activationType`: The type of activation requested. + /// - `reservedIso`: Reserved bytes as defined by ISO specifications. + /// - `reservedOem`: Reserved bytes as defined by OEM specifications, only if present. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class RoutingActivationResponseData - * @brief Represents a Routing Activation Response message in DoIP. - * - * This class encapsulates data for a Routing Activation Response message, - * including logical address, source address, response code, and reserved fields. - */ + /// @class RoutingActivationResponseData + /// @brief Represents a Routing Activation Response message in DoIP. + /// + /// This class encapsulates data for a Routing Activation Response message, + /// including logical address, source address, response code, and reserved fields. class RoutingActivationResponseData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the RoutingActivationResponseData class. - * Initializes a `RoutingActivationResponseData` instance with default values: - * - `logicalAddressExternalTester` is set to `0x0000`. - * - `sourceAddress` is set to `0x0000`. - * - `responseCode` is set to DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED. - * - `reservedIso` fields is zero-initialized. - * This constructor provides a default initialization state for routing activation response - * data, ensuring compliance with the DoIP protocol requirements. - */ + /// @brief Default constructor for the RoutingActivationResponseData class. + /// Initializes a `RoutingActivationResponseData` instance with default values: + /// - `logicalAddressExternalTester` is set to `0x0000`. + /// - `sourceAddress` is set to `0x0000`. + /// - `responseCode` is set to DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED. + /// - `reservedIso` fields is zero-initialized. + /// This constructor provides a default initialization state for routing activation response + /// data, ensuring compliance with the DoIP protocol requirements. RoutingActivationResponseData(); - uint16_t logicalAddressExternalTester; /**< Logical address of the external tester. */ - uint16_t sourceAddress; /**< Source address of the message. */ - DoIpRoutingResponseCodes responseCode; /**< Response code indicating success or failure. */ - std::array reservedIso; /**< Reserved ISO bytes. */ - std::unique_ptr> reservedOem; /**< Reserved OEM bytes. */ + uint16_t logicalAddressExternalTester; /// < Logical address of the external tester. + uint16_t sourceAddress; /// < Source address of the message. + DoIpRoutingResponseCodes responseCode; /// < Response code indicating success or failure. + std::array reservedIso; /// < Reserved ISO bytes. + std::unique_ptr> reservedOem; /// < Reserved OEM bytes. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Routing Activation Response message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Routing Activation Response message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses the Routing Activation Response data from a DoIpLayer. - * - * This method validates and extracts the necessary fields from the provided - * DoIpLayer. It ensures the layer corresponds to the Routing Activation Response - * payload type and parses fields including the logical tester address, source - * address, response code, and reserved fields. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Response data. - * @return `true` if parsing was successful, `false` otherwise. - */ + /// @brief Parses the Routing Activation Response data from a DoIpLayer. + /// + /// This method validates and extracts the necessary fields from the provided + /// DoIpLayer. It ensures the layer corresponds to the Routing Activation Response + /// payload type and parses fields including the logical tester address, source + /// address, response code, and reserved fields. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Response data. + /// @return `true` if parsing was successful, `false` otherwise. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class GenericHeaderNackData - * @brief Represents a Generic Header Negative Acknowledgment message in DoIP. - * - * This class encapsulates data for a Generic Header NACK message, including - * the NACK code to indicate the failure. - */ + /// @class GenericHeaderNackData + /// @brief Represents a Generic Header Negative Acknowledgment message in DoIP. + /// + /// This class encapsulates data for a Generic Header NACK message, including + /// the NACK code to indicate the failure. class GenericHeaderNackData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the GenericHeaderNackData class. - * - * This constructor initializes a `GenericHeaderNackData` instance with default values: - * - `genericNackCode` is set to `DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH`. - */ + /// @brief Default constructor for the GenericHeaderNackData class. + /// + /// This constructor initializes a `GenericHeaderNackData` instance with default values: + /// - `genericNackCode` is set to `DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH`. GenericHeaderNackData(); - DoIpGenericHeaderNackCodes genericNackCode; /**< The NACK code indicating the error. */ + DoIpGenericHeaderNackCodes genericNackCode; /// < The NACK code indicating the error. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Generic Header NACK message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Generic Header NACK message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Generic Header NACK data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Generic Header NACK payload type. It extracts the `genericNackCode` field from the layer. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Generic Header NACK data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method checks for null pointers and verifies that the payload type matches - * `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. Logs an error in case of invalid data. - * - * The following field is parsed: - * - `genericNackCode`: The NACK code indicating the type of error. - */ + /// @brief Parses and initializes the Generic Header NACK data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Generic Header NACK payload type. It extracts the `genericNackCode` field from the layer. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Generic Header NACK data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method checks for null pointers and verifies that the payload type matches + /// `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. Logs an error in case of invalid data. + /// + /// The following field is parsed: + /// - `genericNackCode`: The NACK code indicating the type of error. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class VehicleIdentificationRequestEIDData - * @brief Represents a Vehicle Identification Request with EID message in DoIP. - * - * This class encapsulates data for a Vehicle Identification Request message - * that includes the Electronic Identifier (EID). - */ + /// @class VehicleIdentificationRequestEIDData + /// @brief Represents a Vehicle Identification Request with EID message in DoIP. + /// + /// This class encapsulates data for a Vehicle Identification Request message + /// that includes the Electronic Identifier (EID). class VehicleIdentificationRequestEIDData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the VehicleIdentificationRequestEIDData class. - * - * This constructor initializes a `VehicleIdentificationRequestEIDData` instance with default values: - * - `eid` (Entity Identifier) is initialized to all zeros. - */ + /// @brief Default constructor for the VehicleIdentificationRequestEIDData class. + /// + /// This constructor initializes a `VehicleIdentificationRequestEIDData` instance with default values: + /// - `eid` (Entity Identifier) is initialized to all zeros. VehicleIdentificationRequestEIDData(); - std::array eid; /**< Electronic Identifier (EID). */ + std::array eid; /// < Electronic Identifier (EID). - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Vehicle Identification Request EID message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Vehicle Identification Request EID message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Vehicle Identification Request with EID data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Vehicle Identification Request with EID payload type. It extracts the EID field from the layer. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with EID - * data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method checks for null pointers and verifies that the payload type matches - * `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. Logs an error if the data is invalid. - * - * The following field is parsed: - * - `eid`: The EID (Extended Identifier), extracted as a byte array of length `DOIP_EID_LEN`. - */ + /// @brief Parses and initializes the Vehicle Identification Request with EID data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Vehicle Identification Request with EID payload type. It extracts the EID field from the layer. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with EID + /// data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method checks for null pointers and verifies that the payload type matches + /// `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. Logs an error if the data is invalid. + /// + /// The following field is parsed: + /// - `eid`: The EID (Extended Identifier), extracted as a byte array of length `DOIP_EID_LEN`. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class VehicleIdentificationRequestVINData - * @brief Represents a Vehicle Identification Request with VIN message in DoIP. - * - * This class encapsulates data for a Vehicle Identification Request message - * that includes the Vehicle Identification Number (VIN). - */ + /// @class VehicleIdentificationRequestVINData + /// @brief Represents a Vehicle Identification Request with VIN message in DoIP. + /// + /// This class encapsulates data for a Vehicle Identification Request message + /// that includes the Vehicle Identification Number (VIN). class VehicleIdentificationRequestVINData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the VehicleIdentificationRequestVINData class. - * - * This constructor initializes a `VehicleIdentificationRequestVINData` instance with default values: - * - `vin` (Vehicle Identification Number) is initialized to all zeros. - */ + /// @brief Default constructor for the VehicleIdentificationRequestVINData class. + /// + /// This constructor initializes a `VehicleIdentificationRequestVINData` instance with default values: + /// - `vin` (Vehicle Identification Number) is initialized to all zeros. VehicleIdentificationRequestVINData(); - std::array vin; /**< Vehicle Identification Number (VIN). */ + std::array vin; /// < Vehicle Identification Number (VIN). - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Vehicle Identification Request VIN message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Vehicle Identification Request VIN message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Vehicle Identification Request with VIN data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Vehicle Identification Request with VIN payload type. It extracts the VIN (Vehicle Identification Number) - * field from the payload data and populates the class instance. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with VIN - * data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. - * - Checks that the data length is sufficient to extract the VIN field. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following field is parsed: - * - `vin`: The Vehicle Identification Number (VIN), extracted as a byte array of length `DOIP_VIN_LEN`. - */ + /// @brief Parses and initializes the Vehicle Identification Request with VIN data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Vehicle Identification Request with VIN payload type. It extracts the VIN (Vehicle Identification Number) + /// field from the payload data and populates the class instance. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with VIN + /// data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. + /// - Checks that the data length is sufficient to extract the VIN field. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following field is parsed: + /// - `vin`: The Vehicle Identification Number (VIN), extracted as a byte array of length `DOIP_VIN_LEN`. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class VehicleAnnouncementData - * @brief Represents a Vehicle Announcement message in DoIP. - * - * This class encapsulates data for a Vehicle Announcement message, including - * VIN, logical address, EID, GID, and further action required. - */ + /// @class VehicleAnnouncementData + /// @brief Represents a Vehicle Announcement message in DoIP. + /// + /// This class encapsulates data for a Vehicle Announcement message, including + /// VIN, logical address, EID, GID, and further action required. class VehicleAnnouncementData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the VehicleAnnouncementData class. - * - * This constructor initializes a `VehicleAnnouncementData` instance with default values: - * - `vin` is initialized to all zeros. - * - `logicalAddress` is set to `0`. - * - `eid` (Entity Identifier) is initialized to all zeros. - * - `gid` (Group Identifier) is initialized to all zeros. - * - `furtherActionRequired` is set to `DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED`. - * - `syncStatus` is set to `DoIpSyncStatus::NON_INITIALIZED`, indicating that the sync status is uninitialized. - */ + /// @brief Default constructor for the VehicleAnnouncementData class. + /// + /// This constructor initializes a `VehicleAnnouncementData` instance with default values: + /// - `vin` is initialized to all zeros. + /// - `logicalAddress` is set to `0`. + /// - `eid` (Entity Identifier) is initialized to all zeros. + /// - `gid` (Group Identifier) is initialized to all zeros. + /// - `furtherActionRequired` is set to `DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED`. + /// - `syncStatus` is set to `DoIpSyncStatus::NON_INITIALIZED`, indicating that the sync status is + /// uninitialized. VehicleAnnouncementData(); - std::array vin; /**< Vehicle Identification Number (VIN). */ - uint16_t logicalAddress; /**< Logical address of the vehicle. */ - std::array eid; /**< Electronic Identifier (EID). */ - std::array gid; /**< Group Identifier (GID). */ - DoIpActionCodes furtherActionRequired; /**< Action required after the announcement. */ - DoIpSyncStatus syncStatus; /**< version and invert version are synchronized. */ - - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. - */ + std::array vin; /// < Vehicle Identification Number (VIN). + uint16_t logicalAddress; /// < Logical address of the vehicle. + std::array eid; /// < Electronic Identifier (EID). + std::array gid; /// < Group Identifier (GID). + DoIpActionCodes furtherActionRequired; /// < Action required after the announcement. + DoIpSyncStatus syncStatus; /// < version and invert version are synchronized. + + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Vehicle Announcement message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Vehicle Announcement message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Vehicle Announcement data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Announcement Message payload type. It extracts fields such as VIN, logical address, EID, GID, - * further action required, and synchronization status from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Announcement data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. - * - Checks that the data length is sufficient to extract all required fields. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following fields are parsed: - * - `vin`: Vehicle Identification Number (VIN). - * - `logicalAddress`: Logical address of the vehicle. - * - `eid`: End Identifier. - * - `gid`: Group Identifier. - * - `furtherActionRequired`: Further action required code. - * - `syncStatus`: VIN/GID synchronization status (if present). - */ + /// @brief Parses and initializes the Vehicle Announcement data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Announcement Message payload type. It extracts fields such as VIN, logical address, EID, GID, + /// further action required, and synchronization status from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Announcement data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. + /// - Checks that the data length is sufficient to extract all required fields. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following fields are parsed: + /// - `vin`: Vehicle Identification Number (VIN). + /// - `logicalAddress`: Logical address of the vehicle. + /// - `eid`: End Identifier. + /// - `gid`: Group Identifier. + /// - `furtherActionRequired`: Further action required code. + /// - `syncStatus`: VIN/GID synchronization status (if present). bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class AliveCheckResponseData - * @brief Represents an Alive Check Response message in DoIP. - * - * This class encapsulates data for an Alive Check Response message, - * including the source address. - */ + /// @class AliveCheckResponseData + /// @brief Represents an Alive Check Response message in DoIP. + /// + /// This class encapsulates data for an Alive Check Response message, + /// including the source address. class AliveCheckResponseData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the AliveCheckResponseData class. - * - * This constructor initializes an `AliveCheckResponseData` instance with default values: - * - `sourceAddress` is set to `0x0000`. - */ + /// @brief Default constructor for the AliveCheckResponseData class. + /// + /// This constructor initializes an `AliveCheckResponseData` instance with default values: + /// - `sourceAddress` is set to `0x0000`. AliveCheckResponseData(); - uint16_t sourceAddress; /**< Source address of the Alive Check Response message. */ + uint16_t sourceAddress; /// < Source address of the Alive Check Response message. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Alive Check Response message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Alive Check Response message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Alive Check Response data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Alive Check Response payload type. It extracts the `sourceAddress` field from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Alive Check Response data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. - * - Checks that the data length is sufficient to extract the `sourceAddress`. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following field is parsed: - * - `sourceAddress`: The source address of the response. - */ + /// @brief Parses and initializes the Alive Check Response data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Alive Check Response payload type. It extracts the `sourceAddress` field from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Alive Check Response data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. + /// - Checks that the data length is sufficient to extract the `sourceAddress`. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following field is parsed: + /// - `sourceAddress`: The source address of the response. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class DiagnosticPowerModeResponseData - * @brief Represents a Diagnostic Power Mode Response message in DoIP. - * - * This class encapsulates data for a Diagnostic Power Mode Response message, - * including a power mode code indicating the current power mode. - */ + /// @class DiagnosticPowerModeResponseData + /// @brief Represents a Diagnostic Power Mode Response message in DoIP. + /// + /// This class encapsulates data for a Diagnostic Power Mode Response message, + /// including a power mode code indicating the current power mode. class DiagnosticPowerModeResponseData : public IDoIpMessageData { public: - /** @brief Default constructor for the DiagnosticPowerModeResponseData class. - * - * Initializes a DiagnosticPowerModeResponseData instance with the power mode - * response code set to `NOT_READY`. This indicates that the system is not yet - * ready to respond to diagnostic power mode requests. - */ + /// @brief Default constructor for the DiagnosticPowerModeResponseData class. + /// + /// Initializes a DiagnosticPowerModeResponseData instance with the power mode + /// response code set to `NOT_READY`. This indicates that the system is not yet + /// ready to respond to diagnostic power mode requests. DiagnosticPowerModeResponseData(); - DoIpDiagnosticPowerModeCodes powerModeCode; /**< Code representing the power mode. */ + DoIpDiagnosticPowerModeCodes powerModeCode; /// < Code representing the power mode. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Diagnostic Power Mode Response message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Diagnostic Power Mode Response message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Diagnostic Power Mode Response data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Diagnostic Power Mode Response payload type. It extracts the `powerModeCode` field from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Power Mode Response data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. - * - Checks that the data length is sufficient to extract the `powerModeCode`. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following field is parsed: - * - `powerModeCode`: The diagnostic power mode response code. - */ + /// @brief Parses and initializes the Diagnostic Power Mode Response data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Diagnostic Power Mode Response payload type. It extracts the `powerModeCode` field from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Power Mode Response data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. + /// - Checks that the data length is sufficient to extract the `powerModeCode`. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following field is parsed: + /// - `powerModeCode`: The diagnostic power mode response code. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class EntityStatusResponseData - * @brief Represents an Entity Status Response message in DoIP. - * - * This class encapsulates data for an Entity Status Response message, - * including status, maximum concurrent sockets, open sockets, and maximum data size. - */ + /// @class EntityStatusResponseData + /// @brief Represents an Entity Status Response message in DoIP. + /// + /// This class encapsulates data for an Entity Status Response message, + /// including status, maximum concurrent sockets, open sockets, and maximum data size. class EntityStatusResponseData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the EntityStatusResponseData class. - * - * Initializes an `EntityStatusResponseData` instance with the following default values: - * - `status`: Set to `DoIpEntityStatus::GATEWAY`, indicating the entity is acting as a gateway. - * - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. - * - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. - * - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object creation. - * - * @code - * EntityStatusResponseData data; - * data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, - * 0x03}); - * @endcode - */ + /// @brief Default constructor for the EntityStatusResponseData class. + /// + /// Initializes an `EntityStatusResponseData` instance with the following default values: + /// - `status`: Set to `DoIpEntityStatus::GATEWAY`, indicating the entity is acting as a gateway. + /// - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. + /// - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. + /// - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object creation. + /// + /// @code + /// EntityStatusResponseData data; + /// data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, + /// 0x03}); + /// @endcode EntityStatusResponseData(); - DoIpEntityStatus nodeType; /**< Status of the entity. */ - uint8_t maxConcurrentSockets; /**< Maximum number of concurrent sockets. */ - uint8_t currentlyOpenSockets; /**< Number of currently open sockets. */ + DoIpEntityStatus nodeType; /// < Status of the entity. + uint8_t maxConcurrentSockets; /// < Maximum number of concurrent sockets. + uint8_t currentlyOpenSockets; /// < Number of currently open sockets. std::unique_ptr> - maxDataSize; /**< Maximum data size that can be handled (4 bytes optional). */ + maxDataSize; /// < Maximum data size that can be handled (4 bytes optional). - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Entity Status Response message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Entity Status Response message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Entity Status Response data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Entity Status Response payload type. It extracts fields such as `nodeType`, - * `maxConcurrentSockets`, `currentlyOpenSockets`, and optionally `maxDataSize` from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Entity Status Response data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. - * - Checks that the data length is sufficient for the fixed fields and optional `maxDataSize`. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following fields are parsed: - * - `nodeType`: Entity status indicating the role of the entity. - * - `maxConcurrentSockets`: Maximum allowed concurrent sockets. - * - `currentlyOpenSockets`: Number of currently open sockets. - * - `maxDataSize` (optional): Maximum data size supported (4 bytes). - */ + /// @brief Parses and initializes the Entity Status Response data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Entity Status Response payload type. It extracts fields such as `nodeType`, + /// `maxConcurrentSockets`, `currentlyOpenSockets`, and optionally `maxDataSize` from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Entity Status Response data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. + /// - Checks that the data length is sufficient for the fixed fields and optional `maxDataSize`. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following fields are parsed: + /// - `nodeType`: Entity status indicating the role of the entity. + /// - `maxConcurrentSockets`: Maximum allowed concurrent sockets. + /// - `currentlyOpenSockets`: Number of currently open sockets. + /// - `maxDataSize` (optional): Maximum data size supported (4 bytes). bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class DiagnosticMessageData - * @brief Represents a Diagnostic Message in DoIP. - * This class encapsulates data for a Diagnostic Message, including source - * and target addresses, as well as diagnostic data. - */ + /// @class DiagnosticMessageData + /// @brief Represents a Diagnostic Message in DoIP. + /// This class encapsulates data for a Diagnostic Message, including source + /// and target addresses, as well as diagnostic data. class DiagnosticMessageData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the DiagnosticMessageData class. - * - * Initializes a `DiagnosticMessageData` instance with the following default values: - * - `sourceAddress`: Set to `0x0000`. - * - `targetAddress`: Set to `0x0000`. - * - `diagnosticData`: Initialized to `{0x22, 0xf1, 0x68}` as a default diagnostic payload. - */ + /// @brief Default constructor for the DiagnosticMessageData class. + /// + /// Initializes a `DiagnosticMessageData` instance with the following default values: + /// - `sourceAddress`: Set to `0x0000`. + /// - `targetAddress`: Set to `0x0000`. + /// - `diagnosticData`: Initialized to `{0x22, 0xf1, 0x68}` as a default diagnostic payload. DiagnosticMessageData(); - uint16_t sourceAddress; /**< Source address of the message. */ - uint16_t targetAddress; /**< Target address for the diagnostic message. */ - std::vector diagnosticData; /**< Diagnostic message data with dynamic length. */ + uint16_t sourceAddress; /// < Source address of the message. + uint16_t targetAddress; /// < Target address for the diagnostic message. + std::vector diagnosticData; /// < Diagnostic message data with dynamic length. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Diagnostic Message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Diagnostic Message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Diagnostic Message data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Diagnostic Message payload type. It extracts fields such as `sourceAddress`, - * `targetAddress`, and `diagnosticData` from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Message data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. - * - Checks that the data length is sufficient for the fixed fields and dynamic `diagnosticData`. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following fields are parsed: - * - `sourceAddress`: Source address of the diagnostic message (2 bytes). - * - `targetAddress`: Target address of the diagnostic message (2 bytes). - * - `diagnosticData`: Variable length data representing the diagnostic payload. - */ + /// @brief Parses and initializes the Diagnostic Message data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Diagnostic Message payload type. It extracts fields such as `sourceAddress`, + /// `targetAddress`, and `diagnosticData` from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Message data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. + /// - Checks that the data length is sufficient for the fixed fields and dynamic `diagnosticData`. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following fields are parsed: + /// - `sourceAddress`: Source address of the diagnostic message (2 bytes). + /// - `targetAddress`: Target address of the diagnostic message (2 bytes). + /// - `diagnosticData`: Variable length data representing the diagnostic payload. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class DiagnosticAckMessageData - * @brief Represents a Diagnostic Acknowledgment Message in DoIP. - * - * This class encapsulates data for a Diagnostic Acknowledgment Message, - * including source and target addresses, as well as the acknowledgment code. - */ + /// @class DiagnosticAckMessageData + /// @brief Represents a Diagnostic Acknowledgment Message in DoIP. + /// + /// This class encapsulates data for a Diagnostic Acknowledgment Message, + /// including source and target addresses, as well as the acknowledgment code. class DiagnosticAckMessageData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the DiagnosticAckMessageData class. - * - * Initializes a `DiagnosticAckMessageData` instance with the following default values: - * - `sourceAddress`: Set to `0x0000`. - * - `targetAddress`: Set to `0x0000`. - * - `ackCode`: Set to `DoIpDiagnosticAckCodes::ACK`. - * - `previousMessage`: Initialized to `{0x22, 0xf1, 0x01, 0x02}`. - */ + /// @brief Default constructor for the DiagnosticAckMessageData class. + /// + /// Initializes a `DiagnosticAckMessageData` instance with the following default values: + /// - `sourceAddress`: Set to `0x0000`. + /// - `targetAddress`: Set to `0x0000`. + /// - `ackCode`: Set to `DoIpDiagnosticAckCodes::ACK`. + /// - `previousMessage`: Initialized to `{0x22, 0xf1, 0x01, 0x02}`. DiagnosticAckMessageData(); - uint16_t sourceAddress; /**< Source address of the acknowledgment message. */ - uint16_t targetAddress; /**< Target address of the acknowledgment message. */ - DoIpDiagnosticAckCodes ackCode; /**< Acknowledgment code. */ - std::vector previousMessage; /**< Previous acknowlged message. */ + uint16_t sourceAddress; /// < Source address of the acknowledgment message. + uint16_t targetAddress; /// < Target address of the acknowledgment message. + DoIpDiagnosticAckCodes ackCode; /// < Acknowledgment code. + std::vector previousMessage; /// < Previous acknowlged message. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Diagnostic Acknowledgment Message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Diagnostic Acknowledgment Message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Parses and initializes the Diagnostic Acknowledgment Message data from a DoIpLayer. - * - * This method validates the provided DoIpLayer to ensure it corresponds to the - * Diagnostic Acknowledgment Message payload type. It extracts fields such as `sourceAddress`, - * `targetAddress`, `ackCode`, and `previousMessage` from the payload data. - * - * @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Acknowledgment Message data. - * @return `true` if parsing and initialization were successful, `false` otherwise. - * - * @note The method performs the following checks: - * - Ensures the `doipLayer` is not null. - * - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. - * - Checks that the data length is sufficient for the fixed fields and the dynamic `previousMessage`. - * - * Logs errors if the data is invalid or the payload is incompatible. - * - * The following fields are parsed: - * - `sourceAddress`: Source address of the acknowledgment message (2 bytes). - * - `targetAddress`: Target address of the acknowledgment message (2 bytes). - * - `ackCode`: Acknowledgment code (1 byte, converted from enum). - * - `previousMessage`: std::vector representing the previous message. - */ + /// @brief Parses and initializes the Diagnostic Acknowledgment Message data from a DoIpLayer. + /// + /// This method validates the provided DoIpLayer to ensure it corresponds to the + /// Diagnostic Acknowledgment Message payload type. It extracts fields such as `sourceAddress`, + /// `targetAddress`, `ackCode`, and `previousMessage` from the payload data. + /// + /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Acknowledgment Message data. + /// @return `true` if parsing and initialization were successful, `false` otherwise. + /// + /// @note The method performs the following checks: + /// - Ensures the `doipLayer` is not null. + /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. + /// - Checks that the data length is sufficient for the fixed fields and the dynamic `previousMessage`. + /// + /// Logs errors if the data is invalid or the payload is incompatible. + /// + /// The following fields are parsed: + /// - `sourceAddress`: Source address of the acknowledgment message (2 bytes). + /// - `targetAddress`: Target address of the acknowledgment message (2 bytes). + /// - `ackCode`: Acknowledgment code (1 byte, converted from enum). + /// - `previousMessage`: std::vector representing the previous message. bool buildFromLayer(const DoIpLayer& doipLayer); }; - /** - * @class DiagnosticNackMessageData - * @brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. - * - * This class encapsulates data for a Diagnostic Negative Acknowledgment - * Message, including source and target addresses, as well as the NACK code. - */ + /// @class DiagnosticNackMessageData + /// @brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. + /// + /// This class encapsulates data for a Diagnostic Negative Acknowledgment + /// Message, including source and target addresses, as well as the NACK code. class DiagnosticNackMessageData : public IDoIpMessageData { public: - /** - * @brief Default constructor for the DiagnosticNackMessageData class. - * - * Initializes a `DiagnosticNackMessageData` instance with default values: - * - `sourceAddress` is set to `0x0000`. - * - `targetAddress` is set to `0x0000`. - * - `nackCode` is set to `DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS`. - * - `previousMessage` is set to {0x22, 0xf1, 01, 0x02} as the non acknowledged diagnostic - * message starts with these four bytes - */ + /// @brief Default constructor for the DiagnosticNackMessageData class. + /// + /// Initializes a `DiagnosticNackMessageData` instance with default values: + /// - `sourceAddress` is set to `0x0000`. + /// - `targetAddress` is set to `0x0000`. + /// - `nackCode` is set to `DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS`. + /// - `previousMessage` is set to {0x22, 0xf1, 01, 0x02} as the non acknowledged diagnostic + /// message starts with these four bytes DiagnosticNackMessageData(); - uint16_t sourceAddress; /**< Source address of the NACK message. */ - uint16_t targetAddress; /**< Target address of the NACK message. */ - DoIpDiagnosticMessageNackCodes nackCode; /**< Negative acknowledgment code. */ - std::vector previousMessage; /**< Previous acknowlged message. */ + uint16_t sourceAddress; /// < Source address of the NACK message. + uint16_t targetAddress; /// < Target address of the NACK message. + DoIpDiagnosticMessageNackCodes nackCode; /// < Negative acknowledgment code. + std::vector previousMessage; /// < Previous acknowlged message. - /** - * @brief Returns the type of the message. - * @return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. - */ + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. DoIpPayloadTypes getType() const override; - /** - * @brief Converts the message data to a human-readable string. - * @return A string representation of the Diagnostic Negative Acknowledgment Message. - */ + /// @brief Converts the message data to a human-readable string. + /// @return A string representation of the Diagnostic Negative Acknowledgment Message. std::string toString() const override; - /** - * @brief Retrieves the raw binary data of the message. - * @return A vector of bytes representing the message data. - */ + /// @brief Retrieves the raw binary data of the message. + /// @return A vector of bytes representing the message data. std::vector getData() const override; - /** - * @brief Builds the message data from the given DoIpLayer. - * - * This method parses the `DoIpLayer` to extract the relevant message data, including: - * - sourceAddress - * - targetAddress - * - nackCode - * - previousMessage (optional) - * - * @param doipLayer The layer containing the message data to be parsed. - * @return `true` if the message was successfully built from the layer, `false` otherwise. - */ + /// @brief Builds the message data from the given DoIpLayer. + /// + /// This method parses the `DoIpLayer` to extract the relevant message data, including: + /// - sourceAddress + /// - targetAddress + /// - nackCode + /// - previousMessage (optional) + /// + /// @param doipLayer The layer containing the message data to be parsed. + /// @return `true` if the message was successfully built from the layer, `false` otherwise. bool buildFromLayer(const DoIpLayer& doipLayer); }; } // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index ded3f0ab1b..4c6bb4dd6c 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -1,6 +1,7 @@ #define LOG_MODULE PacketLogModuleDoIpLayer #include "DoIpLayer.h" +#include "DoIpLayerData.h" #include "Packet.h" #include "PayloadLayer.h" #include "EndianPortable.h" @@ -17,24 +18,39 @@ namespace pcpp setInvertProtocolVersion(~(static_cast(version))); buildLayer(type, data); } + DoIpLayer::DoIpLayer() { VehicleAnnouncementData data; initLayer(); - setProtocolVersion(DoIpProtocolVersion::version03Iso2019); - setInvertProtocolVersion(~(static_cast(DoIpProtocolVersion::version03Iso2019))); + setProtocolVersion(DoIpProtocolVersion::Version02Iso2012); + setInvertProtocolVersion(~(static_cast(DoIpProtocolVersion::Version02Iso2012))); buildLayer(DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &data); } DoIpProtocolVersion DoIpLayer::getProtocolVersion() const { - return static_cast(getDoIpHeader()->protocolVersion); + uint8_t version = getDoIpHeader()->protocolVersion; + + switch (static_cast(version)) + { + case DoIpProtocolVersion::ReservedVersion: + case DoIpProtocolVersion::Version01Iso2010: + case DoIpProtocolVersion::Version02Iso2012: + case DoIpProtocolVersion::Version03Iso2019: + case DoIpProtocolVersion::Version04Iso2019_AMD1: + case DoIpProtocolVersion::DefaultVersion: + return static_cast(version); + + default: + return DoIpProtocolVersion::UnknownVersion; + } } std::string DoIpLayer::getProtocolVersionAsStr() const { - auto it = internal::DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); - if (it != internal::DoIpEnumToStringProtocolVersion.end()) + auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); + if (it != DoIpEnumToStringProtocolVersion.end()) { return it->second; } @@ -71,8 +87,8 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { - auto it = internal::DoIpEnumToStringPayloadType.find(getPayloadType()); - if (it != internal::DoIpEnumToStringPayloadType.end()) + auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); + if (it != DoIpEnumToStringPayloadType.end()) { return it->second; } @@ -87,24 +103,22 @@ namespace pcpp return htobe32(getDoIpHeader()->payloadLength); } - void DoIpLayer::setPayloadLength(uint32_t Payloadength) + void DoIpLayer::setPayloadLength(uint32_t payloadLength) const { - getDoIpHeader()->payloadLength = be32toh(Payloadength); + getDoIpHeader()->payloadLength = be32toh(payloadLength); } - bool DoIpLayer::resolveProtocolVersion() const + bool DoIpLayer::isProtocolVersionValid() const { DoIpProtocolVersion version = getProtocolVersion(); uint8_t inVersion = getInvertProtocolVersion(); DoIpPayloadTypes type = getPayloadType(); - // Idea is token from wireshark - if (!(version == DoIpProtocolVersion::version01Iso2010 || version == DoIpProtocolVersion::version02Iso2012 || - version == DoIpProtocolVersion::version03Iso2019 || - version == DoIpProtocolVersion::version04Iso2019_AMD1 || - (version == DoIpProtocolVersion::defaultVersion && - (type >= DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST && - type <= DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN)))) + if ((version == DoIpProtocolVersion::UnknownVersion) || (version == DoIpProtocolVersion::ReservedVersion) || + (version == DoIpProtocolVersion::DefaultVersion && + (type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST))) { PCPP_LOG_ERROR("Invalid/unsupported DoIP version!"); return false; @@ -117,16 +131,10 @@ namespace pcpp return true; } - bool DoIpLayer::resolvePayloadLength() const + bool DoIpLayer::isPayloadLengthValid() const { uint32_t length = getPayloadLength(); - if (m_DataLen < sizeof(doiphdr)) - { - PCPP_LOG_ERROR("Payload length is smaller than the minimum header size"); - return false; - } - if (length != (m_DataLen - sizeof(doiphdr))) { PCPP_LOG_ERROR("Payload length does not match expected size"); @@ -135,10 +143,11 @@ namespace pcpp return true; } - bool DoIpLayer::resolveLayer() const + + bool DoIpLayer::isLayerDataValid() const { // Validate the protocol version and payload length - if (!resolveProtocolVersion() || !resolvePayloadLength()) + if (!isProtocolVersionValid() || !isPayloadLengthValid()) { PCPP_LOG_ERROR("Failed to Parse DoIP layer"); return false; @@ -148,7 +157,7 @@ namespace pcpp std::string DoIpLayer::toString() const { - if (!resolveLayer()) + if (!isLayerDataValid()) { return "Malformed doip Packet"; } diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 2262489388..a9fa089dc6 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -1,13 +1,200 @@ #include "DoIpLayerData.h" #include "DoIpLayer.h" -/// @file +#include "GeneralUtils.h" -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ namespace pcpp { + /// @brief Mapping of DoIP Protocol Versions to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each version of the + /// DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values + /// to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringProtocolVersion{ + { DoIpProtocolVersion::DefaultVersion, "Default value for vehicle identification request messages" }, + { DoIpProtocolVersion::Version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, + { DoIpProtocolVersion::Version02Iso2012, "DoIP ISO 13400-2:2012" }, + { DoIpProtocolVersion::Version03Iso2019, "DoIP ISO 13400-2:2019" }, + { DoIpProtocolVersion::Version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, + { DoIpProtocolVersion::ReservedVersion, "Reserved" }, + }; + + /// @brief Mapping of DoIP Payload Types to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each payload type + /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values + /// to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringPayloadType{ + { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, + { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, + "Vehicle announcement message / vehicle identification response message" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, + { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, + { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, + { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, + { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } + }; + + /// @brief Mapping of DoIP Activation Types to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each activation type + /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values + /// to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringActivationTypes{ + { DoIpActivationTypes::Default, "Default" }, + { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, + { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, + }; + + /// @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each Nack code related to + /// the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum + /// values to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ + { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, + { DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, + { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, + { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, + { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, + }; + + /// @brief Mapping of DoIP Action Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each action code related to + /// the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum + /// values to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringActionCodes{ + { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, + { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } + }; + + /// @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each routing response code + /// related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` + /// enum values to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ + { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, "Routing activation denied due to unknown source address" }, + { DoIpRoutingResponseCodes::NO_FREE_SOCKET, + "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, + { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, + "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, + { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, + "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, + { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, "Routing activation denied due to missing authentication" }, + { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, "Routing activation denied due to rejected confirmation" }, + { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, + "Routing activation denied due to unsupported routing activation type" }, + { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, + "Routing activation denied due to request for encrypted connection via TLS" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, + { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } + }; + + /// @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code + /// related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum + /// values to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, + { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, + { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, + { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, + { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, + { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, + { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, + }; + + /// @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each power mode code + /// related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum + /// values to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ + { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, + { DoIpDiagnosticPowerModeCodes::READY, "ready" }, + { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, + }; + + /// @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for the entity status codes + /// in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values + /// to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." + const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatus::NODE, "DoIp node" }, + { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, + }; + + /// @brief Mapping of DoIP Acknowledgement Codes to their string representations. + /// + /// This unordered map provides a human-readable description for the DoIP acknowledgement + /// code `ACK`, which is used to confirm the successful reception or processing of a message. + const std::unordered_map DoIpEnumToStringAckCode{ + { DoIpDiagnosticAckCodes::ACK, "ACK" }, + }; + + /// @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. + /// + /// This unordered map provides a human-readable string for each synchronization status + /// defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status + /// values to their respective descriptions for logging or display purposes. + const std::unordered_map DoIpEnumToStringSyncStatus{ + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, + { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, + { DoIpSyncStatus::NON_INITIALIZED, "NULL" } + }; + RoutingActivationRequestData::RoutingActivationRequestData() : sourceAddress(0x0000), activationType(DoIpActivationTypes::Default), reservedIso{}, reservedOem(nullptr) {}; @@ -20,8 +207,8 @@ namespace pcpp { std::stringstream os; os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = internal::DoIpEnumToStringActivationTypes.find(activationType); - if (it != internal::DoIpEnumToStringActivationTypes.end()) + auto it = DoIpEnumToStringActivationTypes.find(activationType); + if (it != DoIpEnumToStringActivationTypes.end()) { os << "activation type: " << it->second << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; } @@ -110,8 +297,8 @@ namespace pcpp os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) << "\n"; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = internal::DoIpEnumToStringRoutingResponseCodes.find(responseCode); - if (it != internal::DoIpEnumToStringRoutingResponseCodes.end()) + auto it = DoIpEnumToStringRoutingResponseCodes.find(responseCode); + if (it != DoIpEnumToStringRoutingResponseCodes.end()) { os << "routing activation response code: " << it->second << std::hex << " (0x" << unsigned(responseCode) << ")" << "\n"; @@ -204,8 +391,8 @@ namespace pcpp std::string GenericHeaderNackData::toString() const { std::stringstream os; - auto it = internal::DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); - if (it != internal::DoIpEnumToStringGenericHeaderNackCodes.end()) + auto it = DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); + if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) { os << "generic header nack code: " << it->second << std::hex << " (0x" << unsigned(genericNackCode) << ")" << "\n"; @@ -353,8 +540,8 @@ namespace pcpp os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << "\n"; os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << "\n"; - auto it = internal::DoIpEnumToStringActionCodes.find(furtherActionRequired); - if (it != internal::DoIpEnumToStringActionCodes.end()) + auto it = DoIpEnumToStringActionCodes.find(furtherActionRequired); + if (it != DoIpEnumToStringActionCodes.end()) { os << "further action required:" << it->second << std::hex << " (0x" << unsigned(furtherActionRequired) << ")" << "\n"; @@ -365,8 +552,8 @@ namespace pcpp << "\n"; } - auto it_ = internal::DoIpEnumToStringSyncStatus.find(syncStatus); - if (it_ != internal::DoIpEnumToStringSyncStatus.end()) + auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); + if (it_ != DoIpEnumToStringSyncStatus.end()) { os << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte } @@ -508,8 +695,8 @@ namespace pcpp std::string DiagnosticPowerModeResponseData::toString() const { std::stringstream os; - auto it = internal::DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); - if (it != internal::DoIpEnumToStringDiagnosticPowerModeCodes.end()) + auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); + if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) { os << "diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(powerModeCode) << ")" << "\n"; @@ -566,8 +753,8 @@ namespace pcpp std::string EntityStatusResponseData::toString() const { std::stringstream os; - auto it = internal::DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); - if (it != internal::DoIpEnumToStringEntityStatusNodeTypes.end()) + auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); + if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) { os << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; } @@ -637,7 +824,8 @@ namespace pcpp } else { - maxDataSize = nullptr; // Optional field not present + // Optional field not present + maxDataSize = nullptr; } return true; @@ -721,8 +909,8 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = internal::DoIpEnumToStringAckCode.find(ackCode); - if (it != internal::DoIpEnumToStringAckCode.end()) + auto it = DoIpEnumToStringAckCode.find(ackCode); + if (it != DoIpEnumToStringAckCode.end()) { os << "ack code: " << it->second << " (0x" << unsigned(ackCode) << ")" << "\n"; } @@ -794,7 +982,7 @@ namespace pcpp } else { - previousMessage.clear(); // Ensure previousMessage is empty when not provided + previousMessage.clear(); } return true; } @@ -813,8 +1001,8 @@ namespace pcpp std::stringstream os; os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = internal::DoIpEnumToStringDiagnosticNackCodes.find(nackCode); - if (it != internal::DoIpEnumToStringDiagnosticNackCodes.end()) + auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); + if (it != DoIpEnumToStringDiagnosticNackCodes.end()) { os << "nack code: " << it->second << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; } @@ -886,7 +1074,8 @@ namespace pcpp } else { - previousMessage.clear(); // Ensure previousMessage is empty when not provided + // Ensure previousMessage is empty when not provided + previousMessage.clear(); } return true; diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWithDefaultVersPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWithDefaultVersPacket.dat new file mode 100644 index 0000000000..aefe1474f0 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWithDefaultVersPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff14345800108988ff00000100000000 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index 7cb9d555f7..e00d0c2fbd 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -92,6 +92,7 @@ PTF_TEST_CASE(DnsLayerAddDnsKeyTest); PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing); PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation); PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing); PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation); PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing); PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index f1a61d78c4..53a52dac44 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -10,7 +10,7 @@ #include "SystemUtils.h" #include "PacketUtils.h" #include "DeprecationUtils.h" -#include "DoIpLayer.h" +#include "DoIpLayerData.h" #include // ------------------ @@ -47,7 +47,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); @@ -73,8 +73,8 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; pcpp::GenericHeaderNackData data; - data.genericNackCode = pcpp::DoIpGenericHeaderNackCodes::INKNOWN_PAYLOAD_TYPE; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + data.genericNackCode = pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, &data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -88,7 +88,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Generic DOIP header Nack"); @@ -122,8 +122,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) pcpp::DoIpLayer* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); @@ -152,7 +152,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) // vehIdentificationRequestArgs.args = std::monostate{}; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -160,7 +160,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); @@ -205,7 +205,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, enumclass); @@ -239,7 +239,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) pcpp::VehicleIdentificationRequestVINData withVin; withVin.vin = vin; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withVin); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -249,7 +249,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 25), bytes, 25); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, enumclass); @@ -295,7 +295,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, enumclass); @@ -327,7 +327,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) pcpp::VehicleIdentificationRequestEIDData withEID; withEID.eid = eid; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withEID); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -341,7 +341,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (56 - 14), bytes, 14); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, enumclass); @@ -389,7 +389,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), @@ -431,7 +431,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) ann.syncStatus = pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED; ann.furtherActionRequired = pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &ann); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -445,7 +445,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), @@ -492,7 +492,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) pcpp::RoutingActivationResponseData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); @@ -525,7 +525,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; routingData.reservedOem = std::unique_ptr>(new std::array()); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, &routingData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -539,7 +539,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation request"); @@ -583,7 +583,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); @@ -617,7 +617,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; routingData.reservedOem = std::unique_ptr>(new std::array()); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, &routingData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -631,7 +631,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation response"); @@ -664,7 +664,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) pcpp::DoIpLayer* doipLayer = AliveCheckRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); @@ -690,7 +690,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -704,7 +704,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); @@ -747,7 +747,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); @@ -773,7 +773,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0 }; pcpp::AliveCheckResponseData aliveCheckRespData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, &aliveCheckRespData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -787,7 +787,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check response"); @@ -820,7 +820,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) pcpp::DoIpLayer* doipLayer = EntityStatusRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); @@ -845,7 +845,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -859,7 +859,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); @@ -903,7 +903,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); @@ -933,7 +933,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) entityResponseData.maxConcurrentSockets = 2; entityResponseData.maxDataSize = std::unique_ptr>(new std::array{ 0x0, 0x0, 0xf, 0xff }); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, &entityResponseData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -947,7 +947,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); @@ -980,7 +980,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) pcpp::DoIpLayer* doipLayer = PowerModeRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); @@ -1005,7 +1005,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -1019,7 +1019,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); @@ -1061,7 +1061,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); @@ -1088,7 +1088,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0 }; pcpp::DiagnosticPowerModeResponseData data; data.powerModeCode = pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, &data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -1102,7 +1102,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode response information"); @@ -1144,7 +1144,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); @@ -1175,7 +1175,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) data.sourceAddress = be16toh(0x0e80); data.targetAddress = be16toh(0x4010); data.diagnosticData = diagnosticData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, &data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -1189,7 +1189,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message"); @@ -1233,7 +1233,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); @@ -1266,7 +1266,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) // dont use previous message data.previousMessage.clear(); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, &data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -1280,7 +1280,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Ack"); @@ -1324,7 +1324,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); @@ -1357,7 +1357,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) // dont use previous message data.previousMessage.clear(); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::version02Iso2012, + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, &data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); @@ -1367,7 +1367,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Nack"); @@ -1376,4 +1376,40 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) _doipLayer2->toString(), "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 5\n"); } +// DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestWithDefaultVersPacket.dat"); + + pcpp::Packet vehicleIdentificationRequest(&rawPacket1); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8988)); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x10)); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::DefaultVersion, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0x00); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); + PTF_ASSERT_EQUAL( + doipLayer->toString(), + "DOIP Layer:\nProtocol Version: Default value for vehicle identification request messages (0xff)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); + +} // DoIpVehicleIdentificationRequestPacketParsing DISABLE_WARNING_POP diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 4e467dccd6..dd09300dc5 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -190,6 +190,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DoIpGenericHeaderNackPacketParsing, "doip"); PTF_RUN_TEST(DoIpGenericHeaderNackPacketCreation, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketCreation, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketParsing, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketCreation, "doip"); From d2204c0b52e149ebc8ed00e372a9c3c360576c97 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 30 Mar 2025 04:59:27 -0400 Subject: [PATCH 21/43] . Reply on 1655#pullrequestreview-2707929155 . Move DoIpEnumToStringPayloadType, DoIpEnumToStringProtocolVersion maps to DoIpLayer.cpp . Remove serializeData (...) funct and use memcpy . Make buildLayer private . Improve getPayloadType() func . Add test for invalid paylaodType . Reduce toString() presentation --- Packet++/header/DoIpLayer.h | 48 +++-- Packet++/src/DoIpLayer.cpp | 122 +++++++++---- Packet++/src/DoIpLayerData.cpp | 39 ---- .../DoIpInvalidPayloadTypePacket.dat | 1 + Tests/Packet++Test/TestDefinition.h | 1 + Tests/Packet++Test/Tests/DoIpTests.cpp | 168 +++++++----------- Tests/Packet++Test/main.cpp | 1 + 7 files changed, 176 insertions(+), 204 deletions(-) create mode 100644 Tests/Packet++Test/PacketExamples/DoIpInvalidPayloadTypePacket.dat diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index d450b96490..9e73b9add8 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -16,12 +16,6 @@ namespace pcpp { class IDoIpMessageData; - enum class DoIpPayloadTypes : uint16_t; - enum class DoIpProtocolVersion : uint8_t; - - extern const std::unordered_map DoIpEnumToStringPayloadType; - extern const std::unordered_map DoIpEnumToStringProtocolVersion; - /// @brief Represents the DoIP (Diagnostics over IP) protocol versions. enum class DoIpProtocolVersion : uint8_t { @@ -45,7 +39,8 @@ namespace pcpp /// Used for broadcast Vehicle Identification Request Messages. DefaultVersion = 0xFFU, - /// @brief Represents an unknown or unsupported protocol version + /// Represents an unknown or unsupported protocol version (not specified by ISO). + /// Used to indicate an unsupported or unknown protocol version for internal handling. UnknownVersion = 0xEF }; @@ -134,6 +129,10 @@ namespace pcpp /// Diagnostic message negative acknowledgment. /// Indicates an error in processing a diagnostic message. DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U, + + /// Represents an invalid payload type (not specified by ISO). + /// Used to indicate an unsupported or unrecognized payload type for internal handling. + UNKNOWN_PAYLOAD_TYPE = 0xFFFFU, }; /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). @@ -580,11 +579,6 @@ namespace pcpp /// @param[in] length the doip payload length to set void setPayloadLength(uint32_t length) const; - /// copy data from msgFields to dest - /// @param[in] dest pointer to where start copying - /// @param[in] data the doip Fields to copy - void serializeData(uint8_t* dest, std::vector data); - /// A static method that checks whether a port is considered as a DOIP port /// @param[in] port The port number to check /// @return True if this is a DOIP port number, false otherwise @@ -596,21 +590,6 @@ namespace pcpp /// @return True if the data is valid and can represent an DOIP layer static inline bool isDataValid(const uint8_t* data, size_t dataLen); - /// @brief Builds the DoIP layer based on the payload type and provided data. - /// - /// This function configures the DoIP layer with the appropriate payload type, payload length, - /// and data, depending on the specified payload type. If the payload type does not require - /// additional data, the payload length is set to zero. For payloads that require data, the data - /// is serialized and added to the layer. - /// - /// @param type The DoIP payload type to set for this layer. - /// @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. - /// This parameter can be nullptr for payload types that do not require additional data. - /// - /// @note If the payload type requires data and the `data` parameter is `nullptr`, an error message - /// is logged, and the function does not build the layer. - void buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); - /// @brief Resolves and validates the DoIP layer. /// /// This function validates the protocol version and payload length of the DoIP layer. @@ -662,6 +641,21 @@ namespace pcpp /// Check the integrity of protocol version in doip header /// @return true if version has no integration errors bool isProtocolVersionValid() const; + + /// @brief Builds the DoIP layer based on the payload type and provided data. + /// + /// This function configures the DoIP layer with the appropriate payload type, payload length, + /// and data, depending on the specified payload type. If the payload type does not require + /// additional data, the payload length is set to zero. For payloads that require data, the data + /// is serialized and added to the layer. + /// + /// @param type The DoIP payload type to set for this layer. + /// @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. + /// This parameter can be nullptr for payload types that do not require additional data. + /// + /// @note If the payload type requires data and the `data` parameter is `nullptr`, an error message + /// is logged, and the function does not build the layer. + void buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); }; // inline methods definition diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 4c6bb4dd6c..d1cfbb07b7 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -11,6 +11,47 @@ namespace pcpp { + /// @brief Mapping of DoIP Protocol Versions to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each version of the + /// DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values + /// to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringProtocolVersion{ + { DoIpProtocolVersion::DefaultVersion, "Default value for vehicle identification request messages" }, + { DoIpProtocolVersion::Version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, + { DoIpProtocolVersion::Version02Iso2012, "DoIP ISO 13400-2:2012" }, + { DoIpProtocolVersion::Version03Iso2019, "DoIP ISO 13400-2:2019" }, + { DoIpProtocolVersion::Version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, + { DoIpProtocolVersion::ReservedVersion, "Reserved" }, + { DoIpProtocolVersion::UnknownVersion, "Unknown Protocol Version" } + }; + + /// @brief Mapping of DoIP Payload Types to their respective string descriptions. + /// + /// This unordered map provides human-readable descriptions for each payload type + /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values + /// to their corresponding descriptions. + const std::unordered_map DoIpEnumToStringPayloadType{ + { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, + { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, + { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, + "Vehicle announcement message / vehicle identification response message" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, + { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, + { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, + { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, + { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, + { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, + { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" }, + { DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" } + }; + DoIpLayer::DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data) { initLayer(); @@ -50,14 +91,7 @@ namespace pcpp std::string DoIpLayer::getProtocolVersionAsStr() const { auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); - if (it != DoIpEnumToStringProtocolVersion.end()) - { - return it->second; - } - else - { - return "Unknown Protocol Version"; - } + return it->second; } void DoIpLayer::setProtocolVersion(DoIpProtocolVersion version) @@ -77,7 +111,29 @@ namespace pcpp DoIpPayloadTypes DoIpLayer::getPayloadType() const { - return static_cast(be16toh(getDoIpHeader()->payloadType)); + switch (static_cast(be16toh(getDoIpHeader()->payloadType))) + { + case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: + case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: + case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: + case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: + case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: + case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: + case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: + case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: + return static_cast(be16toh(getDoIpHeader()->payloadType)); + + default: + return DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE; + } } void DoIpLayer::setPayloadType(DoIpPayloadTypes type) @@ -88,14 +144,7 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); - if (it != DoIpEnumToStringPayloadType.end()) - { - return it->second; - } - else - { - return "Unknown Payload type"; - } + return it->second; } uint32_t DoIpLayer::getPayloadLength() const @@ -159,28 +208,21 @@ namespace pcpp { if (!isLayerDataValid()) { - return "Malformed doip Packet"; + return "Malformed DoIP packet"; } - std::stringstream os; - DoIpProtocolVersion version = getProtocolVersion(); + + std::ostringstream os; DoIpPayloadTypes type = getPayloadType(); - uint32_t length = getPayloadLength(); - os << "DOIP Layer:" << "\n"; - os << "Protocol Version: " << getProtocolVersionAsStr() << std::hex << " (0x" << unsigned((uint8_t)version) - << ")" << "\n"; - os << "Payload Type: " << getPayloadTypeAsStr() << std::hex << " (0x" << std::setw(4) << std::setfill('0') - << (uint16_t)type << ")" << "\n"; - os << std::dec << "Payload Length: " << length << "\n"; + os << "DOIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') + << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE + ? static_cast(be16toh(getDoIpHeader()->payloadType)) + : static_cast(type)) + << ")"; return os.str(); } - void DoIpLayer::serializeData(uint8_t* dest, std::vector data) - { - memcpy(dest, data.data(), data.size()); - } - void DoIpLayer::initLayer() { m_DataLen = sizeof(doiphdr); @@ -213,7 +255,7 @@ namespace pcpp setPayloadType(data->getType()); setPayloadLength(payloadSize); extendLayer(headerLength, payloadSize); - serializeData(m_Data + headerLength, data->getData()); + memcpy(m_Data + headerLength, data->getData().data(), payloadSize); break; } } @@ -221,12 +263,16 @@ namespace pcpp void DoIpLayer::parseNextLayer() { - DiagnosticMessageData diagnosticMessage; - if (diagnosticMessage.buildFromLayer(*this)) + if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) { - // handle UDS layer as generic PayloadLayer for now. - m_NextLayer = new PayloadLayer(diagnosticMessage.diagnosticData.data(), - diagnosticMessage.diagnosticData.size(), this, m_Packet); + size_t headerLen = sizeof(doiphdr); + + if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/) + return; + + uint8_t* payload = m_Data + (headerLen + 2 + 2); + size_t payloadLen = m_DataLen - (headerLen + 2 + 2); + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } } } // namespace pcpp diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index a9fa089dc6..9ec47146a8 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -4,45 +4,6 @@ namespace pcpp { - /// @brief Mapping of DoIP Protocol Versions to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each version of the - /// DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values - /// to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringProtocolVersion{ - { DoIpProtocolVersion::DefaultVersion, "Default value for vehicle identification request messages" }, - { DoIpProtocolVersion::Version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, - { DoIpProtocolVersion::Version02Iso2012, "DoIP ISO 13400-2:2012" }, - { DoIpProtocolVersion::Version03Iso2019, "DoIP ISO 13400-2:2019" }, - { DoIpProtocolVersion::Version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, - { DoIpProtocolVersion::ReservedVersion, "Reserved" }, - }; - - /// @brief Mapping of DoIP Payload Types to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each payload type - /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values - /// to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringPayloadType{ - { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, - { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, "Vehicle identification request with VIN" }, - { DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, - "Vehicle announcement message / vehicle identification response message" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, "Routing activation request" }, - { DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, "Routing activation response" }, - { DoIpPayloadTypes::ALIVE_CHECK_REQUEST, "Alive check request" }, - { DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, "Alive check response" }, - { DoIpPayloadTypes::ENTITY_STATUS_REQUEST, "DOIP entity status request" }, - { DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, "DOIP entity status response" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, "Diagnostic power mode request information" }, - { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } - }; - /// @brief Mapping of DoIP Activation Types to their respective string descriptions. /// /// This unordered map provides human-readable descriptions for each activation type diff --git a/Tests/Packet++Test/PacketExamples/DoIpInvalidPayloadTypePacket.dat b/Tests/Packet++Test/PacketExamples/DoIpInvalidPayloadTypePacket.dat new file mode 100644 index 0000000000..75afeb52dd --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpInvalidPayloadTypePacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac150800450000240001000040113aeea9fe75efa9fe75eeff1434580010898202fd777700000000 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index d1c246b65f..239bcf8b13 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -122,6 +122,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing); PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation); PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing); PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation); +PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing); // Implemented in IcmpTests.cpp PTF_TEST_CASE(IcmpParsingTest); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 53a52dac44..47243888d4 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -52,9 +52,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0000)\nPayload Length: 1\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Generic DOIP header Nack (0x0000)") } PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) @@ -93,9 +91,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Generic DOIP header Nack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Generic DOIP header Nack (0x0000)\nPayload Length: 1\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Generic DOIP header Nack (0x0000)") } // DoIpVehicleIdentificationRequestPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) @@ -127,9 +123,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); } // DoIpVehicleIdentificationRequestPacketParsing @@ -164,9 +158,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); } // VehicleIdentificationWithVIN @@ -211,9 +203,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x0003)\nPayload Length: 17\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request with VIN (0x0003)") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -255,9 +245,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 17); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with VIN (0x0003)\nPayload Length: 17\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request with VIN (0x0003)") } // VehicleIdentificationWithEID PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) @@ -301,9 +289,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x0002)\nPayload Length: 6\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request with EID (0x0002)") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -347,9 +333,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle identification request with EID (0x0002)\nPayload Length: 6\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request with EID (0x0002)") } // VehicleAnnouncement PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) @@ -395,9 +379,8 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle announcement message / vehicle identification response message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 32); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x0004)\nPayload Length: 32\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), + "DOIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") } // DoIpVehicleAnnouncementPacketParsing @@ -451,9 +434,8 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle announcement message / vehicle identification response message"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 33); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Vehicle announcement message / vehicle identification response message (0x0004)\nPayload Length: 33\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), + "DOIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") } // RoutingActivationRequest PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) @@ -497,9 +479,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x0005)\nPayload Length: 11\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Routing activation request (0x0005)") } PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) @@ -544,9 +524,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 11); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation request (0x0005)\nPayload Length: 11\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Routing activation request (0x0005)") } // RoutingActivationResponse PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) @@ -588,9 +566,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x0006)\nPayload Length: 9\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Routing activation response (0x0006)") } PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) @@ -636,9 +612,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 13); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Routing activation response (0x0006)\nPayload Length: 13\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Routing activation response (0x0006)") } // --------------- // AliveCheckRequestPacket @@ -669,9 +643,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x0007)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Alive check request (0x0007)") } PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) @@ -709,9 +681,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check request (0x0007)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Alive check request (0x0007)") } // --------------- // AliveCheckResponsePacket @@ -752,9 +722,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x0008)\nPayload Length: 2\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Alive check response (0x0008)") } PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) @@ -792,9 +760,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 2); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Alive check response (0x0008)\nPayload Length: 2\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Alive check response (0x0008)") } // ------------------ // EntityStatusRequestPacket @@ -825,9 +791,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status request (0x4001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, DOIP entity status request (0x4001)") } PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) @@ -864,9 +828,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status request (0x4001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, DOIP entity status request (0x4001)") } // ------------------ // EntityStatusResponsePacket @@ -908,9 +870,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status response (0x4002)\nPayload Length: 7\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, DOIP entity status response (0x4002)") } PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) @@ -952,9 +912,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: DOIP entity status response (0x4002)\nPayload Length: 7\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, DOIP entity status response (0x4002)") } // ------------------ // PowerModeRequestPacket @@ -985,9 +943,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode request information (0x4003)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic power mode request information (0x4003)") } PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) @@ -1024,9 +980,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode request information (0x4003)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic power mode request information (0x4003)") } // ------------------ // PowerModeResponsePacket @@ -1066,9 +1020,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode response information (0x4004)\nPayload Length: 1\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic power mode response information (0x4004)") } PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) @@ -1107,9 +1059,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode response information"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic power mode response information (0x4004)\nPayload Length: 1\n") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic power mode response information (0x4004)") } // ------------------ // DiagnosticMessagePacket @@ -1149,9 +1099,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 6); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message (0x8001)\nPayload Length: 6\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message (0x8001)") } PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) @@ -1194,9 +1142,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message (0x8001)\nPayload Length: 6\n"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message (0x8001)"); } // ------------------ // DiagnosticAckMessagePacket @@ -1238,9 +1184,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 8\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message Ack (0x8002)") } PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) @@ -1285,9 +1229,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Ack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Ack (0x8002)\nPayload Length: 5\n"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message Ack (0x8002)"); } // ------------------ // DiagnosticNackMessagePacket @@ -1329,9 +1271,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 8\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message Nack (0x8003)") } PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) @@ -1372,9 +1312,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Nack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL( - _doipLayer2->toString(), - "DOIP Layer:\nProtocol Version: DoIP ISO 13400-2:2012 (0x2)\nPayload Type: Diagnostic message Nack (0x8003)\nPayload Length: 5\n"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message Nack (0x8003)"); } // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) @@ -1406,10 +1344,40 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0x00); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL( - doipLayer->toString(), - "DOIP Layer:\nProtocol Version: Default value for vehicle identification request messages (0xff)\nPayload Type: Vehicle identification request (0x0001)\nPayload Length: 0\n") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); -} // DoIpVehicleIdentificationRequestPacketParsing +} // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing + +// DoIpInvalidPayloadTypePacketPacketParsing +PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpInvalidPayloadTypePacket.dat"); + + pcpp::Packet InvalidPayloadTypePacket(&rawPacket1); + PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = InvalidPayloadTypePacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + + // DOIP fields for vehicle identification request + pcpp::DoIpLayer* doipLayer = InvalidPayloadTypePacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xfd); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Unknown payload type"); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Unknown payload type (0x7777)"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); + +} // DoIpInvalidPayloadTypePacketParsing DISABLE_WARNING_POP diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 4aab519f65..37e34c9d1e 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -220,6 +220,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DoIpDiagnosticAckMessagePacketCreation, "doip"); PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketParsing, "doip"); PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketCreation, "doip"); + PTF_RUN_TEST(DoIpInvalidPayloadTypePacketParsing, "doip"); PTF_RUN_TEST(IcmpParsingTest, "icmp"); PTF_RUN_TEST(IcmpCreationTest, "icmp"); From 1453f8a92d83a75bdbee934380babbbd65a85620 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 30 Mar 2025 05:30:25 -0400 Subject: [PATCH 22/43] fix clang format in ProtocolType.h --- Packet++/header/ProtocolType.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index 7dd113d13c..1e76e3b42c 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -220,7 +220,7 @@ namespace pcpp /// Cisco HDLC protocol const ProtocolType CiscoHDLC = 58; - /// Diagnostic over IP protocol (DOIP) + /// Diagnostic over IP protocol (DOIP) const ProtocolType DOIP = 59; /// An enum representing OSI model layers From 05e147e48a04ff5ce133d7360c47dffc930e9f23 Mon Sep 17 00:00:00 2001 From: Raissi Oussama <80215516+raissi-oussema@users.noreply.github.com> Date: Sat, 29 Mar 2025 22:55:53 -0400 Subject: [PATCH 23/43] Update ProtocolType.h --- Packet++/header/ProtocolType.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index 1e76e3b42c..976808d127 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -220,7 +220,7 @@ namespace pcpp /// Cisco HDLC protocol const ProtocolType CiscoHDLC = 58; - /// Diagnostic over IP protocol (DOIP) + /// Diagnostic over IP protocol (DOIP) const ProtocolType DOIP = 59; /// An enum representing OSI model layers From 47e2e16508b1025979c8323eca036d4893efdb9e Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Mon, 31 Mar 2025 02:35:47 -0400 Subject: [PATCH 24/43] try fix clang format --- Packet++/header/ProtocolType.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index 976808d127..6a828c7d84 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -220,7 +220,7 @@ namespace pcpp /// Cisco HDLC protocol const ProtocolType CiscoHDLC = 58; - /// Diagnostic over IP protocol (DOIP) + /// Diagnostic over IP protocol (DOIP) const ProtocolType DOIP = 59; /// An enum representing OSI model layers From c205897f54bffcca061b1782f925ed1b5f95a03b Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 8 Apr 2025 01:32:46 -0400 Subject: [PATCH 25/43] serval fixes --- Packet++/header/DoIpLayer.h | 389 +-------------------- Packet++/header/DoIpLayerData.h | 459 +++++++++++++++++++++++++ Packet++/src/DoIpLayer.cpp | 52 +-- Packet++/src/DoIpLayerData.cpp | 146 +++++++- Tests/Packet++Test/Tests/DoIpTests.cpp | 195 +++-------- 5 files changed, 680 insertions(+), 561 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 9e73b9add8..26383ec48f 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -1,9 +1,6 @@ #pragma once -#include -#include #include "Layer.h" -#include "PayloadLayer.h" #include "IpAddress.h" #include "MacAddress.h" #include "Logger.h" @@ -44,23 +41,6 @@ namespace pcpp UnknownVersion = 0xEF }; - /// @brief Enum representing DoIP routing activation types. - /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). - enum class DoIpActivationTypes : uint8_t - { - /// Default routing activation type. - /// Used when no specific type is required. - Default = 0x00U, - - /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. - /// Used for vehicle diagnostics in compliance with WWH-OBD standards. - WWH_OBD = 0x01U, - - /// Central security routing activation type. - /// Used for secure communications involving a central security system. - CENTRAL_SECURITY = 0xE0U - }; - /// @brief Enum representing DoIP payload types. /// These payload types are defined as part of theDoIP(Diagnostic over IP) protocol /// and specify the type of message being transmitted. @@ -135,347 +115,6 @@ namespace pcpp UNKNOWN_PAYLOAD_TYPE = 0xFFFFU, }; - /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). - /// These codes are used to indicate specific errors in the DoIP Generic Header. - enum class DoIpGenericHeaderNackCodes : uint8_t - { - /// Incorrect pattern detected in the header. - /// Indicates that the header does not follow the expected pattern. - INCORRECT_PATTERN = 0x00U, - - /// Unknown payload type. - /// The payload type in the message is not recognized. - UNKNOWN_PAYLOAD_TYPE = 0x01U, - - /// Message too large. - /// The message size exceeds the allowed limit. - MESSAGE_TOO_LARGE = 0x02U, - - /// Out of memory. - /// There is insufficient memory available to process the message. - OUT_OF_MEMORY = 0x03U, - - /// Invalid payload length. - /// The payload length specified in the header is invalid. - INVALID_PAYLOAD_LENGTH = 0x04U, - }; - - /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). - /// These action codes specify the next steps required after receiving a DoIP announcement message. - /// Some codes are reserved for future use by ISO standards. - enum class DoIpActionCodes : uint8_t - { - - /// No further action required. - /// Indicates that no additional steps are needed after the announcement. - NO_FURTHER_ACTION_REQUIRED = 0x00U, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Reserved for ISO (0x02). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x02 = 0x02U, - - /// Reserved for ISO (0x03). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x03 = 0x03U, - - /// Reserved for ISO (0x04). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x04 = 0x04U, - - /// Reserved for ISO (0x05). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x05 = 0x05U, - - /// Reserved for ISO (0x06). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x06 = 0x06U, - - /// Reserved for ISO (0x07). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x07 = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x0F). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// Routing activation required. - /// Indicates that routing activation is needed after the announcement message. - ROUTING_ACTIVATION_REQUIRED = 0x10U, - }; - - /// @brief Enum representing DoIP routing activation response codes (ISO 13400). - /// These codes are used in response to routing activation requests, providing status - /// or error information related to the request. - enum class DoIpRoutingResponseCodes : uint8_t - { - /// Unknown source address. - /// The source address provided in the request is not recognized. - UNKNOWN_SOURCE_ADDRESS = 0x00U, - - /// No free socket. - /// There are no available sockets to establish the connection. - NO_FREE_SOCKET = 0x01U, - - /// Wrong source address. - /// The source address provided in the request is invalid. - WRONG_SOURCE_ADDRESS = 0x02U, - - /// Source address already registered. - /// The provided source address has already been activated. - SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, - - /// Missing authentication. - /// The request is missing required authentication credentials. - MISSING_AUTHENTICATION = 0x04U, - - /// Rejected confirmation. - /// The confirmation of routing activation was rejected. - REJECTED_CONFIRMATION = 0x05U, - - /// Unsupported activation type. - /// The requested routing activation type is not supported. - - UNSUPPORTED_ACTIVATION_TYPE = 0x06U, - - /// Encrypted connection required(TLS). - /// Indicates that the routing activation requires a secure TLS connection. - ENCRYPTED_CONNECTION_TLS = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x0F). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// Routing successfully activated. - /// The routing activation request was processed successfully. - ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, - - /// Confirmation required. - /// Additional confirmation is required to complete the routing activation. - CONFIRMATION_REQUIRED = 0x11U, - }; - - /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). - /// These codes indicate reasons for rejecting or failing to process a diagnostic message - /// in the DoIP protocol. - enum class DoIpDiagnosticMessageNackCodes : uint8_t - { - - /// Reserved for ISO (0x00). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x00 = 0x00U, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Invalid source address. - /// The source address specified in the message is invalid. - INVALID_SOURCE_ADDRESS = 0x02U, - - /// Invalid target address. - /// The target address specified in the message is invalid. - INVALID_TARGET_ADDRESS = 0x03U, - - /// Message too large. - /// The size of the message exceeds the maximum allowed limit. - MESSAGE_TOO_LARGE = 0x04U, - - /// Out of memory. - /// There is insufficient memory available to process the message. - OUT_OF_MEMORY = 0x05U, - - /// Target unreachable. - /// The specified target address cannot be reached. - TARGET_UNREACHABLE = 0x06U, - - /// Unknown network. - /// The message references a network that is not recognized or supported. - UNKNOWN_NETWORK = 0x07U, - - /// Transport protocol error. - /// An error occurred at the transport protocol level, preventing the message from being processed. - TRANSPORT_PROTOCOL_ERROR = 0x08U, - }; - - /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). - /// These codes indicate the diagnostic power mode status of a DoIP entity, - /// providing information about its readiness for diagnostic operations. - enum class DoIpDiagnosticPowerModeCodes : uint8_t - { - - /// Not ready. - /// The DoIP entity is not ready to perform diagnostic operations. - NOT_READY = 0x00U, - - /// Ready. - /// The DoIP entity is ready to perform diagnostic operations. - READY = 0x01U, - - /// Not supported. - /// The DoIP entity does not support diagnostic power mode reporting. - NOT_SUPPORTED = 0x02U - }; - - /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). - /// These codes are used to acknowledge the receipt or processing of diagnostic messages - /// in the DoIP protocol. - enum class DoIpDiagnosticAckCodes : uint8_t - { - - /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. - - ACK = 0x00U - }; - - /// @brief Enum representing DoIP entity status response codes (ISO 13400). - /// These codes are used to indicate the role or type of a DoIP entity in the network. - enum class DoIpEntityStatus : uint8_t - { - /// Gateway. - /// The entity functions as a gateway, - /// facilitating communication between networks. - GATEWAY = 0x00U, - - /// Node. - /// The entity functions as an individual node within the DoIP network. - NODE = 0x01U - }; - - /// @brief Enum representing DoIP sync status (ISO 13400). - /// These codes are used to indicate whether GID and VIN are synchronized or not. - enum class DoIpSyncStatus : uint8_t - { - - /// VIN and or GID are synchronized. - VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Reserved for ISO (0x02). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x02 = 0x02U, - - /// Reserved for ISO (0x03). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x03 = 0x03U, - - /// Reserved for ISO (0x04). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x04 = 0x04U, - - /// Reserved for ISO (0x05). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x05 = 0x05U, - - /// Reserved for ISO (0x06). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x06 = 0x06U, - - /// Reserved for ISO (0x07). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x07 = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// VIN and or GID are not synchronized. - VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, - - /// Check whether this field is initialised or not - NON_INITIALIZED - }; - /// @brief Enum representing DoIP diagnostic ports (ISO 13400). /// These ports are used for communication in the DoIP protocol over different transport layers. @@ -528,16 +167,15 @@ namespace pcpp /// A constructor that creates an generic doip layer and set header and payload fields /// @param[in] version DoIpProtocolVersion specify the doip protocol version - /// @param[in] type DoIpPayloadTypes indicating the doip payload type /// @param[in] data IDoIpMessageData contains all doipMessage specification based on its payload type - DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); + DoIpLayer(DoIpProtocolVersion version, const IDoIpMessageData& data); /// A constructor that create a doip announcement message with all /// zeros for vin, eid, gid and no further action required DoIpLayer(); /// A destructor for DoIpLayer class - virtual ~DoIpLayer() override = default; + ~DoIpLayer() override = default; /// Get the version of DOIP protocol /// @return DoIpProtocolVersion presenting the used protocol version (DOIPV) @@ -623,39 +261,18 @@ namespace pcpp } private: - /// init doip layer with all zeros with size of doip header. void initLayer(); - /// Get a pointer to the DoIP header. Notice this points directly to the data, so every change will change the - /// actual packet data - /// @return A pointer to the @ref doiphdr doiphdr* getDoIpHeader() const { return reinterpret_cast(m_Data); } - /// Check the integrity of length field in doip header - /// @return true if length represent the exact payload arg struct size bool isPayloadLengthValid() const; - /// Check the integrity of protocol version in doip header - /// @return true if version has no integration errors bool isProtocolVersionValid() const; - /// @brief Builds the DoIP layer based on the payload type and provided data. - /// - /// This function configures the DoIP layer with the appropriate payload type, payload length, - /// and data, depending on the specified payload type. If the payload type does not require - /// additional data, the payload length is set to zero. For payloads that require data, the data - /// is serialized and added to the layer. - /// - /// @param type The DoIP payload type to set for this layer. - /// @param data Pointer to the message data (of type IDoIpMessageData) to be serialized into the layer. - /// This parameter can be nullptr for payload types that do not require additional data. - /// - /// @note If the payload type requires data and the `data` parameter is `nullptr`, an error message - /// is logged, and the function does not build the layer. - void buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data = nullptr); + void buildLayer(const IDoIpMessageData& data); }; // inline methods definition diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index aabc0eaaa7..31cddf3320 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -27,6 +27,363 @@ namespace pcpp /// @brief Length of the Reserved OEM field. #define DOIP_RESERVED_OEM_LEN 4 + /// @brief Enum representing DoIP routing activation types. + /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). + enum class DoIpActivationTypes : uint8_t + { + /// Default routing activation type. + /// Used when no specific type is required. + Default = 0x00U, + + /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. + /// Used for vehicle diagnostics in compliance with WWH-OBD standards. + WWH_OBD = 0x01U, + + /// Central security routing activation type. + /// Used for secure communications involving a central security system. + CENTRAL_SECURITY = 0xE0U + }; + + /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). + /// These codes are used to indicate specific errors in the DoIP Generic Header. + enum class DoIpGenericHeaderNackCodes : uint8_t + { + /// Incorrect pattern detected in the header. + /// Indicates that the header does not follow the expected pattern. + INCORRECT_PATTERN = 0x00U, + + /// Unknown payload type. + /// The payload type in the message is not recognized. + UNKNOWN_PAYLOAD_TYPE = 0x01U, + + /// Message too large. + /// The message size exceeds the allowed limit. + MESSAGE_TOO_LARGE = 0x02U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x03U, + + /// Invalid payload length. + /// The payload length specified in the header is invalid. + INVALID_PAYLOAD_LENGTH = 0x04U, + }; + + /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). + /// These action codes specify the next steps required after receiving a DoIP announcement message. + /// Some codes are reserved for future use by ISO standards. + enum class DoIpActionCodes : uint8_t + { + + /// No further action required. + /// Indicates that no additional steps are needed after the announcement. + NO_FURTHER_ACTION_REQUIRED = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing activation required. + /// Indicates that routing activation is needed after the announcement message. + ROUTING_ACTIVATION_REQUIRED = 0x10U, + }; + + /// @brief Enum representing DoIP routing activation response codes (ISO 13400). + /// These codes are used in response to routing activation requests, providing status + /// or error information related to the request. + enum class DoIpRoutingResponseCodes : uint8_t + { + /// Unknown source address. + /// The source address provided in the request is not recognized. + UNKNOWN_SOURCE_ADDRESS = 0x00U, + + /// No free socket. + /// There are no available sockets to establish the connection. + NO_FREE_SOCKET = 0x01U, + + /// Wrong source address. + /// The source address provided in the request is invalid. + WRONG_SOURCE_ADDRESS = 0x02U, + + /// Source address already registered. + /// The provided source address has already been activated. + SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, + + /// Missing authentication. + /// The request is missing required authentication credentials. + MISSING_AUTHENTICATION = 0x04U, + + /// Rejected confirmation. + /// The confirmation of routing activation was rejected. + REJECTED_CONFIRMATION = 0x05U, + + /// Unsupported activation type. + /// The requested routing activation type is not supported. + + UNSUPPORTED_ACTIVATION_TYPE = 0x06U, + + /// Encrypted connection required(TLS). + /// Indicates that the routing activation requires a secure TLS connection. + ENCRYPTED_CONNECTION_TLS = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing successfully activated. + /// The routing activation request was processed successfully. + ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, + + /// Confirmation required. + /// Additional confirmation is required to complete the routing activation. + CONFIRMATION_REQUIRED = 0x11U, + }; + + /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). + /// These codes indicate reasons for rejecting or failing to process a diagnostic message + /// in the DoIP protocol. + enum class DoIpDiagnosticMessageNackCodes : uint8_t + { + + /// Reserved for ISO (0x00). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x00 = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Invalid source address. + /// The source address specified in the message is invalid. + INVALID_SOURCE_ADDRESS = 0x02U, + + /// Invalid target address. + /// The target address specified in the message is invalid. + INVALID_TARGET_ADDRESS = 0x03U, + + /// Message too large. + /// The size of the message exceeds the maximum allowed limit. + MESSAGE_TOO_LARGE = 0x04U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x05U, + + /// Target unreachable. + /// The specified target address cannot be reached. + TARGET_UNREACHABLE = 0x06U, + + /// Unknown network. + /// The message references a network that is not recognized or supported. + UNKNOWN_NETWORK = 0x07U, + + /// Transport protocol error. + /// An error occurred at the transport protocol level, preventing the message from being processed. + TRANSPORT_PROTOCOL_ERROR = 0x08U, + }; + + /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). + /// These codes indicate the diagnostic power mode status of a DoIP entity, + /// providing information about its readiness for diagnostic operations. + enum class DoIpDiagnosticPowerModeCodes : uint8_t + { + + /// Not ready. + /// The DoIP entity is not ready to perform diagnostic operations. + NOT_READY = 0x00U, + + /// Ready. + /// The DoIP entity is ready to perform diagnostic operations. + READY = 0x01U, + + /// Not supported. + /// The DoIP entity does not support diagnostic power mode reporting. + NOT_SUPPORTED = 0x02U + }; + + /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). + /// These codes are used to acknowledge the receipt or processing of diagnostic messages + /// in the DoIP protocol. + enum class DoIpDiagnosticAckCodes : uint8_t + { + + /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. + + ACK = 0x00U + }; + + /// @brief Enum representing DoIP entity status response codes (ISO 13400). + /// These codes are used to indicate the role or type of a DoIP entity in the network. + enum class DoIpEntityStatus : uint8_t + { + /// Gateway. + /// The entity functions as a gateway, + /// facilitating communication between networks. + GATEWAY = 0x00U, + + /// Node. + /// The entity functions as an individual node within the DoIP network. + NODE = 0x01U + }; + + /// @brief Enum representing DoIP sync status (ISO 13400). + /// These codes are used to indicate whether GID and VIN are synchronized or not. + enum class DoIpSyncStatus : uint8_t + { + + /// VIN and or GID are synchronized. + VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// VIN and or GID are not synchronized. + VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, + + /// Check whether this field is initialised or not + NON_INITIALIZED + }; /// @brief A pure abstract class representing the basic structure of DoIP messages. /// @@ -678,4 +1035,106 @@ namespace pcpp /// @return `true` if the message was successfully built from the layer, `false` otherwise. bool buildFromLayer(const DoIpLayer& doipLayer); }; + + /// @class AliveCheckRequestData + /// @brief Represents an alive check request in DoIP. + class AliveCheckRequestData : public IDoIpMessageData + { + public: + /// @brief Default constructor for the AliveCheckRequestData class. + /// + /// Initializes a `AliveCheckRequestData` instance + /// ensuring compliance with the DoIP protocol requirements. + AliveCheckRequestData(); + + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ALIVE_CHECK_REQUEST`. + DoIpPayloadTypes getType() const override; + + /// @brief Converts the message data to a human-readable string. + /// @return An empty string because Alive check request message has no additional data. + std::string toString() const override; + + /// @brief Retrieves the raw binary data of the message. + /// @return An empty vector of bytes representing the message data. + std::vector getData() const override; + + /// @brief Builds the message data from the given DoIpLayer. + bool buildFromLayer(const DoIpLayer& doipLayer); + }; + + class EntityStatusRequestData : public IDoIpMessageData + { + public: + /// @brief Default constructor for the AliveCheckRequestData class. + /// + /// Initializes a `EntityStatusRequestData` instance + /// ensuring compliance with the DoIP protocol requirements. + EntityStatusRequestData(); + + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::ENTITY_STATUS_REQUEST`. + DoIpPayloadTypes getType() const override; + + /// @brief Converts the message data to a human-readable string. + /// @return An empty string because the Alive check request message has no additional data. + std::string toString() const override; + + /// @brief Retrieves the raw binary data of the message. + /// @return An empty vector of bytes representing the message data. + std::vector getData() const override; + + /// @brief Builds the message data from the given DoIpLayer. + bool buildFromLayer(const DoIpLayer& doipLayer); + }; + + class DiagnosticPowerModeRequestData : public IDoIpMessageData + { + public: + /// @brief Default constructor for the AliveCheckRequestData class. + /// + /// Initializes a `DiagnosticPowerModeRequestData` instance + /// ensuring compliance with the DoIP protocol requirements. + DiagnosticPowerModeRequestData(); + + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST`. + DoIpPayloadTypes getType() const override; + + /// @brief Converts the message data to a human-readable string. + /// @return An empty string because Alive check request message has no additional data. + std::string toString() const override; + + /// @brief Retrieves the raw binary data of the message. + /// @return An empty vector of bytes representing the message data. + std::vector getData() const override; + + /// @brief Builds the message data from the given DoIpLayer. + bool buildFromLayer(const DoIpLayer& doipLayer); + }; + + class VehicleIdentificationRequestData : public IDoIpMessageData + { + public: + /// @brief Default constructor for the VehicleIdentificationRequestData class. + /// + /// Initializes a `VehicleIdentificationRequest` instance + /// ensuring compliance with the DoIP protocol requirements. + VehicleIdentificationRequestData(); + + /// @brief Returns the type of the message. + /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST`. + DoIpPayloadTypes getType() const override; + + /// @brief Converts the message data to a human-readable string. + /// @return An empty string because Vehicle identification request message has no additional data. + std::string toString() const override; + + /// @brief Retrieves the raw binary data of the message. + /// @return An empty vector of bytes representing the message data. + std::vector getData() const override; + + /// @brief Builds the message data from the given DoIpLayer. + bool buildFromLayer(const DoIpLayer& doipLayer); + }; } // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index d1cfbb07b7..a36bddcf3a 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -5,6 +5,7 @@ #include "Packet.h" #include "PayloadLayer.h" #include "EndianPortable.h" +#include #include #include #include @@ -52,12 +53,12 @@ namespace pcpp { DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" } }; - DoIpLayer::DoIpLayer(DoIpProtocolVersion version, DoIpPayloadTypes type, const IDoIpMessageData* data) + DoIpLayer::DoIpLayer(DoIpProtocolVersion version, const IDoIpMessageData& data) { initLayer(); setProtocolVersion(version); setInvertProtocolVersion(~(static_cast(version))); - buildLayer(type, data); + buildLayer(data); } DoIpLayer::DoIpLayer() @@ -66,7 +67,7 @@ namespace pcpp initLayer(); setProtocolVersion(DoIpProtocolVersion::Version02Iso2012); setInvertProtocolVersion(~(static_cast(DoIpProtocolVersion::Version02Iso2012))); - buildLayer(DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &data); + buildLayer(data); } DoIpProtocolVersion DoIpLayer::getProtocolVersion() const @@ -208,16 +209,15 @@ namespace pcpp { if (!isLayerDataValid()) { - return "Malformed DoIP packet"; + return "DoIP Layer, malformed data"; } std::ostringstream os; DoIpPayloadTypes type = getPayloadType(); - os << "DOIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') - << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE - ? static_cast(be16toh(getDoIpHeader()->payloadType)) - : static_cast(type)) + os << "DoIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') + << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE ? (be16toh(getDoIpHeader()->payloadType)) + : static_cast(type)) << ")"; return os.str(); @@ -230,35 +230,15 @@ namespace pcpp m_Data = new uint8_t[m_DataLen]{}; } - void DoIpLayer::buildLayer(DoIpPayloadTypes type, const IDoIpMessageData* data) + void DoIpLayer::buildLayer(const IDoIpMessageData& data) { - switch (type) - { - case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: - case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: - case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: - case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: - setPayloadType(type); - setPayloadLength(0); - break; - default: - // Payload handling for rest of types - { - if (data == nullptr) - { - PCPP_LOG_ERROR("Cannot build Layer with empty Data"); - break; - } - size_t payloadSize = data->getData().size(); - size_t headerLength = sizeof(doiphdr); - - setPayloadType(data->getType()); - setPayloadLength(payloadSize); - extendLayer(headerLength, payloadSize); - memcpy(m_Data + headerLength, data->getData().data(), payloadSize); - break; - } - } + size_t payloadSize = data.getData().size(); + size_t headerLength = sizeof(doiphdr); + + setPayloadType(data.getType()); + setPayloadLength(payloadSize); + extendLayer(headerLength, payloadSize); + memcpy(m_Data + headerLength, data.getData().data(), payloadSize); } void DoIpLayer::parseNextLayer() diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp index 9ec47146a8..a01f24ad6b 100644 --- a/Packet++/src/DoIpLayerData.cpp +++ b/Packet++/src/DoIpLayerData.cpp @@ -1,7 +1,7 @@ #include "DoIpLayerData.h" #include "DoIpLayer.h" #include "GeneralUtils.h" - +#include namespace pcpp { /// @brief Mapping of DoIP Activation Types to their respective string descriptions. @@ -1042,4 +1042,148 @@ namespace pcpp return true; } + // Alive check request functions definitions + AliveCheckRequestData::AliveCheckRequestData() + {} + + DoIpPayloadTypes AliveCheckRequestData::getType() const + { + return DoIpPayloadTypes::ALIVE_CHECK_REQUEST; + } + std::string AliveCheckRequestData::toString() const + { + return {}; + } + + std::vector AliveCheckRequestData::getData() const + { + return {}; + } + + bool AliveCheckRequestData::buildFromLayer(const DoIpLayer& doipLayer) + { + + if (doipLayer.getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot build Alive check request Message data from " + doipLayer.getPayloadTypeAsStr()); + return false; + } + + if (doipLayer.getDataLen() != sizeof(doiphdr)) + { + PCPP_LOG_ERROR("Alive check request Message has no additional data"); + return false; + } + return true; + } + + // Entity status request functions definitions + EntityStatusRequestData::EntityStatusRequestData() + {} + + DoIpPayloadTypes EntityStatusRequestData::getType() const + { + return DoIpPayloadTypes::ENTITY_STATUS_REQUEST; + } + + std::string EntityStatusRequestData::toString() const + { + return {}; + } + + std::vector EntityStatusRequestData::getData() const + { + return {}; + } + + bool EntityStatusRequestData::buildFromLayer(const DoIpLayer& doipLayer) + { + + if (doipLayer.getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot build Entity status request message data from " + doipLayer.getPayloadTypeAsStr()); + return false; + } + + if (doipLayer.getDataLen() != sizeof(doiphdr)) + { + PCPP_LOG_ERROR("Entity status request message has no additional data"); + return false; + } + return true; + } + + // diagnostic power mode request functions definitions + DiagnosticPowerModeRequestData::DiagnosticPowerModeRequestData() + {} + + DoIpPayloadTypes DiagnosticPowerModeRequestData::getType() const + { + return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST; + } + + std::string DiagnosticPowerModeRequestData::toString() const + { + return {}; + } + + std::vector DiagnosticPowerModeRequestData::getData() const + { + return {}; + } + + bool DiagnosticPowerModeRequestData::buildFromLayer(const DoIpLayer& doipLayer) + { + + if (doipLayer.getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot build diagnostic power mode request message data from " + + doipLayer.getPayloadTypeAsStr()); + return false; + } + + if (doipLayer.getDataLen() != sizeof(doiphdr)) + { + PCPP_LOG_ERROR("diagnostic power mode request message has no additional data"); + return false; + } + return true; + } + + // Vehicle identification request functions definitions + VehicleIdentificationRequestData::VehicleIdentificationRequestData() + {} + + DoIpPayloadTypes VehicleIdentificationRequestData::getType() const + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST; + } + + std::string VehicleIdentificationRequestData::toString() const + { + return {}; + } + + std::vector VehicleIdentificationRequestData::getData() const + { + return {}; + } + + bool VehicleIdentificationRequestData::buildFromLayer(const DoIpLayer& doipLayer) + { + + if (doipLayer.getPayloadType() != getType()) + { + PCPP_LOG_ERROR("Cannot build vehicle identification request message data from " + + doipLayer.getPayloadTypeAsStr()); + return false; + } + + if (doipLayer.getDataLen() != sizeof(doiphdr)) + { + PCPP_LOG_ERROR("Vehicle identification request message has no additional data"); + return false; + } + return true; + } } // namespace pcpp diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 47243888d4..6280401a8f 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -52,7 +52,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Generic DOIP header Nack (0x0000)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)") } PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) @@ -72,16 +72,11 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; pcpp::GenericHeaderNackData data; data.genericNackCode = pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, &data); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -91,7 +86,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Generic DOIP header Nack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Generic DOIP header Nack (0x0000)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)") } // DoIpVehicleIdentificationRequestPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) @@ -123,7 +118,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); } // DoIpVehicleIdentificationRequestPacketParsing @@ -144,10 +139,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; - // vehIdentificationRequestArgs.args = std::monostate{}; - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST); + pcpp::VehicleIdentificationRequestData req; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); @@ -158,7 +151,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); } // VehicleIdentificationWithVIN @@ -203,7 +196,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request with VIN (0x0003)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -229,8 +222,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) pcpp::VehicleIdentificationRequestVINData withVin; withVin.vin = vin; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withVin); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, withVin); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); @@ -245,7 +237,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 17); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request with VIN (0x0003)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)") } // VehicleIdentificationWithEID PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) @@ -289,7 +281,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request with EID (0x0002)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)") } // DoIpVehicleIdentificationRequestVINPacketParsing @@ -313,16 +305,11 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) pcpp::VehicleIdentificationRequestEIDData withEID; withEID.eid = eid; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, &withEID); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, withEID); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 56); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (56 - 14), bytes, 14); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -333,7 +320,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Vehicle identification request with EID (0x0002)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)") } // VehicleAnnouncement PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) @@ -364,11 +351,9 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) // build doipData from existent layer pcpp::VehicleAnnouncementData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "VIN: BAUNEE4MZ17042403\nlogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nfurther action required:No further action required (0x0)\nVIN/GID sync status: NULL\n"); - // wrong build pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -380,8 +365,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) "Vehicle announcement message / vehicle identification response message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 32); PTF_ASSERT_EQUAL(doipLayer->toString(), - "DOIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") - + "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") } // DoIpVehicleAnnouncementPacketParsing PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) @@ -414,16 +398,11 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) ann.syncStatus = pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED; ann.furtherActionRequired = pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, &ann); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, ann); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 83); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -435,12 +414,13 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) "Vehicle announcement message / vehicle identification response message"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 33); PTF_ASSERT_EQUAL(_doipLayer2->toString(), - "DOIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") + "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") } + // RoutingActivationRequest PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) { - // Dissect Vehicle Announcement message + // Dissect Routing Activation Request message timeval time; gettimeofday(&time, nullptr); @@ -464,12 +444,9 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) // build doipData from existent layer pcpp::RoutingActivationRequestData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL( data.toString(), "sourceAddress: 0xe80\nactivation type: Default (0x0)\nreserved by ISO: 00000000\nReserved by OEM: 00000000\n"); - // wrong build pcpp::RoutingActivationResponseData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -479,7 +456,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Routing activation request (0x0005)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation request (0x0005)") } PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) @@ -505,16 +482,11 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; routingData.reservedOem = std::unique_ptr>(new std::array()); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, &routingData); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, routingData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -524,12 +496,12 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 11); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Routing activation request (0x0005)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Routing activation request (0x0005)") } // RoutingActivationResponse PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) { - // Dissect Vehicle Announcement message + // Dissect Routing Activation Response message timeval time; gettimeofday(&time, nullptr); @@ -552,11 +524,9 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) pcpp::RoutingActivationResponseData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "logical address of external tester: 0xe80\nsource address: 0x4010\nrouting activation response code: Routing successfully activated (0x10)\nreserved by ISO: 00000000\n"); - // wrong build pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -566,7 +536,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Routing activation response (0x0006)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation response (0x0006)") } PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) @@ -593,16 +563,11 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; routingData.reservedOem = std::unique_ptr>(new std::array()); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, &routingData); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, routingData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 75); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -612,7 +577,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 13); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Routing activation response (0x0006)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Routing activation response (0x0006)") } // --------------- // AliveCheckRequestPacket @@ -643,7 +608,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Alive check request (0x0007)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check request (0x0007)") } PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) @@ -661,17 +626,12 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST); + pcpp::AliveCheckRequestData req; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -681,7 +641,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Alive check request (0x0007)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check request (0x0007)") } // --------------- // AliveCheckResponsePacket @@ -722,7 +682,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Alive check response (0x0008)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check response (0x0008)") } PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) @@ -741,16 +701,11 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0 }; pcpp::AliveCheckResponseData aliveCheckRespData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, &aliveCheckRespData); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, aliveCheckRespData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 52); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -760,7 +715,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 2); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Alive check response (0x0008)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check response (0x0008)") } // ------------------ // EntityStatusRequestPacket @@ -791,7 +746,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, DOIP entity status request (0x4001)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status request (0x4001)") } PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) @@ -809,16 +764,12 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST); + pcpp::EntityStatusRequestData req; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -828,7 +779,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, DOIP entity status request (0x4001)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status request (0x4001)") } // ------------------ // EntityStatusResponsePacket @@ -870,7 +821,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, DOIP entity status response (0x4002)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status response (0x4002)") } PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) @@ -893,16 +844,11 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) entityResponseData.maxConcurrentSockets = 2; entityResponseData.maxDataSize = std::unique_ptr>(new std::array{ 0x0, 0x0, 0xf, 0xff }); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, &entityResponseData); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, entityResponseData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 57); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -912,7 +858,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, DOIP entity status response (0x4002)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status response (0x4002)") } // ------------------ // PowerModeRequestPacket @@ -943,7 +889,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic power mode request information (0x4003)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") } PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) @@ -961,16 +907,12 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST); + pcpp::DiagnosticPowerModeRequestData req; + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -980,7 +922,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic power mode request information (0x4003)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") } // ------------------ // PowerModeResponsePacket @@ -1001,16 +943,13 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - // PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x2e2a)); pcpp::DoIpLayer* doipLayer = PowerModeResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); pcpp::DiagnosticPowerModeResponseData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "diagnostic power mode: not ready (0x0)\n"); - // wrong build pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -1020,7 +959,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic power mode response information (0x4004)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)") } PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) @@ -1040,16 +979,11 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0 }; pcpp::DiagnosticPowerModeResponseData data; data.powerModeCode = pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, &data); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -1059,7 +993,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode response information"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic power mode response information (0x4004)") + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)") } // ------------------ // DiagnosticMessagePacket @@ -1087,9 +1021,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) pcpp::DiagnosticMessageData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); PTF_ASSERT_EQUAL(data.toString(), "source address: 0xe80\ntarget address: 0x4010\n"); - // wrong build pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -1099,7 +1031,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message (0x8001)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message (0x8001)") } PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) @@ -1123,16 +1055,11 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) data.sourceAddress = be16toh(0x0e80); data.targetAddress = be16toh(0x4010); data.diagnosticData = diagnosticData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, &data); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 68); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -1142,7 +1069,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message (0x8001)"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message (0x8001)"); } // ------------------ // DiagnosticAckMessagePacket @@ -1170,11 +1097,9 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) pcpp::DiagnosticAckMessageData data; if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); PTF_ASSERT_EQUAL( data.toString(), "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\nprevious message: 22f101\n"); - // wrong build pcpp::RoutingActivationRequestData routingData; PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); @@ -1184,7 +1109,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message Ack (0x8002)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)") } PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) @@ -1210,16 +1135,11 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) // dont use previous message data.previousMessage.clear(); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, &data); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // std::endl; - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); @@ -1229,7 +1149,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Ack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message Ack (0x8002)"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)"); } // ------------------ // DiagnosticNackMessagePacket @@ -1271,7 +1191,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Diagnostic message Nack (0x8003)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Nack (0x8003)") } PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) @@ -1297,8 +1217,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) // dont use previous message data.previousMessage.clear(); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, - pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, &data); + pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); doIpPacket.computeCalculateFields(); @@ -1312,7 +1231,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Nack"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DOIP Layer, Diagnostic message Nack (0x8003)"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message Nack (0x8003)"); } // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) @@ -1344,7 +1263,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0x00); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Vehicle identification request (0x0001)"); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); } // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing @@ -1376,7 +1295,7 @@ PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xfd); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Unknown payload type"); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DOIP Layer, Unknown payload type (0x7777)"); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Unknown payload type (0x7777)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); } // DoIpInvalidPayloadTypePacketParsing From 090ab0e48ee36b684d7db6b74e6468326507ccec Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Wed, 9 Apr 2025 23:00:05 -0400 Subject: [PATCH 26/43] fix doxygene pipeline --- Packet++/header/DoIpLayerData.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h index 31cddf3320..3b1ec1c4c4 100644 --- a/Packet++/header/DoIpLayerData.h +++ b/Packet++/header/DoIpLayerData.h @@ -1063,10 +1063,12 @@ namespace pcpp bool buildFromLayer(const DoIpLayer& doipLayer); }; + /// @class EntityStatusRequestData + /// @brief Represents an entity status request in DoIP. class EntityStatusRequestData : public IDoIpMessageData { public: - /// @brief Default constructor for the AliveCheckRequestData class. + /// @brief Default constructor for the EntityStatusRequestData class. /// /// Initializes a `EntityStatusRequestData` instance /// ensuring compliance with the DoIP protocol requirements. @@ -1088,10 +1090,12 @@ namespace pcpp bool buildFromLayer(const DoIpLayer& doipLayer); }; + /// @class DiagnosticPowerModeRequestData + /// @brief Represents a diagnostic power mode request in DoIP. class DiagnosticPowerModeRequestData : public IDoIpMessageData { public: - /// @brief Default constructor for the AliveCheckRequestData class. + /// @brief Default constructor for the DiagnosticPowerModeRequestData class. /// /// Initializes a `DiagnosticPowerModeRequestData` instance /// ensuring compliance with the DoIP protocol requirements. @@ -1102,7 +1106,7 @@ namespace pcpp DoIpPayloadTypes getType() const override; /// @brief Converts the message data to a human-readable string. - /// @return An empty string because Alive check request message has no additional data. + /// @return An empty string because diagnostic power mode message has no additional data. std::string toString() const override; /// @brief Retrieves the raw binary data of the message. @@ -1113,6 +1117,8 @@ namespace pcpp bool buildFromLayer(const DoIpLayer& doipLayer); }; + /// @class VehicleIdentificationRequestData + /// @brief Represents a vehicle identification request in DoIP. class VehicleIdentificationRequestData : public IDoIpMessageData { public: From 301b0c38cbcaa8b1772f10dfb37cedce70c79049 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sat, 19 Apr 2025 14:23:03 -0400 Subject: [PATCH 27/43] .Big refactoring: .Remove doipLayerData.cpp and doipLayerData.h .Move all enum classes to doipLayer.h .Move string maps to doipLayer.cpp .Change desidgn structure to : .All derived classes for all doipPayloadTypes are inherited from doipLayer itself witch is an abstract interface with protected constructor .Change isLayerDataValid, isProtocolVersionValid, isPayloadTypeValid, to a static func to validate layer from .Make getters and setters for all derived classes and improve dissecting and crafting logic. .Enhance logging errors --- Packet++/CMakeLists.txt | 2 - Packet++/header/DoIpLayer.h | 1469 +++++++++++++++- Packet++/header/DoIpLayerData.h | 1146 ------------- Packet++/src/DoIpLayer.cpp | 1522 +++++++++++++++-- Packet++/src/DoIpLayerData.cpp | 1189 ------------- Packet++/src/TcpLayer.cpp | 2 +- Packet++/src/UdpLayer.cpp | 2 +- ...ngLengthRoutingActivationRequestPacket.dat | 1 + Tests/Packet++Test/TestDefinition.h | 35 +- Tests/Packet++Test/Tests/DoIpTests.cpp | 1514 ++++++++-------- Tests/Packet++Test/main.cpp | 35 +- 11 files changed, 3643 insertions(+), 3274 deletions(-) delete mode 100644 Packet++/header/DoIpLayerData.h delete mode 100644 Packet++/src/DoIpLayerData.cpp create mode 100644 Tests/Packet++Test/PacketExamples/DoIpWrongLengthRoutingActivationRequestPacket.dat diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index 5b71fa3462..80c9ccc039 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -12,7 +12,6 @@ add_library( src/DnsResource.cpp src/DnsResourceData.cpp src/DoIpLayer.cpp - src/DoIpLayerData.cpp src/EthDot3Layer.cpp src/EthLayer.cpp src/FtpLayer.cpp @@ -85,7 +84,6 @@ set( header/DnsResourceData.h header/DnsResource.h header/DoIpLayer.h - header/DoIpLayerData.h header/EthDot3Layer.h header/EthLayer.h header/FtpLayer.h diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 26383ec48f..447e7772ab 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -4,6 +4,7 @@ #include "IpAddress.h" #include "MacAddress.h" #include "Logger.h" +#include /// @file @@ -11,7 +12,377 @@ /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - class IDoIpMessageData; + +/// @brief Length of the External Identifier (EID) field. +#define DOIP_EID_LEN 6 + +/// @brief Length of the Group Identifier (GID) field. +#define DOIP_GID_LEN 6 + +/// @brief Length of the Vehicle Identification Number (VIN) field. +#define DOIP_VIN_LEN 17 + +/// @brief Length of the Reserved ISO field. +#define DOIP_RESERVED_ISO_LEN 4 + +/// @brief Length of the Reserved OEM field. +#define DOIP_RESERVED_OEM_LEN 4 + + enum class DoIpActivationTypes : uint8_t + { + /// Default routing activation type. + /// Used when no specific type is required. + Default = 0x00U, + + /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. + /// Used for vehicle diagnostics in compliance with WWH-OBD standards. + WWH_OBD = 0x01U, + + /// Central security routing activation type. + /// Used for secure communications involving a central security system. + CENTRAL_SECURITY = 0xE0U + }; + + /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). + /// These codes are used to indicate specific errors in the DoIP Generic Header. + enum class DoIpGenericHeaderNackCodes : uint8_t + { + /// Incorrect pattern detected in the header. + /// Indicates that the header does not follow the expected pattern. + INCORRECT_PATTERN = 0x00U, + + /// Unknown payload type. + /// The payload type in the message is not recognized. + UNKNOWN_PAYLOAD_TYPE = 0x01U, + + /// Message too large. + /// The message size exceeds the allowed limit. + MESSAGE_TOO_LARGE = 0x02U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x03U, + + /// Invalid payload length. + /// The payload length specified in the header is invalid. + INVALID_PAYLOAD_LENGTH = 0x04U, + }; + + /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). + /// These action codes specify the next steps required after receiving a DoIP announcement message. + /// Some codes are reserved for future use by ISO standards. + enum class DoIpActionCodes : uint8_t + { + + /// No further action required. + /// Indicates that no additional steps are needed after the announcement. + NO_FURTHER_ACTION_REQUIRED = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing activation required. + /// Indicates that routing activation is needed after the announcement message. + ROUTING_ACTIVATION_REQUIRED = 0x10U, + }; + + /// @brief Enum representing DoIP routing activation response codes (ISO 13400). + /// These codes are used in response to routing activation requests, providing status + /// or error information related to the request. + enum class DoIpRoutingResponseCodes : uint8_t + { + /// Unknown source address. + /// The source address provided in the request is not recognized. + UNKNOWN_SOURCE_ADDRESS = 0x00U, + + /// No free socket. + /// There are no available sockets to establish the connection. + NO_FREE_SOCKET = 0x01U, + + /// Wrong source address. + /// The source address provided in the request is invalid. + WRONG_SOURCE_ADDRESS = 0x02U, + + /// Source address already registered. + /// The provided source address has already been activated. + SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, + + /// Missing authentication. + /// The request is missing required authentication credentials. + MISSING_AUTHENTICATION = 0x04U, + + /// Rejected confirmation. + /// The confirmation of routing activation was rejected. + REJECTED_CONFIRMATION = 0x05U, + + /// Unsupported activation type. + /// The requested routing activation type is not supported. + + UNSUPPORTED_ACTIVATION_TYPE = 0x06U, + + /// Encrypted connection required(TLS). + /// Indicates that the routing activation requires a secure TLS connection. + ENCRYPTED_CONNECTION_TLS = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x0F). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// Routing successfully activated. + /// The routing activation request was processed successfully. + ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, + + /// Confirmation required. + /// Additional confirmation is required to complete the routing activation. + CONFIRMATION_REQUIRED = 0x11U, + }; + + /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). + /// These codes indicate reasons for rejecting or failing to process a diagnostic message + /// in the DoIP protocol. + enum class DoIpDiagnosticMessageNackCodes : uint8_t + { + + /// Reserved for ISO (0x00). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x00 = 0x00U, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Invalid source address. + /// The source address specified in the message is invalid. + INVALID_SOURCE_ADDRESS = 0x02U, + + /// Invalid target address. + /// The target address specified in the message is invalid. + INVALID_TARGET_ADDRESS = 0x03U, + + /// Message too large. + /// The size of the message exceeds the maximum allowed limit. + MESSAGE_TOO_LARGE = 0x04U, + + /// Out of memory. + /// There is insufficient memory available to process the message. + OUT_OF_MEMORY = 0x05U, + + /// Target unreachable. + /// The specified target address cannot be reached. + TARGET_UNREACHABLE = 0x06U, + + /// Unknown network. + /// The message references a network that is not recognized or supported. + UNKNOWN_NETWORK = 0x07U, + + /// Transport protocol error. + /// An error occurred at the transport protocol level, preventing the message from being processed. + TRANSPORT_PROTOCOL_ERROR = 0x08U, + }; + + /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). + /// These codes indicate the diagnostic power mode status of a DoIP entity, + /// providing information about its readiness for diagnostic operations. + enum class DoIpDiagnosticPowerModeCodes : uint8_t + { + + /// Not ready. + /// The DoIP entity is not ready to perform diagnostic operations. + NOT_READY = 0x00U, + + /// Ready. + /// The DoIP entity is ready to perform diagnostic operations. + READY = 0x01U, + + /// Not supported. + /// The DoIP entity does not support diagnostic power mode reporting. + NOT_SUPPORTED = 0x02U + }; + + /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). + /// These codes are used to acknowledge the receipt or processing of diagnostic messages + /// in the DoIP protocol. + enum class DoIpDiagnosticAckCodes : uint8_t + { + + /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. + + ACK = 0x00U + }; + + /// @brief Enum representing DoIP entity status response codes (ISO 13400). + /// These codes are used to indicate the role or type of a DoIP entity in the network. + enum class DoIpEntityStatus : uint8_t + { + /// Gateway. + /// The entity functions as a gateway, + /// facilitating communication between networks. + GATEWAY = 0x00U, + + /// Node. + /// The entity functions as an individual node within the DoIP network. + NODE = 0x01U + }; + + /// @brief Enum representing DoIP sync status (ISO 13400). + /// These codes are used to indicate whether GID and VIN are synchronized or not. + enum class DoIpSyncStatus : uint8_t + { + + /// VIN and or GID are synchronized. + VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, + + /// Reserved for ISO (0x01). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x01 = 0x01U, + + /// Reserved for ISO (0x02). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x02 = 0x02U, + + /// Reserved for ISO (0x03). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x03 = 0x03U, + + /// Reserved for ISO (0x04). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x04 = 0x04U, + + /// Reserved for ISO (0x05). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x05 = 0x05U, + + /// Reserved for ISO (0x06). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x06 = 0x06U, + + /// Reserved for ISO (0x07). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x07 = 0x07U, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x08 = 0x08U, + + /// Reserved for ISO (0x09). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x09 = 0x09U, + + /// Reserved for ISO (0x0A). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0A = 0x0AU, + + /// Reserved for ISO (0x0B). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0B = 0x0BU, + + /// Reserved for ISO (0x0C). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0C = 0x0CU, + + /// Reserved for ISO (0x0D). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0D = 0x0DU, + + /// Reserved for ISO (0x0E). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0E = 0x0EU, + + /// Reserved for ISO (0x08). + /// Reserved for future use as per ISO standards. + RESERVED_ISO_0x0F = 0x0FU, + + /// VIN and or GID are not synchronized. + VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, + + /// Check whether this field is initialised or not + NON_INITIALIZED + }; /// @brief Represents the DoIP (Diagnostics over IP) protocol versions. enum class DoIpProtocolVersion : uint8_t @@ -156,26 +527,12 @@ namespace pcpp class DoIpLayer : public Layer { public: - /// A constructor that creates the layer from an existing packet raw data - /// @param[in] data A pointer to the raw data (will be casted to @ref doiphdr) - /// @param[in] dataLen Size of the data in bytes - /// @param[in] prevLayer A pointer to the previous layer - /// @param[in] packet A pointer to the Packet instance where layer will be stored in - DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : Layer(data, dataLen, prevLayer, packet, DOIP) - {} + // Takes raw data and creates one of the child classes of DoIpLayer, according to the payload type + static DoIpLayer* parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - /// A constructor that creates an generic doip layer and set header and payload fields - /// @param[in] version DoIpProtocolVersion specify the doip protocol version - /// @param[in] data IDoIpMessageData contains all doipMessage specification based on its payload type - DoIpLayer(DoIpProtocolVersion version, const IDoIpMessageData& data); - - /// A constructor that create a doip announcement message with all - /// zeros for vin, eid, gid and no further action required - DoIpLayer(); - - /// A destructor for DoIpLayer class - ~DoIpLayer() override = default; + /// Get the doip payload type + /// @return DoIpPayloadTypes presenting the message doip payload type + virtual DoIpPayloadTypes getPayloadType() const = 0; /// Get the version of DOIP protocol /// @return DoIpProtocolVersion presenting the used protocol version (DOIPV) @@ -197,10 +554,6 @@ namespace pcpp /// @param[in] iVersion the invert version of DOIP protocol to set void setInvertProtocolVersion(uint8_t iVersion); - /// Get the doip payload type - /// @return DoIpPayloadTypes presenting the message doip payload type - DoIpPayloadTypes getPayloadType() const; - /// Get the doip payload type as string /// @return uint16_t presenting the message doip payload type as string std::string getPayloadTypeAsStr() const; @@ -226,19 +579,25 @@ namespace pcpp /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an DOIP layer - static inline bool isDataValid(const uint8_t* data, size_t dataLen); - - /// @brief Resolves and validates the DoIP layer. - /// - /// This function validates the protocol version and payload length of the DoIP layer. - /// If either validation fails, an error is logged, and the function returns `false`. - /// - /// @return `true` if both the protocol version and payload length are valid; - /// otherwise, `false`. - /// - /// @note This function is typically used to ensure the integrity of the DoIP layer - /// before further processing or transmission. - bool isLayerDataValid() const; + static inline bool isDataValid(uint8_t* data, size_t dataLen); + + /// Check if the payload type is valid. + /// @param type Payload type field from DoIP header. + /// @return True if valid, false otherwise. + static inline bool isPayloadTypeValid(uint16_t type); + + /// Validate protocol version and its inverse. + /// @param version Protocol version field. + /// @param invVersion Inverse version field. + /// @param type Payload type (may affect validation rules). + /// @return True if valid, false otherwise. + static inline bool isProtocolVersionValid(uint8_t version, uint8_t invVersion, DoIpPayloadTypes type); + + /// Check if payload length fits within the given buffer. + /// @param payloadLength Declared payload length from header. + /// @param dataLen Total available buffer length. + /// @return True if the buffer is sufficient, false otherwise. + static inline bool isPayloadLengthValid(uint32_t payloadLength, size_t dataLen); // implement abstract methods @@ -251,7 +610,7 @@ namespace pcpp return m_DataLen; } - std::string toString() const override; + std::string toString() const; void computeCalculateFields() override {}; @@ -260,19 +619,18 @@ namespace pcpp return OsiModelTransportLayer; } - private: - void initLayer(); + protected: + // protected c'tors, this class cannot be instantiated by users + DoIpLayer(); + + DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); doiphdr* getDoIpHeader() const { return reinterpret_cast(m_Data); } - bool isPayloadLengthValid() const; - - bool isProtocolVersionValid() const; - - void buildLayer(const IDoIpMessageData& data); + void setHeaderFields(DoIpProtocolVersion version, DoIpPayloadTypes type, uint32_t length); }; // inline methods definition @@ -283,8 +641,1025 @@ namespace pcpp static_cast(port) == DoIpPorts::TLS_PORT); } - inline bool DoIpLayer::isDataValid(const uint8_t* data, size_t dataLen) + inline bool DoIpLayer::isDataValid(uint8_t* data, size_t dataLen) + { + if (data == nullptr) + { + PCPP_LOG_ERROR("Data pointer is null!"); + return false; + } + + auto* doipHeader = reinterpret_cast(data); + const uint8_t version = doipHeader->protocolVersion; + const uint8_t inVersion = doipHeader->invertProtocolVersion; + const uint16_t payloadRaw = doipHeader->payloadType; + const uint32_t lengthRaw = doipHeader->payloadLength; + + const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); + const uint32_t payloadLen = htobe32(lengthRaw); + + if (!isPayloadTypeValid(payloadRaw)) + return false; + + if (!isProtocolVersionValid(version, inVersion, payloadType)) + return false; + + if (!isPayloadLengthValid(payloadLen, dataLen)) + return false; + + return true; + } + + inline bool DoIpLayer::isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type) { - return (data && dataLen >= sizeof(doiphdr)); + DoIpProtocolVersion parsedVersion = static_cast(version); + + switch (parsedVersion) + { + case DoIpProtocolVersion::DefaultVersion: + case DoIpProtocolVersion::ReservedVersion: + case DoIpProtocolVersion::Version01Iso2010: + case DoIpProtocolVersion::Version02Iso2012: + case DoIpProtocolVersion::Version03Iso2019: + case DoIpProtocolVersion::Version04Iso2019_AMD1: + if (parsedVersion == DoIpProtocolVersion::UnknownVersion || + parsedVersion == DoIpProtocolVersion::ReservedVersion || + (parsedVersion == DoIpProtocolVersion::DefaultVersion && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST)) + { + PCPP_LOG_ERROR("[Malformed doip packet]: Invalid or unsupported DoIP protocol version: 0x" + << std::hex << static_cast(version)); + return false; + } + + if (version != static_cast(~inVersion)) + { + PCPP_LOG_ERROR("[Malformed doip packet]: Protocol version and inverse version mismatch! Version: 0x" + << std::hex << static_cast(version) << ", Inverted: 0x" + << static_cast(inVersion)); + return false; + } + + return true; + + default: + PCPP_LOG_ERROR("[Malformed doip packet]: Unknown DoIP protocol version: 0x" << std::hex + << static_cast(version)); + return false; + } + } + + inline bool DoIpLayer::isPayloadTypeValid(uint16_t type) + { + DoIpPayloadTypes payloadType = static_cast(htobe16(type)); + + switch (payloadType) + { + case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: + case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: + case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: + case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: + case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: + case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: + case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: + case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: + return true; + + default: + PCPP_LOG_ERROR("[Malformed doip packet]: Invalid DoIP payload type: 0x" << std::hex << type); + return false; + } } + + inline bool DoIpLayer::isPayloadLengthValid(uint32_t payloadLength, size_t dataLen) + { + constexpr size_t headerSize = sizeof(doiphdr); + + if (dataLen < headerSize) + { + PCPP_LOG_ERROR("[Malformed doip packet]: Data length is smaller than DOIP header size!"); + return false; + } + + size_t actualPayloadLen = dataLen - headerSize; + if (payloadLength != actualPayloadLen) + { + PCPP_LOG_ERROR("[Malformed doip packet]: Payload length mismatch: expected " + << payloadLength << " bytes, but got " << actualPayloadLen << " bytes."); + return false; + } + + return true; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // RoutingActivationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class RoutingActivationRequest + /// @brief Represents a DoIP Routing Activation Request message. + /// + /// Provides parsing and construction for Routing Activation Request messages + /// as defined by the DoIP protocol. + class RoutingActivationRequest : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to raw packet data. + /// @param[in] dataLen Length of the raw data. + /// @param[in] prevLayer Pointer to the previous layer. + /// @param[in] packet Pointer to the parent packet instance. + RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message from field values. + /// @param[in] sourceAddress Source address of the tester. + /// @param[in] activationType Type of routing activation. + RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); + + /// @brief Returns the source address. + uint16_t getSourceAddress() const; + + /// @brief Sets the source address. + void setSourceAddress(uint16_t value); + + /// @brief Returns the activation type. + DoIpActivationTypes getActivationType() const; + + /// @brief Sets the activation type. + void setActivationType(const DoIpActivationTypes& activationType); + + /// @brief Gets the reserved ISO bytes. + std::array getReservedIso() const; + + /// @brief Sets the reserved ISO bytes. + void setReservedIso(const std::array& reservedIso); + + /// @brief Gets the reserved OEM bytes if present. + const std::array* getReservedOem() const; + + /// @brief Sets the reserved OEM bytes. + void setReservedOem(const std::array& reservedOem); + + /// @brief Checks if OEM reserved bytes are present. + bool hasReservedOem() const; + + /// @brief Clears the OEM reserved bytes. + void clearReserveOem(); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; + } + + private: + uint16_t _sourceAddress; ///< Source address of the tester. + DoIpActivationTypes _activationType; ///< Routing activation type. + std::array _reservedIso; ///< ISO reserved bytes. + std::array _reservedOem; ///< OEM reserved bytes. + bool _hasReservedOem; ///< Whether OEM bytes are set. + + static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_activationType) + DOIP_RESERVED_ISO_LEN; + static constexpr size_t RESERVED_OEM_OFFSET = sizeof(doiphdr) + FIXED_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // RoutingActivationResponse | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class RoutingActivationResponse + /// @brief Represents a DoIP Routing Activation Response message. + /// + /// Provides parsing and construction for Routing Activation Response messages + /// as defined by the DoIP protocol. + class RoutingActivationResponse : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to raw packet data. + /// @param[in] dataLen Length of the raw data. + /// @param[in] prevLayer Pointer to the previous layer. + /// @param[in] packet Pointer to the parent packet instance. + RoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message from field values. + /// @param[in] logicalAddressExternalTester Logical address of the external tester. + /// @param[in] sourceAddress ECU source address. + /// @param[in] responseCode The routing response code. + RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, + DoIpRoutingResponseCodes responseCode); + + /// @brief Gets the logical address of the external tester. + uint16_t getLogicalAddressExternalTester() const; + + /// @brief Sets the logical address of the external tester. + void setLogicalAddressExternalTester(uint16_t addr); + + /// @brief Gets the source address. + uint16_t getSourceAddress() const; + + /// @brief Sets the source address. + void setSourceAddress(uint16_t addr); + + /// @brief Gets the routing response code. + DoIpRoutingResponseCodes getResponseCode() const; + + /// @brief Sets the routing response code. + void setResponseCode(DoIpRoutingResponseCodes code); + + /// @brief Gets the reserved ISO bytes. + std::array getReservedIso() const; + + /// @brief Sets the reserved ISO bytes. + void setReservedIso(const std::array& reservedIso); + + /// @brief Gets the reserved OEM bytes if present. + const std::array* getReservedOem() const; + + /// @brief Sets the reserved OEM bytes. + void setReservedOem(const std::array& reservedOem); + + /// @brief Checks if OEM reserved bytes are present. + bool hasReservedOem() const; + + /// @brief Clears the OEM reserved bytes. + void clearReservedOem(); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE; + } + + private: + uint16_t _logicalAddressExternalTester; ///< Logical address of the external tester. + uint16_t _sourceAddress; ///< ECU source address. + DoIpRoutingResponseCodes _responseCode; ///< Routing response code. + std::array _reservedIso; ///< ISO reserved bytes. + std::array _reservedOem; ///< OEM reserved bytes. + bool _hasReservedOem; ///< Whether OEM bytes are set. + + static constexpr size_t FIXED_LEN = sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress) + + sizeof(_responseCode) + DOIP_RESERVED_ISO_LEN; + static constexpr size_t RESERVED_OEM_OFFSET = sizeof(doiphdr) + FIXED_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; + }; + + //~~~~~~~~~~~~~~~~~~~| + // GenericHeaderNack | + //~~~~~~~~~~~~~~~~~~~| + + /// @class GenericHeaderNack + /// @brief Represents a DoIP Generic Header Negative Acknowledgement message. + /// + /// This message indicates that a received DoIP header was invalid or unsupported. + class GenericHeaderNack : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to raw packet data. + /// @param[in] dataLen Length of the raw data. + /// @param[in] prevLayer Pointer to the previous layer. + /// @param[in] packet Pointer to the parent packet instance. + GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message with a specific NACK code. + /// @param[in] nackCode The generic header NACK code. + explicit GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode); + + /// @brief Gets the NACK code. + DoIpGenericHeaderNackCodes getNackCode() const; + + /// @brief Sets the NACK code. + void setNackCode(DoIpGenericHeaderNackCodes code); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK; + } + + private: + DoIpGenericHeaderNackCodes _nackCode; ///< The NACK code indicating the error type. + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequestEID | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class VehicleIdentificationRequestEID + /// @brief Represents a DoIP Vehicle Identification Request with EID. + /// + /// This message is used to identify a vehicle based on its Entity ID (EID). + class VehicleIdentificationRequestEID : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to raw packet data. + /// @param[in] dataLen Length of the raw data. + /// @param[in] prevLayer Pointer to the previous layer. + /// @param[in] packet Pointer to the parent packet instance. + VehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using the specified EID. + /// @param[in] eid A 6-byte Entity ID used for vehicle identification. + explicit VehicleIdentificationRequestEID(const std::array& eid); + + /// @brief Gets the Entity ID (EID). + std::array getEID() const; + + /// @brief Sets the Entity ID (EID). + void setEID(const std::array& eid); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID; + } + + private: + std::array _eid; ///< The 6-byte Entity ID used for identification. + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequestVIN | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class VehicleIdentificationRequestVIN + /// @brief Represents a DoIP Vehicle Identification Request with VIN. + /// + /// This message is used to identify a vehicle based on its Vehicle Identification Number (VIN). + class VehicleIdentificationRequestVIN : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to raw packet data. + /// @param[in] dataLen Length of the raw data. + /// @param[in] prevLayer Pointer to the previous layer. + /// @param[in] packet Pointer to the parent packet instance. + VehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using the specified VIN. + /// @param[in] vin A 17-byte Vehicle Identification Number. + explicit VehicleIdentificationRequestVIN(const std::array& vin); + + /// @brief Gets the Vehicle Identification Number (VIN). + std::array getVIN() const; + + /// @brief Sets the Vehicle Identification Number (VIN). + void setVIN(const std::array& vin); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN; + } + + private: + std::array _vin; ///< The 17-byte Vehicle Identification Number. + }; + + //~~~~~~~~~~~~~~~~~~~~~| + // VehicleAnnouncement | + //~~~~~~~~~~~~~~~~~~~~~| + + /// @class VehicleAnnouncement + /// @brief Represents a DoIP Vehicle Announcement message. + /// + /// This message is broadcasted by a vehicle to announce its presence, including VIN, + /// logical address, EID, GID, and optionally synchronization status. + class VehicleAnnouncement : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to the raw data buffer. + /// @param[in] dataLen Size of the data buffer in bytes. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using specified field values. + /// @param[in] vin Vehicle Identification Number (VIN). + /// @param[in] logicalAddress Logical address of the vehicle. + /// @param[in] eid Entity Identifier (EID). + /// @param[in] gid Group Identifier (GID). + /// @param[in] actionCode Further action code. + VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, const std::array& gid, + DoIpActionCodes actionCode); + + /// @brief Gets the Vehicle Identification Number (VIN). + std::array getVIN() const; + + /// @brief Gets the logical address of the vehicle. + uint16_t getLogicalAddress() const; + + /// @brief Gets the Entity Identifier (EID). + std::array getEID() const; + + /// @brief Gets the Group Identifier (GID). + std::array getGID() const; + + /// @brief Gets the further action required code. + DoIpActionCodes getFurtherActionRequired() const; + + /// @brief Gets the optional synchronization status if available. + const DoIpSyncStatus* getSyncStatus() const; + + /// @brief Sets the Vehicle Identification Number (VIN). + void setVIN(const std::array& vin); + + /// @brief Sets the logical address. + void setLogicalAddress(uint16_t address); + + /// @brief Sets the Entity Identifier (EID). + void setEID(const std::array& eid); + + /// @brief Sets the Group Identifier (GID). + void setGID(const std::array& gid); + + /// @brief Sets the further action required code. + void setFurtherActionRequired(DoIpActionCodes action); + + /// @brief Sets the synchronization status. + void setSyncStatus(DoIpSyncStatus sync); + + /// @brief Checks whether the sync status is present. + bool hasSyncStatus() const; + + /// @brief Clears the optional sync status field. + void clearSyncStatus(); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE; + } + + private: + std::array _vin; ///< Vehicle Identification Number. + uint16_t _logicalAddress; ///< Logical address of the vehicle. + std::array _eid; ///< Entity Identifier. + std::array _gid; ///< Group Identifier. + DoIpActionCodes _actionCode; ///< Further action required code. + DoIpSyncStatus _syncStatus; ///< Optional synchronization status. + bool _hasSyncStatus; ///< Indicates if sync status is set. + + static constexpr size_t FIXED_LEN = + DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + sizeof(_actionCode); + static constexpr size_t SYNC_STATUS_OFFSET = sizeof(doiphdr) + FIXED_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + sizeof(_syncStatus); + }; + + //~~~~~~~~~~~~~~~~~~~~| + // AliveCheckResponse | + //~~~~~~~~~~~~~~~~~~~~| + + /// @class AliveCheckResponse + /// @brief Represents a DoIP Alive Check Response message. + /// + /// The Alive Check Response is used to confirm that an entity is still active in the network. + /// It contains the source address of the responder. + class AliveCheckResponse : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to the raw data buffer. + /// @param[in] dataLen Size of the data buffer in bytes. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using the specified source address. + /// @param[in] sourceAddress The source address of the responder. + explicit AliveCheckResponse(uint16_t sourceAddress); + + /// @brief Gets the source address. + /// @return The 2-byte source address of the responder. + uint16_t getSourceAddress() const; + + /// @brief Sets the source address. + /// @param[in] address The new source address. + void setSourceAddress(uint16_t address); + + /// @brief Returns a human-readable summary of the message. + /// @return A string summarizing the Alive Check Response. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type. + /// @return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE; + } + + private: + uint16_t _sourceAddress; ///< Source address of the responder. + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticPowerModeResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticPowerModeResponse + /// @brief Represents a DoIP Diagnostic Power Mode Response message. + /// + /// This message is used to communicate the current power mode of the vehicle + /// or control unit in response to a diagnostic power mode request. + class DiagnosticPowerModeResponse : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to the raw data buffer. + /// @param[in] dataLen Size of the data buffer in bytes. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using the specified power mode code. + /// @param[in] modeCode Diagnostic power mode code to set. + explicit DiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes modeCode); + + /// @brief Gets the current power mode code. + /// @return The diagnostic power mode code. + DoIpDiagnosticPowerModeCodes getPowerModeCode() const; + + /// @brief Sets the power mode code. + /// @param[in] code The new diagnostic power mode code. + void setPowerModeCode(DoIpDiagnosticPowerModeCodes code); + + /// @brief Returns a human-readable summary of the message. + /// @return A string summarizing the Diagnostic Power Mode Response. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type. + /// @return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE; + } + + private: + DoIpDiagnosticPowerModeCodes _powerModeCode; ///< Diagnostic power mode code. + }; + + //~~~~~~~~~~~~~~~~~~~~~| + // EntityStatusResponse| + //~~~~~~~~~~~~~~~~~~~~~| + + /// @class EntityStatusResponse + /// @brief Represents a DoIP Entity Status Response message. + /// + /// This message provides the status of a DoIP entity, such as its type, + /// the number of concurrent sockets it can support, and optionally the max data size. + class EntityStatusResponse : public DoIpLayer + { + public: + /// @brief Constructs the layer from raw DoIP packet data. + /// @param[in] data Pointer to the raw data buffer. + /// @param[in] dataLen Size of the data buffer in bytes. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs the message using provided field values. + /// @param[in] nodeType Type of the DoIP node (default: GATEWAY). + /// @param[in] maxConcurrentSockets Maximum supported concurrent sockets. + /// @param[in] currentlyOpenSockets Currently active sockets. + EntityStatusResponse(DoIpEntityStatus nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets); + + /// @brief Returns the DoIP payload type. + /// @return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE; + } + + /// @brief Gets the type of the DoIP node. + /// @return The DoIP entity status value. + DoIpEntityStatus getNodeType() const; + + /// @brief Gets the maximum number of concurrent sockets supported. + /// @return Max supported concurrent sockets. + uint8_t getMaxConcurrentSockets() const; + + /// @brief Gets the number of currently open sockets. + /// @return Number of currently open sockets. + uint8_t getCurrentlyOpenSockets() const; + + /// @brief Gets the optional maximum data size field. + /// @return Pointer to a 4-byte array representing max data size, or nullptr if not set. + const std::array* getMaxDataSize() const; + + /// @brief Sets the DoIP node type. + /// @param[in] status New DoIP entity status. + void setNodeType(DoIpEntityStatus status); + + /// @brief Sets the maximum number of concurrent sockets. + /// @param[in] sockets New maximum concurrent socket count. + void setMaxConcurrentSockets(uint8_t sockets); + + /// @brief Sets the number of currently open sockets. + /// @param[in] sockets New count of currently open sockets. + void setCurrentlyOpenSockets(uint8_t sockets); + + /// @brief Sets the maximum data size field. + /// @param[in] data 4-byte array representing the max data size. + void setMaxDataSize(const std::array& data); + + /// @brief Checks if the optional max data size is present. + /// @return True if max data size is available, false otherwise. + bool hasMaxDataSize() const; + + /// @brief Clears the optional max data size field. + void clearMaxDataSize(); + + /// @brief Returns a human-readable summary of the message. + /// @return A string summarizing the Entity Status Response. + std::string getSummary() const; + + private: + DoIpEntityStatus _nodeType; ///< Type of the DoIP node (e.g., gateway, ECU). + uint8_t _maxConcurrentSockets; ///< Maximum number of concurrent sockets supported. + uint8_t _currentlyOpenSockets; ///< Number of currently open sockets. + std::array _maxDataSize; ///< Optional max data size field. + bool _hasMaxDataSize; ///< Indicates if max data size is set. + + static constexpr size_t FIXED_LEN = + sizeof(_nodeType) + sizeof(_maxConcurrentSockets) + sizeof(_currentlyOpenSockets); + static constexpr size_t MAX_DATA_SIZE_OFFSET = sizeof(doiphdr) + FIXED_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + sizeof(_maxDataSize); + }; + + //~~~~~~~~~~~~~~~~~~| + // DiagnosticMessage| + //~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticMessage + /// @brief Represents a DoIP Diagnostic Message sent between tester and ECU. + /// + /// This message includes source and target addresses and carries diagnostic service data. + class DiagnosticMessage : public DoIpLayer + { + public: + /// @brief Constructs the DiagnosticMessage from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs a DiagnosticMessage from specified field values. + /// @param[in] sourceAddress Address of the sending ECU/tester. + /// @param[in] targetAddress Address of the target ECU. + /// @param[in] diagData Vector containing UDS diagnostic service data. + DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData); + + /// @brief Returns the DoIP payload type. + /// @return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; + } + + /// @brief Gets the source logical address of the message. + /// @return 16-bit address of the source ECU. + uint16_t getSourceAddress() const; + + /// @brief Gets the target logical address of the message. + /// @return 16-bit address of the destination ECU. + uint16_t getTargetAddress() const; + + /// @brief Gets the diagnostic data payload. + /// @return Reference to the vector containing UDS data. + const std::vector& getDiagnosticData() const; + + /// @brief Sets the source logical address. + /// @param[in] addr New 16-bit source address. + void setSourceAddress(uint16_t addr); + + /// @brief Sets the target logical address. + /// @param[in] addr New 16-bit target address. + void setTargetAddress(uint16_t addr); + + /// @brief Sets the diagnostic data payload. + /// @param[in] data New diagnostic data to send. + void setDiagnosticData(const std::vector& data); + + /// @brief Returns a human-readable summary of the message content. + /// @return A string summarizing the diagnostic message. + std::string getSummary() const; + + private: + uint16_t _sourceAddress; ///< Logical address of the sender. + uint16_t _targetAddress; ///< Logical address of the receiver. + std::vector _diagnosticData; ///< Diagnostic (UDS) data payload. + }; + + //~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticAckMessage| + //~~~~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticAckMessage + /// @brief Represents a positive acknowledgment message in response to a DiagnosticMessage. + /// + /// This message is sent by a DoIP node to acknowledge the correct reception and processing + /// of a diagnostic message. Optionally, the original message may be echoed back. + class DiagnosticAckMessage : public DoIpLayer + { + public: + /// @brief Constructs a DiagnosticAckMessage from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs a DiagnosticAckMessage from specified field values. + /// @param[in] sourceAddress Address of the sending ECU. + /// @param[in] targetAddress Address of the receiving ECU. + /// @param[in] ackCode Acknowledgment code describing the result. + DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode); + + /// @brief Gets the source logical address of the message. + uint16_t getSourceAddress() const; + + /// @brief Gets the target logical address of the message. + uint16_t getTargetAddress() const; + + /// @brief Gets the diagnostic acknowledgment code. + DoIpDiagnosticAckCodes getAckCode() const; + + /// @brief Gets the optional previously echoed diagnostic message. + /// @return Pointer to the echoed message or nullptr if not present. + const std::vector* getPreviousMessage() const; + + /// @brief Sets the source logical address. + void setSourceAddress(uint16_t address); + + /// @brief Sets the target logical address. + void setTargetAddress(uint16_t address); + + /// @brief Sets the acknowledgment code. + void setAckCode(DoIpDiagnosticAckCodes code); + + /// @brief Checks if a previous message is attached. + /// @return True if a previous message is present. + bool hasPreviousMessage(); + + /// @brief Sets the previous echoed diagnostic message. + void setPreviousMessage(const std::vector& msg); + + /// @brief Clears the previously stored diagnostic message. + void clearPreviousMessage(); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK; + } + + private: + uint16_t _sourceAddress; ///< Logical address of the sender. + uint16_t _targetAddress; ///< Logical address of the receiver. + DoIpDiagnosticAckCodes _ackCode; ///< Acknowledgment result code. + std::vector _previousMessage; ///< Optional echoed diagnostic message. + bool _hasPreviousMessage; ///< True if a previous message is present. + static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_targetAddress) + sizeof(_ackCode); + static constexpr size_t PREVIOUS_MSG_OFFSET = sizeof(doiphdr) + FIXED_LEN; + }; + + //~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticNackMessage| + //~~~~~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticNackMessage + /// @brief Represents a negative acknowledgment message in response to a DiagnosticMessage. + /// + /// This message is sent by a DoIP node when a diagnostic message is received but could not + /// be processed successfully. It may include the original message for reference. + class DiagnosticNackMessage : public DoIpLayer + { + public: + /// @brief Constructs a DiagnosticNackMessage from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs a DiagnosticNackMessage from specified field values. + /// @param[in] sourceAddress Address of the sending ECU. + /// @param[in] targetAddress Address of the receiving ECU. + /// @param[in] nackCode Negative acknowledgment code describing the failure. + DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticMessageNackCodes nackCode); + + /// @brief Gets the source logical address of the message. + uint16_t getSourceAddress() const; + + /// @brief Gets the target logical address of the message. + uint16_t getTargetAddress() const; + + /// @brief Gets the negative acknowledgment code. + DoIpDiagnosticMessageNackCodes getNackCode() const; + + /// @brief Gets the optional previously echoed diagnostic message. + /// @return Pointer to the echoed message or nullptr if not present. + const std::vector* getPreviousMessage() const; + + /// @brief Sets the source logical address. + void setSourceAddress(uint16_t address); + + /// @brief Sets the target logical address. + void setTargetAddress(uint16_t address); + + /// @brief Sets the negative acknowledgment code. + void setNackCode(DoIpDiagnosticMessageNackCodes code); + + /// @brief Checks if a previous message is attached. + /// @return True if a previous message is present. + bool hasPreviousMessage() const; + + /// @brief Sets the previous echoed diagnostic message. + void setPreviousMessage(const std::vector& msg); + + /// @brief Clears the previously stored diagnostic message. + void clearPreviousMessage(); + + /// @brief Returns a human-readable summary of the message. + std::string getSummary() const; + + /// @brief Returns the DoIP payload type. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK; + } + + private: + uint16_t _sourceAddress; ///< Logical address of the sender. + uint16_t _targetAddress; ///< Logical address of the receiver. + DoIpDiagnosticMessageNackCodes _nackCode; ///< Negative acknowledgment result code. + std::vector _previousMessage; ///< Optional echoed diagnostic message. + bool _hasPreviousMessage; ///< True if a previous message is present. + static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_targetAddress) + sizeof(_nackCode); + static constexpr size_t PREVIOUS_MSG_OFFSET = sizeof(doiphdr) + FIXED_LEN; + }; + + //~~~~~~~~~~~~~~~~~~| + // AliveCheckRequest| + //~~~~~~~~~~~~~~~~~~| + + /// @class AliveCheckRequest + /// @brief Represents an Alive Check Request message in the DoIP protocol. + /// + /// This message is sent by a tester to verify if a DoIP entity is responsive. + /// The responding DoIP node should reply with an Alive Check Response. + class AliveCheckRequest : public DoIpLayer + { + public: + /// @brief Constructs an AliveCheckRequest from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + AliveCheckRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + {} + + /// @brief Default constructor to create an empty AliveCheckRequest message. + AliveCheckRequest(); + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ALIVE_CHECK_REQUEST; + } + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class VehicleIdentificationRequest + /// @brief Represents a Vehicle Identification Request message in the DoIP protocol. + /// + /// This message is sent by a tester to request vehicle identification information + /// such as VIN, logical addresses, and other metadata. It can be broadcast or directed. + class VehicleIdentificationRequest : public DoIpLayer + { + public: + /// @brief Constructs a VehicleIdentificationRequest from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + VehicleIdentificationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + {} + + /// @brief Default constructor to create an empty VehicleIdentificationRequest. + VehicleIdentificationRequest(); + + /// @brief Returns the DoIP payload type. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST; + } + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticPowerModeRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticPowerModeRequest + /// @brief Represents a Diagnostic Power Mode Request message in the DoIP protocol. + /// + /// This message is sent to inquire about the current power mode status of the vehicle, + /// which helps determine if diagnostic communication can be initiated or continued. + class DiagnosticPowerModeRequest : public DoIpLayer + { + public: + /// @brief Constructs a DiagnosticPowerModeRequest from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticPowerModeRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + {} + + /// @brief Default constructor to create an empty DiagnosticPowerModeRequest. + DiagnosticPowerModeRequest(); + + /// @brief Returns the DoIP payload type. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST; + } + }; + + //~~~~~~~~~~~~~~~~~~~~| + // EntityStatusRequest| + //~~~~~~~~~~~~~~~~~~~~| + + /// @class EntityStatusRequest + /// @brief Represents an Entity Status Request message in the DoIP protocol. + /// + /// This message is sent by a tester to request the current status of the DoIP entity, + /// including capabilities such as maximum number of concurrent socket connections + /// and optionally the maximum data size supported. + class EntityStatusRequest : public DoIpLayer + { + public: + /// @brief Constructs an EntityStatusRequest from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + EntityStatusRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + {} + + /// @brief Default constructor to create an empty EntityStatusRequest message. + EntityStatusRequest(); + + /// @brief Returns the DoIP payload type for this message. + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::ENTITY_STATUS_REQUEST; + } + }; + } // namespace pcpp diff --git a/Packet++/header/DoIpLayerData.h b/Packet++/header/DoIpLayerData.h deleted file mode 100644 index 3b1ec1c4c4..0000000000 --- a/Packet++/header/DoIpLayerData.h +++ /dev/null @@ -1,1146 +0,0 @@ -#pragma once - -#include -#include -#include -#include "EndianPortable.h" -#include "Logger.h" -#include "DoIpLayer.h" - -/// @file - -/// @namespace pcpp -/// @brief The main namespace for the PcapPlusPlus library -namespace pcpp -{ -/// @brief Length of the External Identifier (EID) field. -#define DOIP_EID_LEN 6 - -/// @brief Length of the Group Identifier (GID) field. -#define DOIP_GID_LEN 6 - -/// @brief Length of the Vehicle Identification Number (VIN) field. -#define DOIP_VIN_LEN 17 - -/// @brief Length of the Reserved ISO field. -#define DOIP_RESERVED_ISO_LEN 4 - -/// @brief Length of the Reserved OEM field. -#define DOIP_RESERVED_OEM_LEN 4 - /// @brief Enum representing DoIP routing activation types. - /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). - enum class DoIpActivationTypes : uint8_t - { - /// Default routing activation type. - /// Used when no specific type is required. - Default = 0x00U, - - /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. - /// Used for vehicle diagnostics in compliance with WWH-OBD standards. - WWH_OBD = 0x01U, - - /// Central security routing activation type. - /// Used for secure communications involving a central security system. - CENTRAL_SECURITY = 0xE0U - }; - - /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). - /// These codes are used to indicate specific errors in the DoIP Generic Header. - enum class DoIpGenericHeaderNackCodes : uint8_t - { - /// Incorrect pattern detected in the header. - /// Indicates that the header does not follow the expected pattern. - INCORRECT_PATTERN = 0x00U, - - /// Unknown payload type. - /// The payload type in the message is not recognized. - UNKNOWN_PAYLOAD_TYPE = 0x01U, - - /// Message too large. - /// The message size exceeds the allowed limit. - MESSAGE_TOO_LARGE = 0x02U, - - /// Out of memory. - /// There is insufficient memory available to process the message. - OUT_OF_MEMORY = 0x03U, - - /// Invalid payload length. - /// The payload length specified in the header is invalid. - INVALID_PAYLOAD_LENGTH = 0x04U, - }; - - /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). - /// These action codes specify the next steps required after receiving a DoIP announcement message. - /// Some codes are reserved for future use by ISO standards. - enum class DoIpActionCodes : uint8_t - { - - /// No further action required. - /// Indicates that no additional steps are needed after the announcement. - NO_FURTHER_ACTION_REQUIRED = 0x00U, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Reserved for ISO (0x02). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x02 = 0x02U, - - /// Reserved for ISO (0x03). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x03 = 0x03U, - - /// Reserved for ISO (0x04). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x04 = 0x04U, - - /// Reserved for ISO (0x05). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x05 = 0x05U, - - /// Reserved for ISO (0x06). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x06 = 0x06U, - - /// Reserved for ISO (0x07). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x07 = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x0F). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// Routing activation required. - /// Indicates that routing activation is needed after the announcement message. - ROUTING_ACTIVATION_REQUIRED = 0x10U, - }; - - /// @brief Enum representing DoIP routing activation response codes (ISO 13400). - /// These codes are used in response to routing activation requests, providing status - /// or error information related to the request. - enum class DoIpRoutingResponseCodes : uint8_t - { - /// Unknown source address. - /// The source address provided in the request is not recognized. - UNKNOWN_SOURCE_ADDRESS = 0x00U, - - /// No free socket. - /// There are no available sockets to establish the connection. - NO_FREE_SOCKET = 0x01U, - - /// Wrong source address. - /// The source address provided in the request is invalid. - WRONG_SOURCE_ADDRESS = 0x02U, - - /// Source address already registered. - /// The provided source address has already been activated. - SOURCE_ADDRESS_ALREADY_REGISTERED = 0x03U, - - /// Missing authentication. - /// The request is missing required authentication credentials. - MISSING_AUTHENTICATION = 0x04U, - - /// Rejected confirmation. - /// The confirmation of routing activation was rejected. - REJECTED_CONFIRMATION = 0x05U, - - /// Unsupported activation type. - /// The requested routing activation type is not supported. - - UNSUPPORTED_ACTIVATION_TYPE = 0x06U, - - /// Encrypted connection required(TLS). - /// Indicates that the routing activation requires a secure TLS connection. - ENCRYPTED_CONNECTION_TLS = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x0F). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// Routing successfully activated. - /// The routing activation request was processed successfully. - ROUTING_SUCCESSFULLY_ACTIVATED = 0x10U, - - /// Confirmation required. - /// Additional confirmation is required to complete the routing activation. - CONFIRMATION_REQUIRED = 0x11U, - }; - - /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). - /// These codes indicate reasons for rejecting or failing to process a diagnostic message - /// in the DoIP protocol. - enum class DoIpDiagnosticMessageNackCodes : uint8_t - { - - /// Reserved for ISO (0x00). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x00 = 0x00U, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Invalid source address. - /// The source address specified in the message is invalid. - INVALID_SOURCE_ADDRESS = 0x02U, - - /// Invalid target address. - /// The target address specified in the message is invalid. - INVALID_TARGET_ADDRESS = 0x03U, - - /// Message too large. - /// The size of the message exceeds the maximum allowed limit. - MESSAGE_TOO_LARGE = 0x04U, - - /// Out of memory. - /// There is insufficient memory available to process the message. - OUT_OF_MEMORY = 0x05U, - - /// Target unreachable. - /// The specified target address cannot be reached. - TARGET_UNREACHABLE = 0x06U, - - /// Unknown network. - /// The message references a network that is not recognized or supported. - UNKNOWN_NETWORK = 0x07U, - - /// Transport protocol error. - /// An error occurred at the transport protocol level, preventing the message from being processed. - TRANSPORT_PROTOCOL_ERROR = 0x08U, - }; - - /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). - /// These codes indicate the diagnostic power mode status of a DoIP entity, - /// providing information about its readiness for diagnostic operations. - enum class DoIpDiagnosticPowerModeCodes : uint8_t - { - - /// Not ready. - /// The DoIP entity is not ready to perform diagnostic operations. - NOT_READY = 0x00U, - - /// Ready. - /// The DoIP entity is ready to perform diagnostic operations. - READY = 0x01U, - - /// Not supported. - /// The DoIP entity does not support diagnostic power mode reporting. - NOT_SUPPORTED = 0x02U - }; - - /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). - /// These codes are used to acknowledge the receipt or processing of diagnostic messages - /// in the DoIP protocol. - enum class DoIpDiagnosticAckCodes : uint8_t - { - - /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. - - ACK = 0x00U - }; - - /// @brief Enum representing DoIP entity status response codes (ISO 13400). - /// These codes are used to indicate the role or type of a DoIP entity in the network. - enum class DoIpEntityStatus : uint8_t - { - /// Gateway. - /// The entity functions as a gateway, - /// facilitating communication between networks. - GATEWAY = 0x00U, - - /// Node. - /// The entity functions as an individual node within the DoIP network. - NODE = 0x01U - }; - - /// @brief Enum representing DoIP sync status (ISO 13400). - /// These codes are used to indicate whether GID and VIN are synchronized or not. - enum class DoIpSyncStatus : uint8_t - { - - /// VIN and or GID are synchronized. - VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, - - /// Reserved for ISO (0x01). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x01 = 0x01U, - - /// Reserved for ISO (0x02). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x02 = 0x02U, - - /// Reserved for ISO (0x03). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x03 = 0x03U, - - /// Reserved for ISO (0x04). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x04 = 0x04U, - - /// Reserved for ISO (0x05). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x05 = 0x05U, - - /// Reserved for ISO (0x06). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x06 = 0x06U, - - /// Reserved for ISO (0x07). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x07 = 0x07U, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x08 = 0x08U, - - /// Reserved for ISO (0x09). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x09 = 0x09U, - - /// Reserved for ISO (0x0A). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0A = 0x0AU, - - /// Reserved for ISO (0x0B). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0B = 0x0BU, - - /// Reserved for ISO (0x0C). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0C = 0x0CU, - - /// Reserved for ISO (0x0D). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0D = 0x0DU, - - /// Reserved for ISO (0x0E). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0E = 0x0EU, - - /// Reserved for ISO (0x08). - /// Reserved for future use as per ISO standards. - RESERVED_ISO_0x0F = 0x0FU, - - /// VIN and or GID are not synchronized. - VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, - - /// Check whether this field is initialised or not - NON_INITIALIZED - }; - - /// @brief A pure abstract class representing the basic structure of DoIP messages. - /// - /// This interface defines methods to retrieve the type, string representation, - /// and binary data of DoIP messages. All DoIP message classes must implement this interface. - class IDoIpMessageData - { - public: - virtual ~IDoIpMessageData() = default; - - /// @brief Returns the type of the DoIP message. - /// @return The type of the message as a `DoIpPayloadTypes` enum. - virtual DoIpPayloadTypes getType() const = 0; - - /// @brief Converts the message data to a human-readable string. - /// @return The string representation of the message. - virtual std::string toString() const = 0; - - /// @brief Retrieves the raw binary data of the message. - /// @return The message data as a vector of bytes. - virtual std::vector getData() const = 0; - }; - - /// @class RoutingActivationRequestData - /// @brief Represents a Routing Activation Request message in DoIP. - /// - /// This class encapsulates data for a Routing Activation Request message, - /// including source address, activation type, and reserved fields. - class RoutingActivationRequestData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the RoutingActivationRequestData class. - /// - /// Initializes a `RoutingActivationRequestData` instance with default values: - /// - `sourceAddress` is set to `0x0000`. - /// - `activationType` is set to `DoIpActivationTypes::Default`. - /// - `reservedIso` and `reservedOem` fields are zero-initialized. - /// This constructor provides a default initialization state for routing activation request - /// data, ensuring compliance with the DoIP protocol requirements. - RoutingActivationRequestData(); - - uint16_t sourceAddress; /// < Source address of the message. - DoIpActivationTypes activationType; /// < The activation type (e.g., activate, deactivate). - std::array reservedIso; /// < Reserved ISO bytes. - std::unique_ptr> reservedOem; /// < Reserved OEM bytes. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Routing Activation Request message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Routing Activation Request data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Routing Activation Request payload type. It extracts the source address, activation - /// type, reserved ISO bytes, and optionally reserved OEM bytes if present. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Request data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note This method overrides the base class implementation and adds specific parsing - /// logic for the Routing Activation Request message. - /// - /// The following fields are parsed: - /// - `sourceAddress`: The source address of the message. - /// - `activationType`: The type of activation requested. - /// - `reservedIso`: Reserved bytes as defined by ISO specifications. - /// - `reservedOem`: Reserved bytes as defined by OEM specifications, only if present. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class RoutingActivationResponseData - /// @brief Represents a Routing Activation Response message in DoIP. - /// - /// This class encapsulates data for a Routing Activation Response message, - /// including logical address, source address, response code, and reserved fields. - class RoutingActivationResponseData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the RoutingActivationResponseData class. - /// Initializes a `RoutingActivationResponseData` instance with default values: - /// - `logicalAddressExternalTester` is set to `0x0000`. - /// - `sourceAddress` is set to `0x0000`. - /// - `responseCode` is set to DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED. - /// - `reservedIso` fields is zero-initialized. - /// This constructor provides a default initialization state for routing activation response - /// data, ensuring compliance with the DoIP protocol requirements. - RoutingActivationResponseData(); - - uint16_t logicalAddressExternalTester; /// < Logical address of the external tester. - uint16_t sourceAddress; /// < Source address of the message. - DoIpRoutingResponseCodes responseCode; /// < Response code indicating success or failure. - std::array reservedIso; /// < Reserved ISO bytes. - std::unique_ptr> reservedOem; /// < Reserved OEM bytes. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Routing Activation Response message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses the Routing Activation Response data from a DoIpLayer. - /// - /// This method validates and extracts the necessary fields from the provided - /// DoIpLayer. It ensures the layer corresponds to the Routing Activation Response - /// payload type and parses fields including the logical tester address, source - /// address, response code, and reserved fields. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Routing Activation Response data. - /// @return `true` if parsing was successful, `false` otherwise. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class GenericHeaderNackData - /// @brief Represents a Generic Header Negative Acknowledgment message in DoIP. - /// - /// This class encapsulates data for a Generic Header NACK message, including - /// the NACK code to indicate the failure. - class GenericHeaderNackData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the GenericHeaderNackData class. - /// - /// This constructor initializes a `GenericHeaderNackData` instance with default values: - /// - `genericNackCode` is set to `DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH`. - GenericHeaderNackData(); - - DoIpGenericHeaderNackCodes genericNackCode; /// < The NACK code indicating the error. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Generic Header NACK message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Generic Header NACK data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Generic Header NACK payload type. It extracts the `genericNackCode` field from the layer. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Generic Header NACK data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method checks for null pointers and verifies that the payload type matches - /// `DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK`. Logs an error in case of invalid data. - /// - /// The following field is parsed: - /// - `genericNackCode`: The NACK code indicating the type of error. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class VehicleIdentificationRequestEIDData - /// @brief Represents a Vehicle Identification Request with EID message in DoIP. - /// - /// This class encapsulates data for a Vehicle Identification Request message - /// that includes the Electronic Identifier (EID). - class VehicleIdentificationRequestEIDData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the VehicleIdentificationRequestEIDData class. - /// - /// This constructor initializes a `VehicleIdentificationRequestEIDData` instance with default values: - /// - `eid` (Entity Identifier) is initialized to all zeros. - VehicleIdentificationRequestEIDData(); - - std::array eid; /// < Electronic Identifier (EID). - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Vehicle Identification Request EID message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Vehicle Identification Request with EID data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Vehicle Identification Request with EID payload type. It extracts the EID field from the layer. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with EID - /// data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method checks for null pointers and verifies that the payload type matches - /// `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID`. Logs an error if the data is invalid. - /// - /// The following field is parsed: - /// - `eid`: The EID (Extended Identifier), extracted as a byte array of length `DOIP_EID_LEN`. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class VehicleIdentificationRequestVINData - /// @brief Represents a Vehicle Identification Request with VIN message in DoIP. - /// - /// This class encapsulates data for a Vehicle Identification Request message - /// that includes the Vehicle Identification Number (VIN). - class VehicleIdentificationRequestVINData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the VehicleIdentificationRequestVINData class. - /// - /// This constructor initializes a `VehicleIdentificationRequestVINData` instance with default values: - /// - `vin` (Vehicle Identification Number) is initialized to all zeros. - VehicleIdentificationRequestVINData(); - - std::array vin; /// < Vehicle Identification Number (VIN). - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Vehicle Identification Request VIN message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Vehicle Identification Request with VIN data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Vehicle Identification Request with VIN payload type. It extracts the VIN (Vehicle Identification Number) - /// field from the payload data and populates the class instance. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Identification Request with VIN - /// data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN`. - /// - Checks that the data length is sufficient to extract the VIN field. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following field is parsed: - /// - `vin`: The Vehicle Identification Number (VIN), extracted as a byte array of length `DOIP_VIN_LEN`. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class VehicleAnnouncementData - /// @brief Represents a Vehicle Announcement message in DoIP. - /// - /// This class encapsulates data for a Vehicle Announcement message, including - /// VIN, logical address, EID, GID, and further action required. - class VehicleAnnouncementData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the VehicleAnnouncementData class. - /// - /// This constructor initializes a `VehicleAnnouncementData` instance with default values: - /// - `vin` is initialized to all zeros. - /// - `logicalAddress` is set to `0`. - /// - `eid` (Entity Identifier) is initialized to all zeros. - /// - `gid` (Group Identifier) is initialized to all zeros. - /// - `furtherActionRequired` is set to `DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED`. - /// - `syncStatus` is set to `DoIpSyncStatus::NON_INITIALIZED`, indicating that the sync status is - /// uninitialized. - VehicleAnnouncementData(); - - std::array vin; /// < Vehicle Identification Number (VIN). - uint16_t logicalAddress; /// < Logical address of the vehicle. - std::array eid; /// < Electronic Identifier (EID). - std::array gid; /// < Group Identifier (GID). - DoIpActionCodes furtherActionRequired; /// < Action required after the announcement. - DoIpSyncStatus syncStatus; /// < version and invert version are synchronized. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Vehicle Announcement message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Vehicle Announcement data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Announcement Message payload type. It extracts fields such as VIN, logical address, EID, GID, - /// further action required, and synchronization status from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Vehicle Announcement data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE`. - /// - Checks that the data length is sufficient to extract all required fields. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following fields are parsed: - /// - `vin`: Vehicle Identification Number (VIN). - /// - `logicalAddress`: Logical address of the vehicle. - /// - `eid`: End Identifier. - /// - `gid`: Group Identifier. - /// - `furtherActionRequired`: Further action required code. - /// - `syncStatus`: VIN/GID synchronization status (if present). - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class AliveCheckResponseData - /// @brief Represents an Alive Check Response message in DoIP. - /// - /// This class encapsulates data for an Alive Check Response message, - /// including the source address. - class AliveCheckResponseData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the AliveCheckResponseData class. - /// - /// This constructor initializes an `AliveCheckResponseData` instance with default values: - /// - `sourceAddress` is set to `0x0000`. - AliveCheckResponseData(); - - uint16_t sourceAddress; /// < Source address of the Alive Check Response message. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Alive Check Response message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Alive Check Response data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Alive Check Response payload type. It extracts the `sourceAddress` field from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Alive Check Response data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::ALIVE_CHECK_RESPONSE`. - /// - Checks that the data length is sufficient to extract the `sourceAddress`. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following field is parsed: - /// - `sourceAddress`: The source address of the response. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class DiagnosticPowerModeResponseData - /// @brief Represents a Diagnostic Power Mode Response message in DoIP. - /// - /// This class encapsulates data for a Diagnostic Power Mode Response message, - /// including a power mode code indicating the current power mode. - class DiagnosticPowerModeResponseData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the DiagnosticPowerModeResponseData class. - /// - /// Initializes a DiagnosticPowerModeResponseData instance with the power mode - /// response code set to `NOT_READY`. This indicates that the system is not yet - /// ready to respond to diagnostic power mode requests. - DiagnosticPowerModeResponseData(); - - DoIpDiagnosticPowerModeCodes powerModeCode; /// < Code representing the power mode. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Diagnostic Power Mode Response message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Diagnostic Power Mode Response data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Diagnostic Power Mode Response payload type. It extracts the `powerModeCode` field from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Power Mode Response data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE`. - /// - Checks that the data length is sufficient to extract the `powerModeCode`. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following field is parsed: - /// - `powerModeCode`: The diagnostic power mode response code. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class EntityStatusResponseData - /// @brief Represents an Entity Status Response message in DoIP. - /// - /// This class encapsulates data for an Entity Status Response message, - /// including status, maximum concurrent sockets, open sockets, and maximum data size. - class EntityStatusResponseData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the EntityStatusResponseData class. - /// - /// Initializes an `EntityStatusResponseData` instance with the following default values: - /// - `status`: Set to `DoIpEntityStatus::GATEWAY`, indicating the entity is acting as a gateway. - /// - `maxConcurrentSockets`: Set to `0`, meaning no concurrent sockets are allowed by default. - /// - `currentlyOpenSockets`: Set to `0`, indicating no sockets are currently open. - /// - `maxDataSize`: Set to `nullptr`, meaning no data for this field. can be assigned after object creation. - /// - /// @code - /// EntityStatusResponseData data; - /// data.maxDataSize = std::unique_ptr>(new std::array {0x00, 0x01, 0x02, - /// 0x03}); - /// @endcode - EntityStatusResponseData(); - - DoIpEntityStatus nodeType; /// < Status of the entity. - uint8_t maxConcurrentSockets; /// < Maximum number of concurrent sockets. - uint8_t currentlyOpenSockets; /// < Number of currently open sockets. - std::unique_ptr> - maxDataSize; /// < Maximum data size that can be handled (4 bytes optional). - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Entity Status Response message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Entity Status Response data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Entity Status Response payload type. It extracts fields such as `nodeType`, - /// `maxConcurrentSockets`, `currentlyOpenSockets`, and optionally `maxDataSize` from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Entity Status Response data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::ENTITY_STATUS_RESPONSE`. - /// - Checks that the data length is sufficient for the fixed fields and optional `maxDataSize`. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following fields are parsed: - /// - `nodeType`: Entity status indicating the role of the entity. - /// - `maxConcurrentSockets`: Maximum allowed concurrent sockets. - /// - `currentlyOpenSockets`: Number of currently open sockets. - /// - `maxDataSize` (optional): Maximum data size supported (4 bytes). - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class DiagnosticMessageData - /// @brief Represents a Diagnostic Message in DoIP. - /// This class encapsulates data for a Diagnostic Message, including source - /// and target addresses, as well as diagnostic data. - class DiagnosticMessageData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the DiagnosticMessageData class. - /// - /// Initializes a `DiagnosticMessageData` instance with the following default values: - /// - `sourceAddress`: Set to `0x0000`. - /// - `targetAddress`: Set to `0x0000`. - /// - `diagnosticData`: Initialized to `{0x22, 0xf1, 0x68}` as a default diagnostic payload. - DiagnosticMessageData(); - - uint16_t sourceAddress; /// < Source address of the message. - uint16_t targetAddress; /// < Target address for the diagnostic message. - std::vector diagnosticData; /// < Diagnostic message data with dynamic length. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Diagnostic Message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Diagnostic Message data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Diagnostic Message payload type. It extracts fields such as `sourceAddress`, - /// `targetAddress`, and `diagnosticData` from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Message data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_MESSAGE`. - /// - Checks that the data length is sufficient for the fixed fields and dynamic `diagnosticData`. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following fields are parsed: - /// - `sourceAddress`: Source address of the diagnostic message (2 bytes). - /// - `targetAddress`: Target address of the diagnostic message (2 bytes). - /// - `diagnosticData`: Variable length data representing the diagnostic payload. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class DiagnosticAckMessageData - /// @brief Represents a Diagnostic Acknowledgment Message in DoIP. - /// - /// This class encapsulates data for a Diagnostic Acknowledgment Message, - /// including source and target addresses, as well as the acknowledgment code. - class DiagnosticAckMessageData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the DiagnosticAckMessageData class. - /// - /// Initializes a `DiagnosticAckMessageData` instance with the following default values: - /// - `sourceAddress`: Set to `0x0000`. - /// - `targetAddress`: Set to `0x0000`. - /// - `ackCode`: Set to `DoIpDiagnosticAckCodes::ACK`. - /// - `previousMessage`: Initialized to `{0x22, 0xf1, 0x01, 0x02}`. - DiagnosticAckMessageData(); - - uint16_t sourceAddress; /// < Source address of the acknowledgment message. - uint16_t targetAddress; /// < Target address of the acknowledgment message. - DoIpDiagnosticAckCodes ackCode; /// < Acknowledgment code. - std::vector previousMessage; /// < Previous acknowlged message. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Diagnostic Acknowledgment Message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Parses and initializes the Diagnostic Acknowledgment Message data from a DoIpLayer. - /// - /// This method validates the provided DoIpLayer to ensure it corresponds to the - /// Diagnostic Acknowledgment Message payload type. It extracts fields such as `sourceAddress`, - /// `targetAddress`, `ackCode`, and `previousMessage` from the payload data. - /// - /// @param[in] doipLayer const reference to the DoIpLayer containing the Diagnostic Acknowledgment Message data. - /// @return `true` if parsing and initialization were successful, `false` otherwise. - /// - /// @note The method performs the following checks: - /// - Ensures the `doipLayer` is not null. - /// - Validates that the payload type matches `DoIpPayloadTypes::DIAGNOSTIC_ACK_MESSAGE`. - /// - Checks that the data length is sufficient for the fixed fields and the dynamic `previousMessage`. - /// - /// Logs errors if the data is invalid or the payload is incompatible. - /// - /// The following fields are parsed: - /// - `sourceAddress`: Source address of the acknowledgment message (2 bytes). - /// - `targetAddress`: Target address of the acknowledgment message (2 bytes). - /// - `ackCode`: Acknowledgment code (1 byte, converted from enum). - /// - `previousMessage`: std::vector representing the previous message. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class DiagnosticNackMessageData - /// @brief Represents a Diagnostic Negative Acknowledgment Message in DoIP. - /// - /// This class encapsulates data for a Diagnostic Negative Acknowledgment - /// Message, including source and target addresses, as well as the NACK code. - class DiagnosticNackMessageData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the DiagnosticNackMessageData class. - /// - /// Initializes a `DiagnosticNackMessageData` instance with default values: - /// - `sourceAddress` is set to `0x0000`. - /// - `targetAddress` is set to `0x0000`. - /// - `nackCode` is set to `DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS`. - /// - `previousMessage` is set to {0x22, 0xf1, 01, 0x02} as the non acknowledged diagnostic - /// message starts with these four bytes - DiagnosticNackMessageData(); - - uint16_t sourceAddress; /// < Source address of the NACK message. - uint16_t targetAddress; /// < Target address of the NACK message. - DoIpDiagnosticMessageNackCodes nackCode; /// < Negative acknowledgment code. - std::vector previousMessage; /// < Previous acknowlged message. - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::DIAGNOSTIC_NACK_MESSAGE`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return A string representation of the Diagnostic Negative Acknowledgment Message. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return A vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Builds the message data from the given DoIpLayer. - /// - /// This method parses the `DoIpLayer` to extract the relevant message data, including: - /// - sourceAddress - /// - targetAddress - /// - nackCode - /// - previousMessage (optional) - /// - /// @param doipLayer The layer containing the message data to be parsed. - /// @return `true` if the message was successfully built from the layer, `false` otherwise. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class AliveCheckRequestData - /// @brief Represents an alive check request in DoIP. - class AliveCheckRequestData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the AliveCheckRequestData class. - /// - /// Initializes a `AliveCheckRequestData` instance - /// ensuring compliance with the DoIP protocol requirements. - AliveCheckRequestData(); - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ALIVE_CHECK_REQUEST`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return An empty string because Alive check request message has no additional data. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return An empty vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Builds the message data from the given DoIpLayer. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class EntityStatusRequestData - /// @brief Represents an entity status request in DoIP. - class EntityStatusRequestData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the EntityStatusRequestData class. - /// - /// Initializes a `EntityStatusRequestData` instance - /// ensuring compliance with the DoIP protocol requirements. - EntityStatusRequestData(); - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::ENTITY_STATUS_REQUEST`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return An empty string because the Alive check request message has no additional data. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return An empty vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Builds the message data from the given DoIpLayer. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class DiagnosticPowerModeRequestData - /// @brief Represents a diagnostic power mode request in DoIP. - class DiagnosticPowerModeRequestData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the DiagnosticPowerModeRequestData class. - /// - /// Initializes a `DiagnosticPowerModeRequestData` instance - /// ensuring compliance with the DoIP protocol requirements. - DiagnosticPowerModeRequestData(); - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return An empty string because diagnostic power mode message has no additional data. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return An empty vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Builds the message data from the given DoIpLayer. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; - - /// @class VehicleIdentificationRequestData - /// @brief Represents a vehicle identification request in DoIP. - class VehicleIdentificationRequestData : public IDoIpMessageData - { - public: - /// @brief Default constructor for the VehicleIdentificationRequestData class. - /// - /// Initializes a `VehicleIdentificationRequest` instance - /// ensuring compliance with the DoIP protocol requirements. - VehicleIdentificationRequestData(); - - /// @brief Returns the type of the message. - /// @return `DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST`. - DoIpPayloadTypes getType() const override; - - /// @brief Converts the message data to a human-readable string. - /// @return An empty string because Vehicle identification request message has no additional data. - std::string toString() const override; - - /// @brief Retrieves the raw binary data of the message. - /// @return An empty vector of bytes representing the message data. - std::vector getData() const override; - - /// @brief Builds the message data from the given DoIpLayer. - bool buildFromLayer(const DoIpLayer& doipLayer); - }; -} // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index a36bddcf3a..6c09015279 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -1,7 +1,6 @@ #define LOG_MODULE PacketLogModuleDoIpLayer #include "DoIpLayer.h" -#include "DoIpLayerData.h" #include "Packet.h" #include "PayloadLayer.h" #include "EndianPortable.h" @@ -9,15 +8,149 @@ #include #include #include +#include "GeneralUtils.h" namespace pcpp { - /// @brief Mapping of DoIP Protocol Versions to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each version of the - /// DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values - /// to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringProtocolVersion{ + + // This unordered map provides human-readable descriptions for each activation type + // defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values + // to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringActivationTypes{ + { DoIpActivationTypes::Default, "Default" }, + { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, + { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, + }; + + // This unordered map provides human-readable descriptions for each Nack code related to + // the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum + // values to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ + { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, + { DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, + { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, + { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, + { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, + }; + + // This unordered map provides human-readable descriptions for each action code related to + // the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum + // values to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringActionCodes{ + { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, + { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } + }; + + // This unordered map provides human-readable descriptions for each routing response code + // related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` + // enum values to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ + { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, "Routing activation denied due to unknown source address" }, + { DoIpRoutingResponseCodes::NO_FREE_SOCKET, + "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, + { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, + "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, + { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, + "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, + { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, "Routing activation denied due to missing authentication" }, + { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, "Routing activation denied due to rejected confirmation" }, + { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, + "Routing activation denied due to unsupported routing activation type" }, + { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, + "Routing activation denied due to request for encrypted connection via TLS" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, + { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } + }; + + // This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code + // related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum + // values to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, + { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, + { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, + { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, + { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, + { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, + { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, + }; + + // This unordered map provides human-readable descriptions for each power mode code + // related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum + // values to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ + { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, + { DoIpDiagnosticPowerModeCodes::READY, "ready" }, + { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, + }; + + // This unordered map provides human-readable descriptions for the entity status codes + // in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values + // to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." + static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatus::NODE, "DoIp node" }, + { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, + }; + + // This unordered map provides a human-readable description for the DoIP acknowledgement + // code `ACK`, which is used to confirm the successful reception or processing of a message. + static const std::unordered_map DoIpEnumToStringAckCode{ + { DoIpDiagnosticAckCodes::ACK, "ACK" }, + }; + + // This unordered map provides a human-readable string for each synchronization status + // defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status + // values to their respective descriptions for logging or display purposes. + static const std::unordered_map DoIpEnumToStringSyncStatus{ + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, + { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, + { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, + { DoIpSyncStatus::NON_INITIALIZED, "NULL" } + }; + + // This unordered map provides human-readable descriptions for each version of the + // DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values + // to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringProtocolVersion{ { DoIpProtocolVersion::DefaultVersion, "Default value for vehicle identification request messages" }, { DoIpProtocolVersion::Version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, { DoIpProtocolVersion::Version02Iso2012, "DoIP ISO 13400-2:2012" }, @@ -27,12 +160,10 @@ namespace pcpp { DoIpProtocolVersion::UnknownVersion, "Unknown Protocol Version" } }; - /// @brief Mapping of DoIP Payload Types to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each payload type - /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values - /// to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringPayloadType{ + // This unordered map provides human-readable descriptions for each payload type + // defined in the DoIP protocol as per ISO 13400. It maps the `DoIpPayloadTypes` enum values + // to their corresponding descriptions. + static const std::unordered_map DoIpEnumToStringPayloadType{ { DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, "Generic DOIP header Nack" }, { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, "Vehicle identification request" }, { DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, "Vehicle identification request with EID" }, @@ -53,23 +184,6 @@ namespace pcpp { DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" } }; - DoIpLayer::DoIpLayer(DoIpProtocolVersion version, const IDoIpMessageData& data) - { - initLayer(); - setProtocolVersion(version); - setInvertProtocolVersion(~(static_cast(version))); - buildLayer(data); - } - - DoIpLayer::DoIpLayer() - { - VehicleAnnouncementData data; - initLayer(); - setProtocolVersion(DoIpProtocolVersion::Version02Iso2012); - setInvertProtocolVersion(~(static_cast(DoIpProtocolVersion::Version02Iso2012))); - buildLayer(data); - } - DoIpProtocolVersion DoIpLayer::getProtocolVersion() const { uint8_t version = getDoIpHeader()->protocolVersion; @@ -89,6 +203,61 @@ namespace pcpp } } + DoIpLayer::DoIpLayer() + { + m_DataLen = sizeof(doiphdr); + m_Protocol = DOIP; + m_Data = new uint8_t[m_DataLen]{}; + } + + DoIpLayer::DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet, DOIP) + {} + + DoIpLayer* DoIpLayer::parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + { + doiphdr* doipHeader = reinterpret_cast(data); + uint16_t payloadType = doipHeader->payloadType; + DoIpPayloadTypes detectedPayloadType = static_cast(htobe16(payloadType)); + + switch (detectedPayloadType) + { + case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: + return new RoutingActivationRequest(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: + return new RoutingActivationResponse(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: + return new GenericHeaderNack(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: + return new VehicleIdentificationRequestEID(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: + return new VehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: + return new VehicleAnnouncement(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: + return new AliveCheckResponse(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: + return new DiagnosticPowerModeResponse(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: + return new EntityStatusResponse(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: + return new DiagnosticMessage(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: + return new DiagnosticAckMessage(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: + return new DiagnosticNackMessage(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: + return new VehicleIdentificationRequest(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: + return new AliveCheckRequest(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: + return new DiagnosticPowerModeRequest(data, dataLen, prevLayer, packet); + case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: + return new EntityStatusRequest(data, dataLen, prevLayer, packet); + default: + return nullptr; + } + } std::string DoIpLayer::getProtocolVersionAsStr() const { auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); @@ -110,33 +279,6 @@ namespace pcpp getDoIpHeader()->invertProtocolVersion = iVersion; } - DoIpPayloadTypes DoIpLayer::getPayloadType() const - { - switch (static_cast(be16toh(getDoIpHeader()->payloadType))) - { - case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: - case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: - case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: - case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: - case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: - case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: - case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: - case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: - case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: - case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: - case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: - case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: - case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: - case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: - case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: - case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: - return static_cast(be16toh(getDoIpHeader()->payloadType)); - - default: - return DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE; - } - } - void DoIpLayer::setPayloadType(DoIpPayloadTypes type) { getDoIpHeader()->payloadType = htobe16(static_cast(type)); @@ -144,7 +286,8 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { - auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); + auto it = + DoIpEnumToStringPayloadType.find(static_cast(be16toh(getDoIpHeader()->payloadType))); return it->second; } @@ -158,101 +301,1252 @@ namespace pcpp getDoIpHeader()->payloadLength = be32toh(payloadLength); } - bool DoIpLayer::isProtocolVersionValid() const + std::string DoIpLayer::toString() const { - DoIpProtocolVersion version = getProtocolVersion(); - uint8_t inVersion = getInvertProtocolVersion(); + std::ostringstream oss; DoIpPayloadTypes type = getPayloadType(); - if ((version == DoIpProtocolVersion::UnknownVersion) || (version == DoIpProtocolVersion::ReservedVersion) || - (version == DoIpProtocolVersion::DefaultVersion && - (type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && - type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && - type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST))) + oss << "DoIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') + << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE ? (be16toh(getDoIpHeader()->payloadType)) + : static_cast(type)) + << ")"; + + return oss.str(); + } + + void DoIpLayer::setHeaderFields(DoIpProtocolVersion version, DoIpPayloadTypes type, uint32_t length) + { + setProtocolVersion(version); + setInvertProtocolVersion(~(static_cast(version))); + setPayloadType(type); + setPayloadLength(length); + } + + void DoIpLayer::parseNextLayer() + { + if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) + { + constexpr size_t headerLen = sizeof(doiphdr); + + if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/) + return; + + uint8_t* payload = m_Data + (headerLen + 2 + 2); + size_t payloadLen = m_DataLen - (headerLen + 2 + 2); + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + // RoutingActivationRequest | + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + RoutingActivationRequest::RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + constexpr size_t headerLength = sizeof(doiphdr); + + if (dataLen < (headerLength + FIXED_LEN) || dataLen > (headerLength + OPT_LEN)) + { + throw std::runtime_error("RoutingActivationRequest: Invalid payload length"); + } + if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + { + throw std::runtime_error("RoutingActivationRequest: Invalid OEM field length"); + } + + uint8_t* dataPtr = getDataPtr(headerLength); + + memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); + dataPtr += sizeof(_sourceAddress); + + _activationType = static_cast(*dataPtr); + dataPtr += sizeof(_activationType); + + memcpy(dataPtr, &_reservedIso, DOIP_RESERVED_ISO_LEN); + dataPtr += DOIP_RESERVED_ISO_LEN; + + if (dataLen - (RESERVED_OEM_OFFSET) == DOIP_RESERVED_OEM_LEN) + { + memcpy(dataPtr, &_reservedOem, DOIP_RESERVED_OEM_LEN); + _hasReservedOem = true; + } + else + { + PCPP_LOG_DEBUG("Reserved OEM field is empty !"); + _hasReservedOem = false; + } + } + + RoutingActivationRequest::RoutingActivationRequest(uint16_t sourrceAddress, DoIpActivationTypes activationType) + : _reservedIso{}, _hasReservedOem(false) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + setSourceAddress(sourrceAddress); + setActivationType(activationType); + } + + DoIpActivationTypes RoutingActivationRequest::getActivationType() const + { + return _activationType; + } + + void RoutingActivationRequest::setActivationType(const DoIpActivationTypes& activationType) + { + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)); + memcpy(dataPtr, &activationType, sizeof(activationType)); + _activationType = activationType; + } + + uint16_t RoutingActivationRequest::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + + void RoutingActivationRequest::setSourceAddress(uint16_t sourceAddress) + { + _sourceAddress = htobe16(sourceAddress); + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); + } + + std::array RoutingActivationRequest::getReservedIso() const + { + return _reservedIso; + } + + void RoutingActivationRequest::setReservedIso(const std::array& reservedIso) + { + _reservedIso = reservedIso; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_activationType)); + memcpy(dataPtr, &_reservedIso, DOIP_RESERVED_ISO_LEN); + } + + bool RoutingActivationRequest::hasReservedOem() const + { + return _hasReservedOem; + } + + const std::array* RoutingActivationRequest::getReservedOem() const + { + return _hasReservedOem ? &_reservedOem : nullptr; + } + + void RoutingActivationRequest::setReservedOem(const std::array& reservedOem) + { + _reservedOem = reservedOem; + if (!_hasReservedOem) + { + extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + } + setPayloadLength(OPT_LEN); + memcpy(getDataPtr(RESERVED_OEM_OFFSET), &reservedOem, sizeof(_reservedOem)); + _hasReservedOem = true; + } + + void RoutingActivationRequest::clearReserveOem() + { + if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + { + shortenLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + _hasReservedOem = false; + PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); + } + if (getDataLen() == RESERVED_OEM_OFFSET) + { + PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); + } + } + std::string RoutingActivationRequest::getSummary() const + { + std::ostringstream oss; + oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; + auto it = DoIpEnumToStringActivationTypes.find(_activationType); + if (it != DoIpEnumToStringActivationTypes.end()) { - PCPP_LOG_ERROR("Invalid/unsupported DoIP version!"); - return false; + oss << "Activation type: " << it->second << std::hex << " (0x" << unsigned(_activationType) << ")\n"; } - if ((uint8_t)(version) != (uint8_t)~(inVersion)) + else { - PCPP_LOG_ERROR("Version and invert version are not synchronised !"); - return false; + oss << "Activation type: Unknown" << std::hex << " (0x" << unsigned(_activationType) << ")\n"; } - return true; + oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(_reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; + if (_hasReservedOem) + { + oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(_reservedOem.data(), DOIP_RESERVED_OEM_LEN) + << '\n'; + } + return oss.str(); } - bool DoIpLayer::isPayloadLengthValid() const + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + // RoutingActivationResponse | + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + RoutingActivationResponse::RoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) { - uint32_t length = getPayloadLength(); + constexpr size_t headerLength = sizeof(doiphdr); + if (dataLen < headerLength + FIXED_LEN || dataLen > headerLength + OPT_LEN) + { + throw std::runtime_error("RoutingActivationResponse: Invalid payload length!"); + } + + if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + { + throw std::runtime_error("RoutingActivationRequest: invalid OEM field length"); + } + + const uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); - if (length != (m_DataLen - sizeof(doiphdr))) + memcpy(&_logicalAddressExternalTester, dataPtr, sizeof(_logicalAddressExternalTester)); + dataPtr += sizeof(_logicalAddressExternalTester); + + memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); + dataPtr += sizeof(_sourceAddress); + + _responseCode = static_cast(*dataPtr++); + memcpy(&_reservedIso, dataPtr, DOIP_RESERVED_ISO_LEN); + dataPtr += DOIP_RESERVED_ISO_LEN; + + if (dataLen - (RESERVED_OEM_OFFSET) == DOIP_RESERVED_OEM_LEN) + { + memcpy(&_reservedOem, dataPtr, DOIP_RESERVED_OEM_LEN); + _hasReservedOem = true; + } + else { - PCPP_LOG_ERROR("Payload length does not match expected size"); - return false; + PCPP_LOG_DEBUG("Reserved OEM field is empty !"); + _hasReservedOem = false; } + } + RoutingActivationResponse::RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, + DoIpRoutingResponseCodes responseCode) + : _reservedIso{}, _reservedOem{}, _hasReservedOem(false) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + + setLogicalAddressExternalTester(logicalAddressExternalTester); + setSourceAddress(sourceAddress); + setResponseCode(responseCode); + } + + uint16_t RoutingActivationResponse::getLogicalAddressExternalTester() const + { + return htobe16(_logicalAddressExternalTester); + } + void RoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) + { + _logicalAddressExternalTester = htobe16(addr); + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + memcpy(dataPtr, &_logicalAddressExternalTester, sizeof(_logicalAddressExternalTester)); + } + + uint16_t RoutingActivationResponse::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + void RoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) + { + _sourceAddress = htobe16(sourceAddress); + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_logicalAddressExternalTester)); + memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); + } + + DoIpRoutingResponseCodes RoutingActivationResponse::getResponseCode() const + { + return _responseCode; + } + + void RoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) + { + _responseCode = code; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress)); + *dataPtr = static_cast(code); + } + + std::array RoutingActivationResponse::getReservedIso() const + { + return _reservedIso; + } + void RoutingActivationResponse::setReservedIso(const std::array& reservedIso) + { + _reservedIso = reservedIso; + uint8_t* dataPtr = getDataPtr(RESERVED_OEM_OFFSET - DOIP_RESERVED_ISO_LEN); + memcpy(dataPtr, &_reservedIso, sizeof(reservedIso)); + } + + bool RoutingActivationResponse::hasReservedOem() const + { + return _hasReservedOem; + } - return true; + const std::array* RoutingActivationResponse::getReservedOem() const + { + return _hasReservedOem ? &_reservedOem : nullptr; } - bool DoIpLayer::isLayerDataValid() const + void RoutingActivationResponse::setReservedOem(const std::array& reservedOem) { - // Validate the protocol version and payload length - if (!isProtocolVersionValid() || !isPayloadLengthValid()) + _reservedOem = reservedOem; + if (!_hasReservedOem) { - PCPP_LOG_ERROR("Failed to Parse DoIP layer"); - return false; + extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); } - return true; + setPayloadLength(OPT_LEN); + memcpy(getDataPtr(RESERVED_OEM_OFFSET), &_reservedOem, sizeof(_reservedOem)); + _hasReservedOem = true; } - std::string DoIpLayer::toString() const + void RoutingActivationResponse::clearReservedOem() { - if (!isLayerDataValid()) + if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + { + shortenLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + _hasReservedOem = false; + PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); + } + if (getDataLen() == RESERVED_OEM_OFFSET) { - return "DoIP Layer, malformed data"; + PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); } + } + std::string RoutingActivationResponse::getSummary() const + { + std::ostringstream ss; + ss << "Logical Address (Tester): 0x" << std::hex << htobe16(_logicalAddressExternalTester) << "\n"; + ss << "Source Address: 0x" << std::hex << htobe16(_sourceAddress) << "\n"; + auto it = DoIpEnumToStringRoutingResponseCodes.find(_responseCode); + if (it != DoIpEnumToStringRoutingResponseCodes.end()) + ss << "Routing activation response code: " << it->second << " (0x" << std::hex << unsigned(_responseCode) + << ")\n"; + else + ss << "Response Code: Unknown (0x" << std::hex << unsigned(_responseCode) << ")\n"; - std::ostringstream os; - DoIpPayloadTypes type = getPayloadType(); + ss << "Reserved by ISO: " << pcpp::byteArrayToHexString(_reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; + if (_hasReservedOem) + ss << "Reserved by OEM: " << pcpp::byteArrayToHexString(_reservedOem.data(), DOIP_RESERVED_OEM_LEN) << "\n"; - os << "DoIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') - << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE ? (be16toh(getDoIpHeader()->payloadType)) - : static_cast(type)) - << ")"; + return ss.str(); + } + + //~~~~~~~~~~~~~~~~~~~| + // GenericHeaderNack | + //~~~~~~~~~~~~~~~~~~~| + GenericHeaderNack::GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen != (sizeof(doiphdr) + sizeof(_nackCode))) + throw std::runtime_error("GenericHeaderNack: Invalid payload length!"); - return os.str(); + _nackCode = static_cast(data[sizeof(doiphdr)]); } - void DoIpLayer::initLayer() + GenericHeaderNack::GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) { - m_DataLen = sizeof(doiphdr); - m_Protocol = DOIP; - m_Data = new uint8_t[m_DataLen]{}; + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), sizeof(_nackCode)); + extendLayer(sizeof(doiphdr), sizeof(_nackCode)); + setNackCode(nackCode); } - void DoIpLayer::buildLayer(const IDoIpMessageData& data) + DoIpGenericHeaderNackCodes GenericHeaderNack::getNackCode() const { - size_t payloadSize = data.getData().size(); - size_t headerLength = sizeof(doiphdr); + return _nackCode; + } - setPayloadType(data.getType()); - setPayloadLength(payloadSize); - extendLayer(headerLength, payloadSize); - memcpy(m_Data + headerLength, data.getData().data(), payloadSize); + void GenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) + { + _nackCode = nackCode; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + *dataPtr = static_cast(nackCode); } - void DoIpLayer::parseNextLayer() + std::string GenericHeaderNack::getSummary() const { - if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) + std::ostringstream ss; + auto it = DoIpEnumToStringGenericHeaderNackCodes.find(_nackCode); + if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) + { + ss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(_nackCode) + << ")\n"; + } + else { - size_t headerLen = sizeof(doiphdr); + ss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(_nackCode) << ")\n"; + } + return ss.str(); + } - if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/) - return; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequestEID | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen != sizeof(doiphdr) + DOIP_EID_LEN) + throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); - uint8_t* payload = m_Data + (headerLen + 2 + 2); - size_t payloadLen = m_DataLen - (headerLen + 2 + 2); - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - } + memcpy(&_eid, data + sizeof(doiphdr), DOIP_EID_LEN); + } + + VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid) + : _eid(eid) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); + extendLayer(sizeof(doiphdr), DOIP_EID_LEN); + setEID(eid); + } + + std::array VehicleIdentificationRequestEID::getEID() const + { + return _eid; + } + + void VehicleIdentificationRequestEID::setEID(const std::array& eid) + { + _eid = eid; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + memcpy(dataPtr, &_eid, DOIP_EID_LEN); + } + + std::string VehicleIdentificationRequestEID::getSummary() const + { + std::ostringstream oss; + oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DOIP_EID_LEN) << "\n"; + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequestVIN | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen != sizeof(doiphdr) + DOIP_VIN_LEN) + throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length"); + + memcpy(&_vin, data + sizeof(doiphdr), DOIP_VIN_LEN); + } + + VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); + extendLayer(sizeof(doiphdr), DOIP_VIN_LEN); + setVIN(vin); + } + + std::array VehicleIdentificationRequestVIN::getVIN() const + { + return _vin; + } + + void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) + { + _vin = vin; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + memcpy(dataPtr, &_vin, DOIP_VIN_LEN); + } + + std::string VehicleIdentificationRequestVIN::getSummary() const + { + std::ostringstream oss; + oss << "VIN: " << std::string(reinterpret_cast(_vin.data()), _vin.size()) << "\n"; + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~| + // VehicleAnnouncement | + //~~~~~~~~~~~~~~~~~~~~~| + VehicleAnnouncement::VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + uint8_t* dataPtr = data + sizeof(doiphdr); + + if (dataLen < SYNC_STATUS_OFFSET || dataLen > sizeof(doiphdr) + OPT_LEN) + { + throw std::runtime_error("VehicleAnnouncement: invalid payload length!"); + } + + memcpy(&_vin, dataPtr, DOIP_VIN_LEN); + dataPtr += DOIP_VIN_LEN; + + memcpy(&_logicalAddress, dataPtr, sizeof(_logicalAddress)); + dataPtr += sizeof(_logicalAddress); + + memcpy(&_eid, dataPtr, DOIP_EID_LEN); + dataPtr += DOIP_EID_LEN; + + memcpy(&_gid, dataPtr, DOIP_GID_LEN); + dataPtr += DOIP_GID_LEN; + + _actionCode = static_cast(*(dataPtr++)); + + if (dataLen - SYNC_STATUS_OFFSET == sizeof(_syncStatus)) + { + _syncStatus = static_cast(*(dataPtr)); + _hasSyncStatus = true; + } + else + { + PCPP_LOG_INFO("Sync status field is empty!"); + _hasSyncStatus = false; + } + } + + VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, DoIpActionCodes actionCode) + + : _vin(vin), _logicalAddress(logicalAddress), _eid(eid), _gid(gid), _actionCode(actionCode), + _hasSyncStatus(false) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + + setVIN(vin); + setLogicalAddress(logicalAddress); + setEID(eid); + setGID(gid); + setFurtherActionRequired(actionCode); + } + std::array VehicleAnnouncement::getVIN() const + { + return _vin; + } + uint16_t VehicleAnnouncement::getLogicalAddress() const + { + return htobe16(_logicalAddress); + } + + std::array VehicleAnnouncement::getEID() const + { + return _eid; + } + std::array VehicleAnnouncement::getGID() const + { + return _gid; + } + DoIpActionCodes VehicleAnnouncement::getFurtherActionRequired() const + { + return _actionCode; + } + const DoIpSyncStatus* VehicleAnnouncement::getSyncStatus() const + { + return _hasSyncStatus ? &_syncStatus : nullptr; + } + + void VehicleAnnouncement::clearSyncStatus() + { + if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + { + shortenLayer(FIXED_LEN, sizeof(_syncStatus)); + _hasSyncStatus = false; + PCPP_LOG_INFO("Sync status has been removed successfully!"); + } + if (getDataLen() == SYNC_STATUS_OFFSET) + { + PCPP_LOG_DEBUG("doip packet has no syncStatus!"); + } + } + void VehicleAnnouncement::setVIN(const std::array& vin) + { + _vin = vin; + memcpy(getDataPtr(sizeof(doiphdr)), &_vin, DOIP_VIN_LEN); + } + + void VehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) + { + _logicalAddress = htobe16(logicalAddress); + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN); + memcpy(dataPtr, &_logicalAddress, sizeof(_logicalAddress)); + } + + void VehicleAnnouncement::setEID(const std::array& eid) + { + _eid = eid; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress)); + memcpy(dataPtr, &_eid, DOIP_EID_LEN); + } + + void VehicleAnnouncement::setGID(const std::array& gid) + { + _gid = gid; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN); + memcpy(dataPtr, &_gid, DOIP_GID_LEN); + } + + void VehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) + { + _actionCode = action; + uint8_t* dataPtr = + getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN); + *dataPtr = static_cast(action); + } + + void VehicleAnnouncement::setSyncStatus(DoIpSyncStatus sync) + { + _syncStatus = sync; + if (!_hasSyncStatus) + { + extendLayer(SYNC_STATUS_OFFSET, sizeof(_syncStatus)); + } + setPayloadLength(OPT_LEN); + *getDataPtr(SYNC_STATUS_OFFSET) = static_cast(_syncStatus); + _hasSyncStatus = true; + } + + bool VehicleAnnouncement::hasSyncStatus() const + { + return _hasSyncStatus; + } + + std::string VehicleAnnouncement::getSummary() const + { + std::ostringstream oss; + + oss << "VIN: " << std::string(reinterpret_cast(_vin.data()), _vin.size()) << "\n"; + oss << "Logical address: " << std::hex << "0x" << htobe16(_logicalAddress) << "\n"; + oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DOIP_EID_LEN) << "\n"; + oss << "GID: " << pcpp::byteArrayToHexString(_gid.data(), DOIP_GID_LEN) << "\n"; + auto it = DoIpEnumToStringActionCodes.find(_actionCode); + if (it != DoIpEnumToStringActionCodes.end()) + { + oss << "Further action required: " << it->second << std::hex << " (0x" << unsigned(_actionCode) << ")" + << "\n"; + } + else + { + oss << "Further action required: Unknown" << std::hex << " (0x" << unsigned(_actionCode) << ")" + << "\n"; + } + if (_hasSyncStatus) + { + auto it_ = DoIpEnumToStringSyncStatus.find(_syncStatus); + if (it_ != DoIpEnumToStringSyncStatus.end()) + { + oss << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte + } + else + { + oss << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(_syncStatus) << ")" << "\n"; + } + } + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~| + // AliveCheckResponse | + //~~~~~~~~~~~~~~~~~~~~| + AliveCheckResponse::AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen < sizeof(doiphdr) + sizeof(_sourceAddress)) + throw std::runtime_error("AliveCheckResponse: insufficient payload length"); + + const uint8_t* dataPtr = data + sizeof(doiphdr); + memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); + } + + AliveCheckResponse::AliveCheckResponse(uint16_t sourceAddress) + { + const size_t payloadLen = sizeof(_sourceAddress); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); + extendLayer(sizeof(doiphdr), payloadLen); + setSourceAddress(sourceAddress); + } + + uint16_t AliveCheckResponse::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + + void AliveCheckResponse::setSourceAddress(uint16_t address) + { + _sourceAddress = htobe16(address); + memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + } + + std::string AliveCheckResponse::getSummary() const + { + std::ostringstream oss; + oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticPowerModeResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DiagnosticPowerModeResponse::DiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + constexpr size_t payloadLen = sizeof(doiphdr) + sizeof(_powerModeCode); + if (dataLen != payloadLen) + throw std::runtime_error("DiagnosticPowerModeResponse: invalid payload length!"); + + const uint8_t* payloadPtr = data + sizeof(doiphdr); + _powerModeCode = static_cast(*payloadPtr); + } + + DiagnosticPowerModeResponse::DiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) : _powerModeCode(code) + { + const size_t payloadLen = sizeof(_powerModeCode); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); + extendLayer(sizeof(doiphdr), payloadLen); + setPowerModeCode(code); + } + + DoIpDiagnosticPowerModeCodes DiagnosticPowerModeResponse::getPowerModeCode() const + { + return _powerModeCode; + } + + void DiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) + { + _powerModeCode = code; + uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + *dataPtr = static_cast(code); + } + + std::string DiagnosticPowerModeResponse::getSummary() const + { + std::ostringstream oss; + auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(_powerModeCode); + if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) + { + oss << "Diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(_powerModeCode) << ")\n"; + } + else + { + oss << "Diagnostic power mode: Unknown" << std::hex << " (0x" << unsigned(_powerModeCode) << ")\n"; + } + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~| + // EntityStatusResponse| + //~~~~~~~~~~~~~~~~~~~~~| + EntityStatusResponse::EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + constexpr size_t headerLength = sizeof(doiphdr); + if (dataLen < headerLength + FIXED_LEN || dataLen > headerLength + OPT_LEN) + { + throw std::runtime_error("EntityStatusResponse: Invalid payload length!"); + } + + if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + { + throw std::runtime_error("EntityStatusResponse: Invalid MaxDataSize field length!"); + } + + const uint8_t* dataPtr = data + sizeof(doiphdr); + _nodeType = static_cast(*dataPtr); + dataPtr += sizeof(_nodeType); + + _maxConcurrentSockets = (*dataPtr); + dataPtr += sizeof(_maxConcurrentSockets); + + _currentlyOpenSockets = (*dataPtr); + dataPtr += sizeof(_currentlyOpenSockets); + + if (dataLen - (MAX_DATA_SIZE_OFFSET) == sizeof(_maxDataSize)) + { + memcpy(&_maxDataSize, dataPtr, sizeof(_maxDataSize)); + _hasMaxDataSize = true; + } + else + { + PCPP_LOG_INFO("MaxDataSize field is empty !"); + _hasMaxDataSize = false; + } + } + + EntityStatusResponse::EntityStatusResponse(DoIpEntityStatus nodeType, uint8_t maxConcurrentSockets, + uint8_t currentlyOpenSockets) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + + setNodeType(nodeType); + setMaxConcurrentSockets(maxConcurrentSockets); + setCurrentlyOpenSockets(currentlyOpenSockets); + } + DoIpEntityStatus EntityStatusResponse::getNodeType() const + { + return _nodeType; + } + uint8_t EntityStatusResponse::getMaxConcurrentSockets() const + { + return _maxConcurrentSockets; + } + uint8_t EntityStatusResponse::getCurrentlyOpenSockets() const + { + return _currentlyOpenSockets; + } + const std::array* EntityStatusResponse::getMaxDataSize() const + { + return _hasMaxDataSize ? &_maxDataSize : nullptr; + } + void EntityStatusResponse::setNodeType(DoIpEntityStatus nodeType) + { + _nodeType = nodeType; + getDataPtr(sizeof(doiphdr))[0] = static_cast(nodeType); + } + bool EntityStatusResponse::hasMaxDataSize() const + { + return _hasMaxDataSize; + } + void EntityStatusResponse::clearMaxDataSize() + { + if (getDataLen() == sizeof(doiphdr) + OPT_LEN && _hasMaxDataSize) + { + shortenLayer(FIXED_LEN, sizeof(_maxDataSize)); + _hasMaxDataSize = false; + PCPP_LOG_INFO("MaxDataSize has been removed successfully!"); + } + else + { + PCPP_LOG_DEBUG("doip packet has no MaxDataSize field!"); + } + } + void EntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) + { + _maxConcurrentSockets = sockets; + getDataPtr(sizeof(doiphdr))[1] = sockets; + } + + void EntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) + { + _currentlyOpenSockets = sockets; + getDataPtr(sizeof(doiphdr))[2] = sockets; + } + + void EntityStatusResponse::setMaxDataSize(const std::array& data) + { + _maxDataSize = data; + if (!_hasMaxDataSize) + { + extendLayer(MAX_DATA_SIZE_OFFSET, sizeof(_maxDataSize)); + } + memcpy(getDataPtr(MAX_DATA_SIZE_OFFSET), &_maxDataSize, sizeof(_maxDataSize)); + setPayloadLength(OPT_LEN); + _hasMaxDataSize = true; + } + + std::string EntityStatusResponse::getSummary() const + { + std::ostringstream oos; + auto it = DoIpEnumToStringEntityStatusNodeTypes.find(_nodeType); + if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) + { + oos << "Entity status: " << it->second << std::hex << " (0x" << unsigned(_nodeType) << ")" << "\n"; + } + else + { + oos << "Node Type: Unknown" << std::hex << " (0x" << unsigned(_nodeType) << ")\n"; + } + oos << "Max Concurrent Socket: " << unsigned(_maxConcurrentSockets) << "\n"; + oos << "Currently Opened Socket: " << unsigned(_currentlyOpenSockets) << "\n"; + if (_hasMaxDataSize) + { + oos << "Max Data Size: " + << "0x" << pcpp::byteArrayToHexString(_maxDataSize.data(), 4) << "\n"; + } + return oos.str(); + } + + //~~~~~~~~~~~~~~~~~~| + // DiagnosticMessage| + //~~~~~~~~~~~~~~~~~~| + DiagnosticMessage::DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen < + sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress) + 1 /*Minimum diag payload len*/) + throw std::runtime_error("DiagnosticMessage: insufficient payload"); + + const uint8_t* dataPtr = data + sizeof(doiphdr); + memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); + dataPtr += (sizeof(_sourceAddress)); + memcpy(&_targetAddress, dataPtr, sizeof(_targetAddress)); + dataPtr += (sizeof(_targetAddress)); + + _diagnosticData.assign( + dataPtr, dataPtr + (dataLen - (sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)))); + } + + DiagnosticMessage::DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, + const std::vector& diagData) + { + size_t payloadLen = sizeof(_sourceAddress) + sizeof(_targetAddress) + _diagnosticData.size(); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); + extendLayer(sizeof(doiphdr), payloadLen); + setSourceAddress(sourceAddress); + setTargetAddress(targetAddress); + setDiagnosticData(diagData); + } + + uint16_t DiagnosticMessage::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + uint16_t DiagnosticMessage::getTargetAddress() const + { + return htobe16(_targetAddress); + } + const std::vector& DiagnosticMessage::getDiagnosticData() const + { + return _diagnosticData; + } + + void DiagnosticMessage::setSourceAddress(uint16_t address) + { + _sourceAddress = htobe16(address); + memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + } + + void DiagnosticMessage::setTargetAddress(uint16_t targetAddress) + { + _targetAddress = htobe16(targetAddress); + memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + } + + void DiagnosticMessage::setDiagnosticData(const std::vector& data) + { + constexpr size_t fixedLen = sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress); + const size_t newPayloadlLength = sizeof(_sourceAddress) + sizeof(_targetAddress) + data.size(); + uint8_t* dataPtr = getDataPtr(fixedLen); + setPayloadLength(newPayloadlLength); + // always clear the current diagnostic data and extendLayer with the new provided data + if (_diagnosticData.size() > 0) + { + shortenLayer(fixedLen, _diagnosticData.size()); + } + extendLayer(fixedLen, data.size()); + memcpy(dataPtr, data.data(), data.size()); + _diagnosticData = data; + } + + std::string DiagnosticMessage::getSummary() const + { + std::ostringstream oss; + oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; + oss << "Target Address: " << std::hex << "0x" << getTargetAddress() << "\n"; + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticAckMessage| + //~~~~~~~~~~~~~~~~~~~~~| + DiagnosticAckMessage::DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen < PREVIOUS_MSG_OFFSET) + throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); + + const uint8_t* ptr = data + sizeof(doiphdr); + memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); + ptr += sizeof(_sourceAddress); + + memcpy(&_targetAddress, ptr, sizeof(_targetAddress)); + ptr += sizeof(_targetAddress); + + _ackCode = static_cast(*ptr++); + + const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); + if (remainingData > 0) + { + _previousMessage.assign(ptr, ptr + remainingData); + _hasPreviousMessage = true; + } + else + { + PCPP_LOG_INFO("PreviousMessage field is empty!"); + _hasPreviousMessage = false; + } + } + + DiagnosticAckMessage::DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticAckCodes ackCode) + : _hasPreviousMessage(false) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + + setSourceAddress(sourceAddress); + setTargetAddress(targetAddress); + setAckCode(ackCode); + } + + uint16_t DiagnosticAckMessage::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + uint16_t DiagnosticAckMessage::getTargetAddress() const + { + return htobe16(_targetAddress); + } + DoIpDiagnosticAckCodes DiagnosticAckMessage::getAckCode() const + { + return _ackCode; + } + const std::vector* DiagnosticAckMessage::getPreviousMessage() const + { + return _hasPreviousMessage ? &_previousMessage : nullptr; + } + + // Setter implementations. + void DiagnosticAckMessage::setSourceAddress(uint16_t address) + { + _sourceAddress = htobe16(address); + // Write sourceAddress into payload at offset 0 (immediately after doiphdr) + memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + } + + void DiagnosticAckMessage::setTargetAddress(uint16_t address) + { + _targetAddress = htobe16(address); + memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + } + + void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) + { + _ackCode = code; + uint8_t* ptr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)); + *ptr = static_cast(code); + } + + bool DiagnosticAckMessage::hasPreviousMessage() + { + return _hasPreviousMessage; + } + + void DiagnosticAckMessage::setPreviousMessage(const std::vector& msg) + { + + size_t newPayloadLen = FIXED_LEN + msg.size(); + // clear memory for old previous message + if (_hasPreviousMessage) + { + shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + } + setPayloadLength(newPayloadLen); + extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); + uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); + memcpy(ptr, msg.data(), msg.size()); + _previousMessage = msg; + _hasPreviousMessage = true; + } + + void DiagnosticAckMessage::clearPreviousMessage() + { + if (_hasPreviousMessage) + { + shortenLayer(FIXED_LEN, sizeof(_previousMessage)); + _hasPreviousMessage = false; + PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); + } + else + { + PCPP_LOG_DEBUG("doip packet has no PreviousMessage field!"); + } + } + // Summary method. + std::string DiagnosticAckMessage::getSummary() const + { + std::ostringstream oss; + oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; + oss << "Target Address: " << std::hex << "0x" << getTargetAddress() << "\n"; + auto it = DoIpEnumToStringAckCode.find(_ackCode); + if (it != DoIpEnumToStringAckCode.end()) + { + oss << "ACK code: " << it->second << " (0x" << unsigned(_ackCode) << ")\n"; + } + else + { + oss << "ACK code: Unknown" << std::hex << " (0x" << unsigned(_ackCode) << ")\n"; + } + if (_hasPreviousMessage) + { + oss << "Previous message: " << pcpp::byteArrayToHexString(_previousMessage.data(), _previousMessage.size()) + << "\n"; + } + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticNackMessage| + //~~~~~~~~~~~~~~~~~~~~~~| + DiagnosticNackMessage::DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpLayer(data, dataLen, prevLayer, packet) + { + if (dataLen < PREVIOUS_MSG_OFFSET) + throw std::runtime_error("DiagnosticNackMessage: Invalid payload length"); + + const uint8_t* ptr = data + sizeof(doiphdr); + memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); + ptr += sizeof(_sourceAddress); + + memcpy(&_targetAddress, ptr, sizeof(_targetAddress)); + ptr += sizeof(_targetAddress); + + _nackCode = static_cast(*ptr++); + + const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); + if (remainingData > 0) + { + _previousMessage.assign(ptr, ptr + remainingData); + _hasPreviousMessage = true; + } + else + { + PCPP_LOG_INFO("PreviousMessage field is empty!"); + _hasPreviousMessage = false; + } + } + + DiagnosticNackMessage::DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticMessageNackCodes nackCode) + : _hasPreviousMessage(false) + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); + extendLayer(sizeof(doiphdr), FIXED_LEN); + + setSourceAddress(sourceAddress); + setTargetAddress(targetAddress); + setNackCode(nackCode); + } + + uint16_t DiagnosticNackMessage::getSourceAddress() const + { + return htobe16(_sourceAddress); + } + uint16_t DiagnosticNackMessage::getTargetAddress() const + { + return htobe16(_targetAddress); + } + DoIpDiagnosticMessageNackCodes DiagnosticNackMessage::getNackCode() const + { + return _nackCode; + } + const std::vector* DiagnosticNackMessage::getPreviousMessage() const + { + return _hasPreviousMessage ? &_previousMessage : nullptr; + } + bool DiagnosticNackMessage::hasPreviousMessage() const + { + return _hasPreviousMessage; + } + + void DiagnosticNackMessage::setSourceAddress(uint16_t address) + { + _sourceAddress = htobe16(address); + memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + } + + void DiagnosticNackMessage::setTargetAddress(uint16_t address) + { + _targetAddress = htobe16(address); + memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + } + + void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) + { + _nackCode = code; + uint8_t* ptr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)); + *ptr = static_cast(code); + } + + void DiagnosticNackMessage::setPreviousMessage(const std::vector& msg) + { + const size_t newPayloadLen = FIXED_LEN + msg.size(); + + if (_hasPreviousMessage) + { + shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + } + + setPayloadLength(newPayloadLen); + extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); + + uint8_t* dataPtr = getDataPtr(PREVIOUS_MSG_OFFSET); + memcpy(dataPtr, msg.data(), msg.size()); + + _previousMessage = msg; + _hasPreviousMessage = true; + } + + void DiagnosticNackMessage::clearPreviousMessage() + { + if (_hasPreviousMessage) + { + shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + _hasPreviousMessage = false; + PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); + } + else + { + PCPP_LOG_DEBUG("doip packet has no PreviousMessage field!"); + } + } + + std::string DiagnosticNackMessage::getSummary() const + { + std::ostringstream oss; + oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; + oss << "Target Address: 0x" << std::hex << getTargetAddress() << "\n"; + + auto it = DoIpEnumToStringDiagnosticNackCodes.find(_nackCode); + if (it != DoIpEnumToStringDiagnosticNackCodes.end()) + { + oss << "NACK code: " << it->second << " (0x" << unsigned(_nackCode) << ")\n"; + } + else + { + oss << "NACK code: Unknown (0x" << unsigned(_nackCode) << ")\n"; + } + + if (_hasPreviousMessage) + { + oss << "Previous message: " << pcpp::byteArrayToHexString(_previousMessage.data(), _previousMessage.size()) + << "\n"; + } + return oss.str(); + } + + //~~~~~~~~~~~~~~~~~~| + // AliveCheckRequest| + //~~~~~~~~~~~~~~~~~~| + AliveCheckRequest::AliveCheckRequest() + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + VehicleIdentificationRequest::VehicleIdentificationRequest() + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticPowerModeRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DiagnosticPowerModeRequest::DiagnosticPowerModeRequest() + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + } + + //~~~~~~~~~~~~~~~~~~~~| + // EntityStatusRequest| + //~~~~~~~~~~~~~~~~~~~~| + EntityStatusRequest::EntityStatusRequest() + { + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } } // namespace pcpp diff --git a/Packet++/src/DoIpLayerData.cpp b/Packet++/src/DoIpLayerData.cpp deleted file mode 100644 index a01f24ad6b..0000000000 --- a/Packet++/src/DoIpLayerData.cpp +++ /dev/null @@ -1,1189 +0,0 @@ -#include "DoIpLayerData.h" -#include "DoIpLayer.h" -#include "GeneralUtils.h" -#include -namespace pcpp -{ - /// @brief Mapping of DoIP Activation Types to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each activation type - /// defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values - /// to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringActivationTypes{ - { DoIpActivationTypes::Default, "Default" }, - { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, - { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, - }; - - /// @brief Mapping of DoIP Generic Header Nack Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each Nack code related to - /// the DoIP Generic Header as per ISO 13400. It maps the `DoIpGenericHeaderNackCodes` enum - /// values to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringGenericHeaderNackCodes{ - { DoIpGenericHeaderNackCodes::INCORRECT_PATTERN, "Incorrect pattern format" }, - { DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" }, - { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, - { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, - { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, - }; - - /// @brief Mapping of DoIP Action Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each action code related to - /// the DoIP announcement message, as per ISO 13400. It maps the `DoIpActionCodes` enum - /// values to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringActionCodes{ - { DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED, "No further action required" }, - { DoIpActionCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } - }; - - /// @brief Mapping of DoIP Routing Response Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each routing response code - /// related to the DoIP routing activation process, as per ISO 13400. It maps the `DoIpRoutingResponseCodes` - /// enum values to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringRoutingResponseCodes{ - { DoIpRoutingResponseCodes::UNKNOWN_SOURCE_ADDRESS, "Routing activation denied due to unknown source address" }, - { DoIpRoutingResponseCodes::NO_FREE_SOCKET, - "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active" }, - { DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS, - "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket" }, - { DoIpRoutingResponseCodes::SOURCE_ADDRESS_ALREADY_REGISTERED, - "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket" }, - { DoIpRoutingResponseCodes::MISSING_AUTHENTICATION, "Routing activation denied due to missing authentication" }, - { DoIpRoutingResponseCodes::REJECTED_CONFIRMATION, "Routing activation denied due to rejected confirmation" }, - { DoIpRoutingResponseCodes::UNSUPPORTED_ACTIVATION_TYPE, - "Routing activation denied due to unsupported routing activation type" }, - { DoIpRoutingResponseCodes::ENCRYPTED_CONNECTION_TLS, - "Routing activation denied due to request for encrypted connection via TLS" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, - { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } - }; - - /// @brief Mapping of DoIP Diagnostic Message Nack Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code - /// related to DoIP diagnostic messages, as per ISO 13400. It maps the `DoIpDiagnosticMessageNackCodes` enum - /// values to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringDiagnosticNackCodes{ - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x00, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, "Invalid source address" }, - { DoIpDiagnosticMessageNackCodes::INVALID_TARGET_ADDRESS, "Unknown target address" }, - { DoIpDiagnosticMessageNackCodes::MESSAGE_TOO_LARGE, "Diagnostic message too large" }, - { DoIpDiagnosticMessageNackCodes::OUT_OF_MEMORY, "Out of memory" }, - { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, - { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, - { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, - }; - - /// @brief Mapping of DoIP Diagnostic Power Mode Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for each power mode code - /// related to DoIP diagnostics, as per ISO 13400. It maps the `DoIpDiagnosticPowerMode` enum - /// values to their corresponding descriptions. - const std::unordered_map DoIpEnumToStringDiagnosticPowerModeCodes{ - { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, - { DoIpDiagnosticPowerModeCodes::READY, "ready" }, - { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, - }; - - /// @brief Mapping of DoIP Entity Status Codes to their respective string descriptions. - /// - /// This unordered map provides human-readable descriptions for the entity status codes - /// in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values - /// to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." - const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatus::NODE, "DoIp node" }, - { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, - }; - - /// @brief Mapping of DoIP Acknowledgement Codes to their string representations. - /// - /// This unordered map provides a human-readable description for the DoIP acknowledgement - /// code `ACK`, which is used to confirm the successful reception or processing of a message. - const std::unordered_map DoIpEnumToStringAckCode{ - { DoIpDiagnosticAckCodes::ACK, "ACK" }, - }; - - /// @brief A mapping of DoIP synchronization statuses to their corresponding string descriptions. - /// - /// This unordered map provides a human-readable string for each synchronization status - /// defined in the `DoIpSyncStatus` enumeration. It is used to convert synchronization status - /// values to their respective descriptions for logging or display purposes. - const std::unordered_map DoIpEnumToStringSyncStatus{ - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, "VIN and/or GID are synchronized" }, - { DoIpSyncStatus::RESERVED_ISO_0x01, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x02, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x03, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x04, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x05, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x06, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x07, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x08, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x09, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0A, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0B, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0C, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, - { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, - { DoIpSyncStatus::NON_INITIALIZED, "NULL" } - }; - - RoutingActivationRequestData::RoutingActivationRequestData() - : sourceAddress(0x0000), activationType(DoIpActivationTypes::Default), reservedIso{}, reservedOem(nullptr) {}; - - DoIpPayloadTypes RoutingActivationRequestData::getType() const - { - return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; - } - - std::string RoutingActivationRequestData::toString() const - { - std::stringstream os; - os << "sourceAddress: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = DoIpEnumToStringActivationTypes.find(activationType); - if (it != DoIpEnumToStringActivationTypes.end()) - { - os << "activation type: " << it->second << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; - } - else - { - os << "activation type: Unknown" << std::hex << " (0x" << unsigned(activationType) << ")" << "\n"; - } - os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; - if (reservedOem) - { - os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) << '\n'; - } - return os.str(); - } - - std::vector RoutingActivationRequestData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(sourceAddress & 0xFF)); - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - data.push_back(static_cast(activationType)); - data.insert(data.end(), reservedIso.begin(), reservedIso.end()); - if (reservedOem) - { - data.insert(data.end(), reservedOem->begin(), reservedOem->end()); - } - return data; - } - - // buildFromLayer implementation - bool RoutingActivationRequestData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve routing activation request data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(activationType) + DOIP_RESERVED_ISO_LEN; - - if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for routing activation request payload"); - return false; - } - - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - dataPtr += sizeof(sourceAddress); - - activationType = static_cast(dataPtr[0]); - dataPtr += sizeof(activationType); - - std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); - dataPtr += DOIP_RESERVED_ISO_LEN; - - if (doipLayer.getDataLen() - (sizeof(doiphdr) + fixedFieldLength) == DOIP_RESERVED_OEM_LEN) - { - reservedOem = std::unique_ptr>( - new std::array()); - std::copy(dataPtr, dataPtr + DOIP_RESERVED_OEM_LEN, reservedOem->begin()); - } - else - { - PCPP_LOG_DEBUG("Reserved OEM field is empty or has invalid size !"); - reservedOem.reset(); - } - return true; - } - - // Routing Response function definition - RoutingActivationResponseData::RoutingActivationResponseData() - : logicalAddressExternalTester(0x0000), sourceAddress(0x0000), - responseCode(DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED), reservedIso{}, reservedOem(nullptr) - {} - - DoIpPayloadTypes RoutingActivationResponseData::getType() const - { - return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE; - } - - std::string RoutingActivationResponseData::toString() const - { - std::stringstream os; - os << "logical address of external tester: " << std::hex << "0x" << htobe16(logicalAddressExternalTester) - << "\n"; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - auto it = DoIpEnumToStringRoutingResponseCodes.find(responseCode); - if (it != DoIpEnumToStringRoutingResponseCodes.end()) - { - os << "routing activation response code: " << it->second << std::hex << " (0x" << unsigned(responseCode) - << ")" << "\n"; - } - else - { - os << "routing activation response code: Unknown" << std::hex << " (0x" << unsigned(responseCode) << ")" - << "\n"; - } - os << "reserved by ISO: " << pcpp::byteArrayToHexString(reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; - if (reservedOem) - { - os << "Reserved by OEM: " << pcpp::byteArrayToHexString(reservedOem->data(), DOIP_RESERVED_OEM_LEN) << "\n"; - } - return os.str(); - } - std::vector RoutingActivationResponseData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(logicalAddressExternalTester & 0xFF)); - data.push_back(static_cast((logicalAddressExternalTester >> 8) & 0xFF)); - - data.push_back(static_cast(sourceAddress & 0xFF)); - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - - data.push_back(static_cast(responseCode)); // Convert enum to byte - data.insert(data.end(), reservedIso.begin(), reservedIso.end()); - if (reservedOem) - { - data.insert(data.end(), reservedOem->begin(), reservedOem->end()); - } - return data; - } - - bool RoutingActivationResponseData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve routing activation response data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - if (doipLayer.getDataLen() - sizeof(doiphdr) < - sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) - { - PCPP_LOG_ERROR("Insufficient data length for routing activation response payload"); - return false; - } - - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - logicalAddressExternalTester = static_cast(dataPtr[1] << 8 | dataPtr[0]); - dataPtr += sizeof(logicalAddressExternalTester); - - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - dataPtr += sizeof(sourceAddress); - - responseCode = static_cast(dataPtr[0]); - dataPtr += sizeof(responseCode); - - std::copy(dataPtr, dataPtr + DOIP_RESERVED_ISO_LEN, reservedIso.begin()); - dataPtr += DOIP_RESERVED_ISO_LEN; - - if (doipLayer.getDataLen() - (sizeof(doiphdr) + sizeof(logicalAddressExternalTester) + sizeof(sourceAddress) + - sizeof(responseCode) + DOIP_RESERVED_ISO_LEN) == - DOIP_RESERVED_OEM_LEN) - { - reservedOem = std::unique_ptr>( - new std::array()); - std::copy(dataPtr, dataPtr + DOIP_RESERVED_OEM_LEN, reservedOem->begin()); - } - else - { - PCPP_LOG_DEBUG("Reserved OEM field is empty or has invalid size !"); - reservedOem.reset(); // Clear reservedOem if not present - } - - return true; - } - - // Generic header nack function definition - GenericHeaderNackData::GenericHeaderNackData() : genericNackCode(DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH) - {} - - DoIpPayloadTypes GenericHeaderNackData::getType() const - { - return DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK; - } - - std::string GenericHeaderNackData::toString() const - { - std::stringstream os; - auto it = DoIpEnumToStringGenericHeaderNackCodes.find(genericNackCode); - if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) - { - os << "generic header nack code: " << it->second << std::hex << " (0x" << unsigned(genericNackCode) << ")" - << "\n"; - } - else - { - os << "generic header nack code: Unknown" << std::hex << " (0x" << unsigned(genericNackCode) << ")" << "\n"; - } - return os.str(); - } - std::vector GenericHeaderNackData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(genericNackCode)); // Convert enum to byte - return data; - } - - // buildFromLayer fun implementation - bool GenericHeaderNackData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Generic Header NACK data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate data length (1 byte is expected for genericNackCode) - if (doipLayer.getDataLen() - sizeof(doiphdr) < 1) - { - PCPP_LOG_ERROR("Insufficient data length for Generic Header NACK payload"); - return false; - } - - // Extract the NACK code (1 byte) - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - genericNackCode = static_cast(dataPtr[0]); - - return true; - } - - // vehicle ideentification with EID functions definition - VehicleIdentificationRequestEIDData::VehicleIdentificationRequestEIDData() : eid{} - {} - DoIpPayloadTypes VehicleIdentificationRequestEIDData::getType() const - { - return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID; - } - std::string VehicleIdentificationRequestEIDData::toString() const - { - std::stringstream os; - os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; - return os.str(); - } - std::vector VehicleIdentificationRequestEIDData::getData() const - { - // Copy each field's data into the vector - return std::vector(eid.begin(), eid.end()); - } - - bool VehicleIdentificationRequestEIDData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with EID data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate data length (must at least accommodate EID length) - if (doipLayer.getDataLen() - sizeof(doiphdr) != DOIP_EID_LEN) - { - PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); - return false; - } - - // Extract the EID - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - std::copy(dataPtr, dataPtr + DOIP_EID_LEN, eid.begin()); - - return true; - } - - // vehicle ideentification with VIN functions definition - VehicleIdentificationRequestVINData::VehicleIdentificationRequestVINData() : vin{} - {} - DoIpPayloadTypes VehicleIdentificationRequestVINData::getType() const - { - return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN; - } - std::string VehicleIdentificationRequestVINData::toString() const - { - std::stringstream os; - os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << "\n"; - return os.str(); - } - std::vector VehicleIdentificationRequestVINData::getData() const - { - // Copy each field's data into the vector - return std::vector(vin.begin(), vin.end()); - } - - bool VehicleIdentificationRequestVINData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Vehicle Identification Request with VIN data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate data length (must at least accommodate VIN length) - if (doipLayer.getDataLen() - sizeof(doiphdr) != DOIP_VIN_LEN) - { - PCPP_LOG_ERROR("Insufficient data length for Vehicle Identification Request with EID payload"); - return false; - } - - // Extract the VIN - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); - - return true; - } - - // vehicle announcement functions definition - VehicleAnnouncementData::VehicleAnnouncementData() - : vin{}, // Initialize VIN to all zeros - logicalAddress(0), // Set logical address to 0 - eid{}, // Initialize EID to all zeros - gid{}, // Initialize GID to all zeros - furtherActionRequired(DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED), // No further action required - syncStatus(DoIpSyncStatus::NON_INITIALIZED) // not initialized sync status field - {}; - - DoIpPayloadTypes VehicleAnnouncementData::getType() const - { - return DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE; - } - - std::string VehicleAnnouncementData::toString() const - { - std::stringstream os; - os << "VIN: " << std::string(reinterpret_cast(vin.data()), vin.size()) << "\n"; - os << "logical address: " << std::hex << "0x" << htobe16(logicalAddress) << "\n"; - os << "EID: " << pcpp::byteArrayToHexString(eid.data(), DOIP_EID_LEN) << "\n"; - os << "GID: " << pcpp::byteArrayToHexString(gid.data(), DOIP_GID_LEN) << "\n"; - auto it = DoIpEnumToStringActionCodes.find(furtherActionRequired); - if (it != DoIpEnumToStringActionCodes.end()) - { - os << "further action required:" << it->second << std::hex << " (0x" << unsigned(furtherActionRequired) - << ")" << "\n"; - } - else - { - os << "further action required: Unknown" << std::hex << " (0x" << unsigned(furtherActionRequired) << ")" - << "\n"; - } - - auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); - if (it_ != DoIpEnumToStringSyncStatus.end()) - { - os << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte - } - else - { - os << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(syncStatus) << ")" << "\n"; - } - - return os.str(); - } - - std::vector VehicleAnnouncementData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.insert(data.end(), vin.begin(), vin.end()); - data.insert(data.end(), reinterpret_cast(&logicalAddress), - reinterpret_cast(&logicalAddress) + sizeof(logicalAddress)); - data.insert(data.end(), eid.begin(), eid.end()); - data.insert(data.end(), gid.begin(), gid.end()); - data.push_back(static_cast(furtherActionRequired)); // Convert enum to byte - // optional field can be non-initialised - if (syncStatus != DoIpSyncStatus::NON_INITIALIZED) - { - data.push_back(static_cast(syncStatus)); // Convert enum to byte - } - return data; - } - - bool VehicleAnnouncementData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Vehicle Announcement data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate minimum data length - size_t fixedFieldLength = - DOIP_VIN_LEN + sizeof(logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + 1; // 1 for furtherActionRequired - if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Vehicle Announcement payload"); - return false; - } - - // Parse fields from payload - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - - // VIN - std::copy(dataPtr, dataPtr + DOIP_VIN_LEN, vin.begin()); - dataPtr += DOIP_VIN_LEN; - - // Logical Address - logicalAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - dataPtr += sizeof(logicalAddress); - - // EID - std::copy(dataPtr, dataPtr + DOIP_EID_LEN, eid.begin()); - dataPtr += DOIP_EID_LEN; - - // GID - std::copy(dataPtr, dataPtr + DOIP_GID_LEN, gid.begin()); - dataPtr += DOIP_GID_LEN; - - // Further Action Required - furtherActionRequired = static_cast(*dataPtr); - dataPtr += sizeof(furtherActionRequired); - - // Optional Sync Status - if (doipLayer.getDataLen() - sizeof(doiphdr) > fixedFieldLength) - { - syncStatus = static_cast(*dataPtr); - } - else - { - syncStatus = DoIpSyncStatus::NON_INITIALIZED; - } - - return true; - } - - // alive check response functions definition - AliveCheckResponseData::AliveCheckResponseData() : sourceAddress(0x0000) - {} - DoIpPayloadTypes AliveCheckResponseData::getType() const - { - return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE; - } - std::string AliveCheckResponseData::toString() const - { - std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - return os.str(); - } - std::vector AliveCheckResponseData::getData() const - { - std::vector data; - - data.push_back(static_cast(sourceAddress & 0xFF)); - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - - return data; - } - - bool AliveCheckResponseData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Alive Check Response data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate minimum data length - constexpr size_t fixedFieldLength = sizeof(sourceAddress); - if (doipLayer.getDataLen() - sizeof(doiphdr) != fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Alive Check Response payload"); - return false; - } - - // Parse sourceAddress from payload - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - return true; - } - - // Diagnostic Power Mode Response functions definition - DiagnosticPowerModeResponseData::DiagnosticPowerModeResponseData() - : powerModeCode(DoIpDiagnosticPowerModeCodes::NOT_READY) - {} - - DoIpPayloadTypes DiagnosticPowerModeResponseData::getType() const - { - return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE; - } - - std::string DiagnosticPowerModeResponseData::toString() const - { - std::stringstream os; - auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); - if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) - { - os << "diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(powerModeCode) << ")" - << "\n"; - } - else - { - os << "diagnostic power mode: Unknown" << std::hex << " (0x" << unsigned(powerModeCode) << ")" << "\n"; - } - return os.str(); - } - - std::vector DiagnosticPowerModeResponseData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(powerModeCode)); // Convert enum to byte - return data; - } - - bool DiagnosticPowerModeResponseData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic Power Mode Response data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - // Validate minimum data length - constexpr size_t fixedFieldLength = sizeof(powerModeCode); - if (doipLayer.getDataLen() - sizeof(doiphdr) < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Diagnostic Power Mode Response payload"); - return false; - } - - // Parse powerModeCode from payload - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - powerModeCode = static_cast(dataPtr[0]); - - return true; - } - - // Entity status response functions definitions - EntityStatusResponseData::EntityStatusResponseData() - : nodeType(DoIpEntityStatus::GATEWAY), maxConcurrentSockets(0), currentlyOpenSockets(0), maxDataSize(nullptr) - {} - - DoIpPayloadTypes EntityStatusResponseData::getType() const - { - return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE; - } - - std::string EntityStatusResponseData::toString() const - { - std::stringstream os; - auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); - if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) - { - os << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; - } - else - { - os << "Node Type: Unknown" << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; - } - os << "maximum Concurrent Socket: " << unsigned(maxConcurrentSockets) << "\n"; - os << "currently Opened Socket: " << unsigned(currentlyOpenSockets) << "\n"; - if (maxDataSize) - { - os << "maximum Data Size: " - << "0x" << pcpp::byteArrayToHexString(maxDataSize->data(), 4) << "\n"; - } - - return os.str(); - } - - std::vector EntityStatusResponseData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(nodeType)); - data.push_back(static_cast(maxConcurrentSockets)); - data.push_back(static_cast(currentlyOpenSockets)); - - // optional field - if (maxDataSize) - { - data.insert(data.end(), maxDataSize->begin(), maxDataSize->end()); - } - return data; - } - - bool EntityStatusResponseData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Entity Status Response data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - constexpr size_t fixedFieldLength = - sizeof(nodeType) + sizeof(maxConcurrentSockets) + sizeof(currentlyOpenSockets); - constexpr size_t optionalFieldLength = 4; // Length of maxDataSize field - size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); - - if (totalDataLength < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Entity Status Response fixed fields"); - return false; - } - - // Parse fixed fields - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - nodeType = static_cast(dataPtr[0]); - maxConcurrentSockets = dataPtr[1]; - currentlyOpenSockets = dataPtr[2]; - - // Parse optional maxDataSize field if present - if (totalDataLength == (fixedFieldLength + optionalFieldLength)) - { - maxDataSize = std::unique_ptr>( - new std::array()); - std::copy(dataPtr + fixedFieldLength, dataPtr + fixedFieldLength + optionalFieldLength, - maxDataSize->begin()); - } - else - { - // Optional field not present - maxDataSize = nullptr; - } - - return true; - } - - // Diagnostic Message functions definitions - DiagnosticMessageData::DiagnosticMessageData() - : sourceAddress(0x0000), targetAddress(0x0000), diagnosticData{ 0x22, 0xf1, 0x68 } - {} - DoIpPayloadTypes DiagnosticMessageData::getType() const - { - return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; - } - std::string DiagnosticMessageData::toString() const - { - std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - return os.str(); - } - std::vector DiagnosticMessageData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(sourceAddress & 0xFF)); - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - - data.push_back(static_cast(targetAddress & 0xFF)); - data.push_back(static_cast((targetAddress >> 8) & 0xFF)); - - data.insert(data.end(), diagnosticData.data(), diagnosticData.data() + diagnosticData.size()); - - return data; - } - - bool DiagnosticMessageData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic Message data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + 2; // SI + DID - size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); - - if (totalDataLength < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Diagnostic Message fixed fields"); - return false; - } - - // Parse fixed fields - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(sourceAddress); - targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(targetAddress); - - // Parse diagnosticData field (remaining data after fixed fields) - size_t diagnosticDataLength = totalDataLength - fixedFieldLength; - diagnosticData.resize(diagnosticDataLength); - std::copy(dataPtr, dataPtr + diagnosticDataLength, diagnosticData.begin()); - - return true; - } - - // Diagnostic Ack Message functions definitions - DiagnosticAckMessageData::DiagnosticAckMessageData() - : sourceAddress(0x0000), targetAddress(0x0000), ackCode(DoIpDiagnosticAckCodes::ACK), - previousMessage{ 0x22, 0xf1, 0x01, 0x02 } - {} - DoIpPayloadTypes DiagnosticAckMessageData::getType() const - { - return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK; - } - std::string DiagnosticAckMessageData::toString() const - { - std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = DoIpEnumToStringAckCode.find(ackCode); - if (it != DoIpEnumToStringAckCode.end()) - { - os << "ack code: " << it->second << " (0x" << unsigned(ackCode) << ")" << "\n"; - } - else - { - os << "Ack code: Unknown" << std::hex << " (0x" << unsigned(ackCode) << ")" << "\n"; - } - if (!previousMessage.empty()) - { - os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) - << "\n"; - } - return os.str(); - } - std::vector DiagnosticAckMessageData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(sourceAddress & 0xFF)); // Low byte - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - - data.push_back(static_cast(targetAddress & 0xFF)); - data.push_back(static_cast((targetAddress >> 8) & 0xFF)); - - data.push_back(static_cast(ackCode)); - - if (!previousMessage.empty()) - { - data.insert(data.end(), previousMessage.begin(), previousMessage.end()); - } - return data; - } - - bool DiagnosticAckMessageData::buildFromLayer(const DoIpLayer& doipLayer) - { - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic Acknowledgment Message data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(ackCode); - size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); - - if (totalDataLength < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Diagnostic Acknowledgment Message fixed fields"); - return false; - } - - // Parse fixed fields - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(sourceAddress); - targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(targetAddress); - ackCode = static_cast(dataPtr[0]); - - dataPtr += sizeof(ackCode); - // Check if there is any data left for the optional previousMessage field - size_t remainingDataLength = totalDataLength - fixedFieldLength; - if (remainingDataLength > 0) - { - previousMessage.resize(remainingDataLength); - std::copy(dataPtr, dataPtr + remainingDataLength, previousMessage.begin()); - } - else - { - previousMessage.clear(); - } - return true; - } - - // Diagnostic Nack Message functions definitions - DiagnosticNackMessageData::DiagnosticNackMessageData() - : sourceAddress(0x0000), targetAddress(0x0000), - nackCode(DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS), previousMessage{ 0x22, 0xf1, 0x01, 0x02 } - {} - DoIpPayloadTypes DiagnosticNackMessageData::getType() const - { - return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK; - } - std::string DiagnosticNackMessageData::toString() const - { - std::stringstream os; - os << "source address: " << std::hex << "0x" << htobe16(sourceAddress) << "\n"; - os << "target address: " << std::hex << "0x" << htobe16(targetAddress) << "\n"; - auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); - if (it != DoIpEnumToStringDiagnosticNackCodes.end()) - { - os << "nack code: " << it->second << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; - } - else - { - os << "nack code: Unknown" << std::hex << " (0x" << unsigned(nackCode) << ")" << "\n"; - } - if (!previousMessage.empty()) - { - os << "previous message: " << pcpp::byteArrayToHexString(previousMessage.data(), previousMessage.size()) - << "\n"; - } - return os.str(); - } - std::vector DiagnosticNackMessageData::getData() const - { - std::vector data; - // Copy each field's data into the vector - data.push_back(static_cast(sourceAddress & 0xFF)); - data.push_back(static_cast((sourceAddress >> 8) & 0xFF)); - - data.push_back(static_cast(targetAddress & 0xFF)); - data.push_back(static_cast((targetAddress >> 8) & 0xFF)); - - data.push_back(static_cast(nackCode)); - if (!previousMessage.empty()) - { - data.insert(data.end(), reinterpret_cast(&previousMessage), - reinterpret_cast(&previousMessage) + sizeof(previousMessage)); - } - return data; - } - - bool DiagnosticNackMessageData::buildFromLayer(const DoIpLayer& doipLayer) - { - - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot retrieve Diagnostic NACK Message data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - constexpr size_t fixedFieldLength = sizeof(sourceAddress) + sizeof(targetAddress) + sizeof(nackCode); - size_t totalDataLength = doipLayer.getDataLen() - sizeof(doiphdr); - - if (totalDataLength < fixedFieldLength) - { - PCPP_LOG_ERROR("Insufficient data length for Diagnostic NACK Message fixed fields"); - return false; - } - - // Parse fixed fields - uint8_t* dataPtr = doipLayer.getDataPtr(sizeof(doiphdr)); - sourceAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(sourceAddress); - targetAddress = static_cast(dataPtr[1] << 8 | dataPtr[0]); - - dataPtr += sizeof(targetAddress); - nackCode = static_cast(dataPtr[0]); - - dataPtr += sizeof(nackCode); - // Check if there is any data left for the optional previousMessage field - size_t remainingDataLength = totalDataLength - fixedFieldLength; - if (remainingDataLength > 0) - { - previousMessage.resize(remainingDataLength); - std::copy(dataPtr, dataPtr + remainingDataLength, previousMessage.begin()); - } - else - { - // Ensure previousMessage is empty when not provided - previousMessage.clear(); - } - - return true; - } - - // Alive check request functions definitions - AliveCheckRequestData::AliveCheckRequestData() - {} - - DoIpPayloadTypes AliveCheckRequestData::getType() const - { - return DoIpPayloadTypes::ALIVE_CHECK_REQUEST; - } - std::string AliveCheckRequestData::toString() const - { - return {}; - } - - std::vector AliveCheckRequestData::getData() const - { - return {}; - } - - bool AliveCheckRequestData::buildFromLayer(const DoIpLayer& doipLayer) - { - - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot build Alive check request Message data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - if (doipLayer.getDataLen() != sizeof(doiphdr)) - { - PCPP_LOG_ERROR("Alive check request Message has no additional data"); - return false; - } - return true; - } - - // Entity status request functions definitions - EntityStatusRequestData::EntityStatusRequestData() - {} - - DoIpPayloadTypes EntityStatusRequestData::getType() const - { - return DoIpPayloadTypes::ENTITY_STATUS_REQUEST; - } - - std::string EntityStatusRequestData::toString() const - { - return {}; - } - - std::vector EntityStatusRequestData::getData() const - { - return {}; - } - - bool EntityStatusRequestData::buildFromLayer(const DoIpLayer& doipLayer) - { - - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot build Entity status request message data from " + doipLayer.getPayloadTypeAsStr()); - return false; - } - - if (doipLayer.getDataLen() != sizeof(doiphdr)) - { - PCPP_LOG_ERROR("Entity status request message has no additional data"); - return false; - } - return true; - } - - // diagnostic power mode request functions definitions - DiagnosticPowerModeRequestData::DiagnosticPowerModeRequestData() - {} - - DoIpPayloadTypes DiagnosticPowerModeRequestData::getType() const - { - return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST; - } - - std::string DiagnosticPowerModeRequestData::toString() const - { - return {}; - } - - std::vector DiagnosticPowerModeRequestData::getData() const - { - return {}; - } - - bool DiagnosticPowerModeRequestData::buildFromLayer(const DoIpLayer& doipLayer) - { - - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot build diagnostic power mode request message data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - if (doipLayer.getDataLen() != sizeof(doiphdr)) - { - PCPP_LOG_ERROR("diagnostic power mode request message has no additional data"); - return false; - } - return true; - } - - // Vehicle identification request functions definitions - VehicleIdentificationRequestData::VehicleIdentificationRequestData() - {} - - DoIpPayloadTypes VehicleIdentificationRequestData::getType() const - { - return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST; - } - - std::string VehicleIdentificationRequestData::toString() const - { - return {}; - } - - std::vector VehicleIdentificationRequestData::getData() const - { - return {}; - } - - bool VehicleIdentificationRequestData::buildFromLayer(const DoIpLayer& doipLayer) - { - - if (doipLayer.getPayloadType() != getType()) - { - PCPP_LOG_ERROR("Cannot build vehicle identification request message data from " + - doipLayer.getPayloadTypeAsStr()); - return false; - } - - if (doipLayer.getDataLen() != sizeof(doiphdr)) - { - PCPP_LOG_ERROR("Vehicle identification request message has no additional data"); - return false; - } - return true; - } -} // namespace pcpp diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index d480f8f878..90527f20ec 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -369,7 +369,7 @@ namespace pcpp if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(payload, payloadLen))) - m_NextLayer = new DoIpLayer(payload, payloadLen, this, m_Packet); + m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); else if (HttpMessage::isHttpPort(portDst) && HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) m_NextLayer = new HttpRequestLayer(payload, payloadLen, this, m_Packet); diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 9b91337d8c..5a2b4ba271 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -133,7 +133,7 @@ namespace pcpp m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(udpData, udpDataLen))) - m_NextLayer = new DoIpLayer(udpData, udpDataLen, this, m_Packet); + m_NextLayer = DoIpLayer::parseDoIpLayer(udpData, udpDataLen, this, m_Packet); else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && NtpLayer::isDataValid(udpData, udpDataLen)) m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); diff --git a/Tests/Packet++Test/PacketExamples/DoIpWrongLengthRoutingActivationRequestPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpWrongLengthRoutingActivationRequestPacket.dat new file mode 100644 index 0000000000..c987356453 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpWrongLengthRoutingActivationRequestPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac1508004500003cf0e44000400609fea9fe75efa9fe75eed25a345849689c4200186ab95018faf04008000002fd00050000000b0e8000000000000000000005 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index 239bcf8b13..a61a534dde 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -89,40 +89,41 @@ PTF_TEST_CASE(DnsOverTcpCreationTest); PTF_TEST_CASE(DnsLayerAddDnsKeyTest); // Implemented in DoIpTests.cpp +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation); +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing); +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing); +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation); PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing); PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation); PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing); PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation); PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing); PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation); -PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing); -PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation); -PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing); -PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation); -PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing); -PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation); PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing); PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation); -PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing); -PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation); -PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing); -PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation); -PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing); -PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation); PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing); PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation); +PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing); +PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation); PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing); PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation); PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing); PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation); PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing); PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation); +PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing); +PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation); +PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing); +PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation); +PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing); +PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing); PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing); +PTF_TEST_CASE(DoIpInvalidPayloadLenPacketParsing); // Implemented in IcmpTests.cpp PTF_TEST_CASE(IcmpParsingTest); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 6280401a8f..1dd87c4f3a 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -10,202 +10,252 @@ #include "SystemUtils.h" #include "PacketUtils.h" #include "DeprecationUtils.h" -#include "DoIpLayerData.h" #include +#include +#include "DoIpLayer.h" +#include "GeneralUtils.h" -// ------------------ -// GenericHeaderNackPacket -PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) +// RoutingActivationRequest +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) { + // Dissect Routing Activation Request message timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpGenericHeaderNackPacket.dat"); - - pcpp::Packet GenericHeaderNack(&rawPacket1); - PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::DOIP)); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationRequestPacket.dat"); - pcpp::UdpLayer* udpLayer = GenericHeaderNack.getLayerOfType(); - PTF_ASSERT_NOT_NULL(udpLayer); + pcpp::Packet RoutingActivationRequest(&rawPacket1); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::DOIP)); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8886)); + pcpp::TcpLayer* tcpLayer = RoutingActivationRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); - pcpp::DoIpLayer* doipLayer = GenericHeaderNack.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); - // build doipData from existent layer - pcpp::GenericHeaderNackData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), "generic header nack code: Unknown payload type (0x1)\n"); - // wrong build + auto* doipLayer = RoutingActivationRequest.getLayerOfType(); - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation request (0x0005)"); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x0e80); + PTF_ASSERT_EQUAL(doipLayer->getActivationType(), pcpp::DoIpActivationTypes::Default, enumclass); + std::array isoField{}; + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), isoField); + + PTF_ASSERT_TRUE(doipLayer->hasReservedOem()); + PTF_ASSERT_NOT_NULL(doipLayer->getReservedOem()); + std::array oemField = {}; + + PTF_ASSERT_TRUE(*doipLayer->getReservedOem() == oemField); + + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "Source Address: 0xe80\nActivation type: Default (0x0)\nReserved by ISO: 00000000\nReserved by OEM: 00000000\n"); } -PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) +PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); + tcpLayer.getTcpHeader()->windowSize = 64240; ipLayer.getIPv4Header()->timeToLive = 128; PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; - pcpp::GenericHeaderNackData data; - data.genericNackCode = pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, 0xb, 0xe, 0x80, + 0x0, 0x1, 0x2, 0x3, 0x4, 0x05, 0x05, 0x05, 0x05 }; + std::array isoReserved{ 0x1, 0x2, 0x3, 0x4 }; + std::array oemField{ 0x5, 0x5, 0x5, 0x5 }; - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); - doIpPacket.computeCalculateFields(); + pcpp::RoutingActivationRequest doipLayer(0x00, pcpp::DoIpActivationTypes::WWH_OBD); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + doipLayer.setSourceAddress(0x0e80); + doipLayer.setActivationType(pcpp::DoIpActivationTypes::Default); + doipLayer.setReservedIso(isoReserved); + doipLayer.setReservedOem(oemField); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Generic DOIP header Nack"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)") + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer)); + doIpPacket.computeCalculateFields(); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); + + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Routing activation request"); + PTF_ASSERT_EQUAL(doipLayer.getPayloadLength(), 11); + PTF_ASSERT_EQUAL(doipLayer.toString(), "DoIP Layer, Routing activation request (0x0005)"); + + PTF_ASSERT_EQUAL(doipLayer.getSourceAddress(), 0x0e80); + PTF_ASSERT_EQUAL(doipLayer.getActivationType(), pcpp::DoIpActivationTypes::Default, enumclass); + + PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); + PTF_ASSERT_VECTORS_EQUAL(*doipLayer.getReservedOem(), oemField); + // std::cout << pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(), + // doIpPacket.getRawPacket()->getRawDataLen()) << "\n"; + doipLayer.clearReserveOem(); + // std::cout << + // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << + // "\n"; + PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - DOIP_RESERVED_OEM_LEN); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - DOIP_RESERVED_OEM_LEN) - 15, bytes, 15); + PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), isoReserved); + PTF_ASSERT_TRUE(doipLayer.getReservedOem() == nullptr); + PTF_ASSERT_EQUAL(doipLayer.getSummary(), + "Source Address: 0xe80\nActivation type: Default (0x0)\nReserved by ISO: 01020304\n"); + doipLayer.setReservedOem(oemField); + PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); + PTF_ASSERT_EQUAL( + doipLayer.getSummary(), + "Source Address: 0xe80\nActivation type: Default (0x0)\nReserved by ISO: 01020304\nReserved by OEM: 05050505\n"); } -// DoIpVehicleIdentificationRequestPacketParsing -PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) +// RoutingActivationResponse +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) { + // Dissect Routing Activation Response message timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestPacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationResponsePacket.dat"); - pcpp::Packet vehicleIdentificationRequest(&rawPacket1); - PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::DOIP)); + pcpp::Packet RoutingActivationResponse(&rawPacket1); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(udpLayer); + pcpp::TcpLayer* tcpLayer = RoutingActivationResponse.getLayerOfType(); + PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8988)); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x10)); + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53850); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0xa0a5)); - // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + auto* doipLayer = RoutingActivationResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 00000000\n"); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); - -} // DoIpVehicleIdentificationRequestPacketParsing + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation response (0x0006)"); + PTF_ASSERT_EQUAL(doipLayer->getLogicalAddressExternalTester(), 0x0e80); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x4010); + PTF_ASSERT_EQUAL(doipLayer->getResponseCode(), pcpp::DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, + enumclass); + std::array resISO{}; + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), resISO); + PTF_ASSERT_FALSE(doipLayer->hasReservedOem()); + PTF_ASSERT_TRUE(doipLayer->getReservedOem() == nullptr); +} -PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) +PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); - ipLayer.getIPv4Header()->ipId = htobe16(20370); + tcpLayer.getTcpHeader()->windowSize = 64240; ipLayer.getIPv4Header()->timeToLive = 128; - pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); + doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x6, 0x0, 0x0, 0x0, 0xd, 0xe, 0x80, 0x40, + 0x10, 0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x5 }; - pcpp::VehicleIdentificationRequestData req; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + pcpp::RoutingActivationResponse doipLayer(0x0, 0x0, pcpp::DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS); + doipLayer.setLogicalAddressExternalTester(0x0e80); + doipLayer.setSourceAddress(0x4010); + doipLayer.setResponseCode(pcpp::DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED); + doipLayer.setReservedIso({ 0x1, 0x2, 0x3, 0x4 }); + doipLayer.setReservedOem({ 0x5, 0x5, 0x5, 0x5 }); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer)); + doIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 75); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); + + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Routing activation response"); + PTF_ASSERT_EQUAL(doipLayer.getPayloadLength(), 13); + PTF_ASSERT_EQUAL(doipLayer.toString(), "DoIP Layer, Routing activation response (0x0006)") + std::array resISO{ 0x1, 0x2, 0x3, 0x4 }; + std::array resOEM{ 0x5, 0x5, 0x5, 0x5 }; + PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), resISO); + PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); + PTF_ASSERT_VECTORS_EQUAL(*doipLayer.getReservedOem(), resOEM); + PTF_ASSERT_EQUAL( + doipLayer.getSummary(), + "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 01020304\nReserved by OEM: 05050505\n"); + doipLayer.clearReservedOem(); + PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); + PTF_ASSERT_EQUAL( + doipLayer.getSummary(), + "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 01020304\n"); } -// VehicleIdentificationWithVIN -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) + +// GenericHeaderNackPacket +PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) { - // Dissect Vehicle identification Request with VIN timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpGenericHeaderNackPacket.dat"); - pcpp::Packet VehicleIdentificationRequestVIN(&rawPacket1); - PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::DOIP)); + pcpp::Packet GenericHeaderNack(&rawPacket1); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(GenericHeaderNack.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + pcpp::UdpLayer* udpLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4b6d)); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(33)); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + auto* doipLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // build doipData from existent layer - pcpp::VehicleIdentificationRequestVINData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), "VIN: BAUNEE4MZ17042403\n"); - // wrong build - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, - enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)") - -} // DoIpVehicleIdentificationRequestVINPacketParsing + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)"); + PTF_ASSERT_EQUAL(doipLayer->getNackCode(), pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Generic header nack code: Unknown payload type (0x1)\n"); +} -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) +PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); ipLayer.getIPv4Header()->timeToLive = 128; @@ -214,31 +264,25 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x3, 0x0, 0x0, 0x0, 0x11, 0x42, 0x41, 0x55, 0x4e, 0x45, - 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, - 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - - pcpp::VehicleIdentificationRequestVINData withVin; - withVin.vin = vin; - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, withVin); + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; + pcpp::GenericHeaderNack doipLayer(pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer)); doIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 25), bytes, 25); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, - enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 17); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)") + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Generic DOIP header Nack"); + PTF_ASSERT_EQUAL(doipLayer.getPayloadLength(), 1); + PTF_ASSERT_EQUAL(doipLayer.toString(), "DoIP Layer, Generic DOIP header Nack (0x0000)"); + PTF_ASSERT_EQUAL(doipLayer.getNackCode(), pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getSummary(), "Generic header nack code: Unknown payload type (0x1)\n"); } + // VehicleIdentificationWithEID PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) { @@ -258,22 +302,11 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x7a80)); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x16)); - // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); + auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // build doipData from existent layer - pcpp::VehicleIdentificationRequestEIDData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), "EID: 4241554e4545\n"); - // wrong build - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "EID: 4241554e4545\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -282,8 +315,10 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)") + std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); -} // DoIpVehicleIdentificationRequestVINPacketParsing +} // VehicleIdentificationWithEIDacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) { @@ -302,26 +337,103 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; - pcpp::VehicleIdentificationRequestEIDData withEID; - withEID.eid = eid; + pcpp::VehicleIdentificationRequestEID withEID(eid); + withEID.setEID(eid); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, withEID); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&withEID)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 56); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (56 - 14), bytes, 14); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, + PTF_ASSERT_EQUAL(withEID.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(withEID.getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(withEID.getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, + enumclass); + PTF_ASSERT_EQUAL(withEID.getPayloadTypeAsStr(), "Vehicle identification request with EID"); + PTF_ASSERT_EQUAL(withEID.getPayloadLength(), 6); + PTF_ASSERT_EQUAL(withEID.toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)"); + PTF_ASSERT_VECTORS_EQUAL(withEID.getEID(), eid); + PTF_ASSERT_EQUAL(withEID.getSummary(), "EID: 4241554e4545\n"); +} + +// VehicleIdentificationWithVIN +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) +{ + // Dissect Vehicle identification Request with VIN + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat"); + + pcpp::Packet VehicleIdentificationRequestVIN(&rawPacket1); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + + auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, + enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with VIN"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)"); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\n"); + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getVIN(), vin); + +} // DoIpVehicleIdentificationRequestVINPacketParsing + +// DoIpVehicleIdentificationRequestVINPacketCreation +PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x3, 0x0, 0x0, 0x0, 0x11, 0x42, 0x41, 0x55, 0x4e, 0x45, + 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + + pcpp::VehicleIdentificationRequestVIN withVin(vin); + withVin.setVIN(vin); + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&withVin)); + doIpPacket.computeCalculateFields(); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 25), bytes, 25); + + PTF_ASSERT_EQUAL(withVin.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(withVin.getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(withVin.getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request with EID"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)") + PTF_ASSERT_EQUAL(withVin.getPayloadTypeAsStr(), "Vehicle identification request with VIN"); + PTF_ASSERT_EQUAL(withVin.getPayloadLength(), 17); + PTF_ASSERT_EQUAL(withVin.toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)"); + PTF_ASSERT_EQUAL(withVin.getSummary(), "VIN: BAUNEE4MZ17042403\n"); + PTF_ASSERT_VECTORS_EQUAL(withVin.getVIN(), vin); } + // VehicleAnnouncement PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) { @@ -331,8 +443,12 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleAnnouncementPacket.dat"); + std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + pcpp::Packet VehicleAnnouncement(&rawPacket1); - PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::IPv4)); PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::UDP)); PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::DOIP)); @@ -340,23 +456,15 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 13400); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0xdf5e)); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x30)); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = VehicleAnnouncement.getLayerOfType(); + auto* doipLayer = VehicleAnnouncement.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // build doipData from existent layer - pcpp::VehicleAnnouncementData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL( - data.toString(), - "VIN: BAUNEE4MZ17042403\nlogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nfurther action required:No further action required (0x0)\nVIN/GID sync status: NULL\n"); - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -365,7 +473,13 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) "Vehicle announcement message / vehicle identification response message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 32); PTF_ASSERT_EQUAL(doipLayer->toString(), - "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") + "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)"); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getVIN(), vin); + PTF_ASSERT_EQUAL(doipLayer->getLogicalAddress(), 0x4010); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getGID(), gid); + PTF_ASSERT_FALSE(doipLayer->hasSyncStatus()); + PTF_ASSERT_NULL(doipLayer->getSyncStatus()); } // DoIpVehicleAnnouncementPacketParsing PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) @@ -390,246 +504,86 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - pcpp::VehicleAnnouncementData ann; - ann.gid = gid; - ann.eid = eid; - ann.vin = vin; - ann.logicalAddress = be16toh(0x4010); - ann.syncStatus = pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED; - ann.furtherActionRequired = pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED; - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, ann); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + pcpp::VehicleAnnouncement ann(vin, 0x4010, eid, gid, pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED); + ann.setSyncStatus(pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ann)); doIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 83); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle announcement message / vehicle identification response message"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 33); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), - "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 33); + PTF_ASSERT_EQUAL(doipLayer->toString(), + "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)"); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getVIN(), vin); + PTF_ASSERT_EQUAL(doipLayer->getLogicalAddress(), 0x4010); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getGID(), gid); + PTF_ASSERT_TRUE(doipLayer->hasSyncStatus()); + PTF_ASSERT_EQUAL(*doipLayer->getSyncStatus(), pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, enumclass); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\nVIN/GID sync status: VIN and/or GID are synchronized\n"); + doipLayer->clearSyncStatus(); + PTF_ASSERT_FALSE(doipLayer->hasSyncStatus()); + PTF_ASSERT_TRUE(doipLayer->getSyncStatus() == nullptr); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\n"); } - -// RoutingActivationRequest -PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) -{ - // Dissect Routing Activation Request message - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationRequestPacket.dat"); - - pcpp::Packet RoutingActivationRequest(&rawPacket1); - PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::TCP)); - PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::DOIP)); - - pcpp::TcpLayer* tcpLayer = RoutingActivationRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(tcpLayer); - - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), 53850); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x4008)); - - pcpp::DoIpLayer* doipLayer = RoutingActivationRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); - - // build doipData from existent layer - pcpp::RoutingActivationRequestData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL( - data.toString(), - "sourceAddress: 0xe80\nactivation type: Default (0x0)\nreserved by ISO: 00000000\nReserved by OEM: 00000000\n"); - - pcpp::RoutingActivationResponseData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation request (0x0005)") -} - -PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) -{ - pcpp::Packet doIpPacket(100); - pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); - pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); - - tcpLayer.getTcpHeader()->windowSize = 64240; - ipLayer.getIPv4Header()->timeToLive = 128; - - PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); - doIpPacket.computeCalculateFields(); - - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, 0xb, 0xe, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - pcpp::RoutingActivationRequestData routingData; - routingData.sourceAddress = be16toh(0x0e80); - routingData.activationType = pcpp::DoIpActivationTypes::Default; - routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; - routingData.reservedOem = std::unique_ptr>(new std::array()); - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, routingData); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); - doIpPacket.computeCalculateFields(); - - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation request"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 11); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Routing activation request (0x0005)") -} -// RoutingActivationResponse -PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) -{ - // Dissect Routing Activation Response message - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpRoutingActivationResponsePacket.dat"); - - pcpp::Packet RoutingActivationResponse(&rawPacket1); - PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::TCP)); - PTF_ASSERT_TRUE(RoutingActivationResponse.isPacketOfType(pcpp::DOIP)); - - pcpp::TcpLayer* tcpLayer = RoutingActivationResponse.getLayerOfType(); - PTF_ASSERT_NOT_NULL(tcpLayer); - - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53850); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0xa0a5)); - - pcpp::DoIpLayer* doipLayer = RoutingActivationResponse.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); - - pcpp::RoutingActivationResponseData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL( - data.toString(), - "logical address of external tester: 0xe80\nsource address: 0x4010\nrouting activation response code: Routing successfully activated (0x10)\nreserved by ISO: 00000000\n"); - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 9); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation response (0x0006)") -} - -PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) -{ - pcpp::Packet doIpPacket(100); - pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); - pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); - - tcpLayer.getTcpHeader()->windowSize = 64240; - ipLayer.getIPv4Header()->timeToLive = 128; - - PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); - doIpPacket.computeCalculateFields(); - - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x6, 0x0, 0x0, 0x0, 0xd, 0xe, 0x80, 0x40, - 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - pcpp::RoutingActivationResponseData routingData; - routingData.logicalAddressExternalTester = be16toh(0x0e80); - routingData.sourceAddress = be16toh(0x4010); - routingData.responseCode = pcpp::DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED; - routingData.reservedIso = { 0x0, 0x0, 0x0, 0x0 }; - routingData.reservedOem = std::unique_ptr>(new std::array()); - - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, routingData); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); - doIpPacket.computeCalculateFields(); - - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 75); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Routing activation response"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 13); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Routing activation response (0x0006)") -} -// --------------- -// AliveCheckRequestPacket -PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) +// DoIpVehicleIdentificationRequestPacketParsing +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) { timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpAliveCheckRequestPacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestPacket.dat"); - pcpp::Packet AliveCheckRequest(&rawPacket1); - PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::DOIP)); + pcpp::Packet vehicleIdentificationRequest(&rawPacket1); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = AliveCheckRequest.getLayerOfType(); + pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8982)); - pcpp::DoIpLayer* doipLayer = AliveCheckRequest.getLayerOfType(); + auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check request (0x0007)") -} + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); -PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) +} // DoIpVehicleIdentificationRequestPacketParsing + +PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + ipLayer.getIPv4Header()->ipId = htobe16(20370); ipLayer.getIPv4Header()->timeToLive = 128; + pcpp::UdpLayer udpLayer((uint16_t)65300, (uint16_t)13400); PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); - doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; - pcpp::AliveCheckRequestData req; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + pcpp::VehicleIdentificationRequest req; + PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); @@ -638,12 +592,11 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check request (0x0007)") + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); } -// --------------- // AliveCheckResponsePacket PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) { @@ -657,32 +610,22 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_TRUE(AliveCheckResponse.isPacketOfType(pcpp::UDP)); PTF_ASSERT_TRUE(AliveCheckResponse.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = AliveCheckResponse.getLayerOfType(); + auto* udpLayer = AliveCheckResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x897b)); - pcpp::DoIpLayer* doipLayer = AliveCheckResponse.getLayerOfType(); + auto* doipLayer = AliveCheckResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // build doipData from existent layer - pcpp::AliveCheckResponseData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL(data.toString(), "source address: 0x0\n"); - // wrong build - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); - + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x0\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check response (0x0008)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check response (0x0008)"); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x00); } PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) @@ -699,132 +642,59 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0 }; - pcpp::AliveCheckResponseData aliveCheckRespData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, aliveCheckRespData); + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x10, 0x20 }; + pcpp::AliveCheckResponse aliveCheckResp(0x1020); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&aliveCheckResp)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 52); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check response"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 2); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check response (0x0008)") -} -// ------------------ -// EntityStatusRequestPacket -PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) -{ - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusRequestPacket.dat"); - - pcpp::Packet EntityStatusRequest(&rawPacket1); - PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::DOIP)); - - pcpp::UdpLayer* udpLayer = EntityStatusRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(udpLayer); - - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4988)); - - pcpp::DoIpLayer* doipLayer = EntityStatusRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status request (0x4001)") -} - -PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) -{ - pcpp::Packet doIpPacket(100); - pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); - pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); - - ipLayer.getIPv4Header()->timeToLive = 128; - - PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); - doIpPacket.computeCalculateFields(); - - unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; - pcpp::EntityStatusRequestData req; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); - doIpPacket.computeCalculateFields(); - - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status request (0x4001)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check response (0x0008)"); + doipLayer->setSourceAddress(0x3040); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x3040); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x3040\n"); } -// ------------------ -// EntityStatusResponsePacket -PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) +// PowerModeResponsePacket +PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) { timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusResponsePacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeResponsePacket.dat"); - pcpp::Packet EntityStatusResponse(&rawPacket1); - PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::DOIP)); + pcpp::Packet PowerModeResponse(&rawPacket1); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = EntityStatusResponse.getLayerOfType(); + pcpp::UdpLayer* udpLayer = PowerModeResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4a61)); - pcpp::DoIpLayer* doipLayer = EntityStatusResponse.getLayerOfType(); + auto* doipLayer = PowerModeResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - pcpp::EntityStatusResponseData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL( - data.toString(), - "Entity status: DoIP gateway (0x0)\nmaximum Concurrent Socket: 1\ncurrently Opened Socket: 0\nmaximum Data Size: 0x00000fff\n"); - // wrong build - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: not ready (0x0)\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status response (0x4002)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)"); + PTF_ASSERT_EQUAL(doipLayer->getPowerModeCode(), pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY, enumclass); } - -PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) +PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); @@ -838,131 +708,68 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x2, 0x2, 0x0, 0x0, 0xf, 0xff }; - pcpp::EntityStatusResponseData entityResponseData; - entityResponseData.currentlyOpenSockets = 2; - entityResponseData.maxConcurrentSockets = 2; - entityResponseData.maxDataSize = - std::unique_ptr>(new std::array{ 0x0, 0x0, 0xf, 0xff }); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, entityResponseData); + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x1 }; + pcpp::DiagnosticPowerModeResponse data(pcpp::DoIpDiagnosticPowerModeCodes::READY); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 57); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status response (0x4002)") -} -// ------------------ -// PowerModeRequestPacket -PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) -{ - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeRequestPacket.dat"); - - pcpp::Packet PowerModeRequest(&rawPacket1); - PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::DOIP)); - - pcpp::UdpLayer* udpLayer = PowerModeRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(udpLayer); - - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4986)); - - pcpp::DoIpLayer* doipLayer = PowerModeRequest.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") -} - -PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) -{ - pcpp::Packet doIpPacket(100); - pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); - pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); - pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); - - ipLayer.getIPv4Header()->timeToLive = 128; - - PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); - doIpPacket.computeCalculateFields(); - - unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DiagnosticPowerModeRequestData req; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, req); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); - doIpPacket.computeCalculateFields(); - - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)"); + PTF_ASSERT_EQUAL(doipLayer->getPowerModeCode(), pcpp::DoIpDiagnosticPowerModeCodes::READY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: ready (0x1)\n"); + doipLayer->setPowerModeCode(pcpp::DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED); + PTF_ASSERT_EQUAL(doipLayer->getPowerModeCode(), pcpp::DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: not supported (0x2)\n"); } -// ------------------ -// PowerModeResponsePacket -PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) + +// EntityStatusResponsePacket +PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) { timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeResponsePacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusResponsePacket.dat"); - pcpp::Packet PowerModeResponse(&rawPacket1); - PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(PowerModeResponse.isPacketOfType(pcpp::DOIP)); + pcpp::Packet EntityStatusResponse(&rawPacket1); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(EntityStatusResponse.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = PowerModeResponse.getLayerOfType(); + pcpp::UdpLayer* udpLayer = EntityStatusResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - pcpp::DoIpLayer* doipLayer = PowerModeResponse.getLayerOfType(); + auto* doipLayer = EntityStatusResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - pcpp::DiagnosticPowerModeResponseData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL(data.toString(), "diagnostic power mode: not ready (0x0)\n"); - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "Entity status: DoIP gateway (0x0)\nMax Concurrent Socket: 1\nCurrently Opened Socket: 0\nMax Data Size: 0x00000fff\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)") + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatus::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 1); + PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 0); + std::array maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; + PTF_ASSERT_TRUE(*doipLayer->getMaxDataSize() == maxDataSize); } -PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) +PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); @@ -976,26 +783,39 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0 }; - pcpp::DiagnosticPowerModeResponseData data; - data.powerModeCode = pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x5, 0x2, 0xff, 0xff, 0xff, 0xff }; + pcpp::EntityStatusResponse data(pcpp::DoIpEntityStatus::GATEWAY, 0, 0); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); + auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); + doipLayer->setNodeType(pcpp::DoIpEntityStatus::GATEWAY); + doipLayer->setMaxConcurrentSockets(5); + doipLayer->setCurrentlyOpenSockets(2); + const std::array& maxDataSize{ 0xff, 0xff, 0xff, 0xff }; + doipLayer->setMaxDataSize(maxDataSize); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 57); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode response information"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 1); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)") + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatus::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 5); + PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 2); + PTF_ASSERT_TRUE(doipLayer->hasMaxDataSize()); + PTF_ASSERT_TRUE(*doipLayer->getMaxDataSize() == maxDataSize); + doipLayer->clearMaxDataSize(); + PTF_ASSERT_FALSE(doipLayer->hasMaxDataSize()); + PTF_ASSERT_TRUE(doipLayer->getMaxDataSize() == nullptr); } -// ------------------ + // DiagnosticMessagePacket PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) { @@ -1013,25 +833,27 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_NOT_NULL(tcpLayer); PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), 53854); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x4003)); - pcpp::DoIpLayer* doipLayer = DiagnosticMessagePacket.getLayerOfType(); + auto* doipLayer = DiagnosticMessagePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - pcpp::DiagnosticMessageData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL(data.toString(), "source address: 0xe80\ntarget address: 0x4010\n"); + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0xe, 0x80, 0x40, 0x10, 0x10, 0x3 }; + + PTF_ASSERT_EQUAL(DiagnosticMessagePacket.getRawPacket()->getRawDataLen(), 68); + PTF_ASSERT_BUF_COMPARE(DiagnosticMessagePacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0xe80\nTarget Address: 0x4010\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message (0x8001)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message (0x8001)"); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0xe80); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4010); + const std::vector& diagData{ 0x10, 0x03 }; + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getDiagnosticData(), diagData); } PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) @@ -1048,30 +870,41 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0xe, 0x80, 0x40, 0x10, 0x10, 0x3 }; - std::vector diagnosticData{ 0x10, 0x03 }; - - pcpp::DiagnosticMessageData data; - data.sourceAddress = be16toh(0x0e80); - data.targetAddress = be16toh(0x4010); - data.diagnosticData = diagnosticData; - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0x20, 0x30, 0x40, 0x40, 0x10, 0x02 }; + std::vector diagnosticData{ 0x10, 0x02 }; + std::vector diagnosticData2{ 0x10, 0x02, 0x40, 0x50 }; + pcpp::DiagnosticMessage data(0x2030, 0x4040, diagnosticData); - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); + // std::cout << pcpp::byteArrayToHexString(data.getDataPtr(0),14) << "\n"; + data.setDiagnosticData(diagnosticData); + data.setDiagnosticData(diagnosticData2); + data.setDiagnosticData(diagnosticData); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 68); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x2030); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4040); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 6); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message (0x8001)"); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 6); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message (0x8001)"); + doipLayer->setSourceAddress(0x8080); + doipLayer->setTargetAddress(0x4343); + std::vector newDiagnosticData{ 0x10, 0x02, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0a }; + doipLayer->setDiagnosticData(newDiagnosticData); + + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x8080); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4343); + PTF_ASSERT_VECTORS_EQUAL(doipLayer->getDiagnosticData(), newDiagnosticData); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x8080\nTarget Address: 0x4343\n"); } -// ------------------ + // DiagnosticAckMessagePacket PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) { @@ -1088,28 +921,26 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) pcpp::TcpLayer* tcpLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x49a2)); - pcpp::DoIpLayer* doipLayer = DiagnosticAckMessage.getLayerOfType(); + auto* doipLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - pcpp::DiagnosticAckMessageData data; - if (data.buildFromLayer(*doipLayer)) - PTF_ASSERT_EQUAL( - data.toString(), - "source address: 0x4010\ntarget address: 0xe80\nack code: ACK (0x0)\nprevious message: 22f101\n"); - - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL(doipLayer->getSummary(), + "Source Address: 0x4010\nTarget Address: 0xe80\nACK code: ACK (0x0)\nPrevious message: 22f101\n"); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)") + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)"); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x4010); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x0e80); + PTF_ASSERT_EQUAL(doipLayer->getAckCode(), pcpp::DoIpDiagnosticAckCodes::ACK, enumclass); + PTF_ASSERT_TRUE(doipLayer->hasPreviousMessage()); + const std::vector& prev{ 0X22, 0Xf1, 0x01 }; + PTF_ASSERT_TRUE(*doipLayer->getPreviousMessage() == prev); } PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) @@ -1128,30 +959,48 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x2, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0xe, 0x80, 0x0 }; - pcpp::DiagnosticAckMessageData data; - data.sourceAddress = be16toh(0x4010); - data.targetAddress = be16toh(0x0e80); - data.ackCode = pcpp::DoIpDiagnosticAckCodes::ACK; - // dont use previous message - data.previousMessage.clear(); + pcpp::DiagnosticAckMessage data(0x4010, 0xe80, pcpp::DoIpDiagnosticAckCodes::ACK); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); - - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); - pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Ack"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)"); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 5); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Ack (0x8002)"); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x4010); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x0e80); + PTF_ASSERT_EQUAL(doipLayer->getAckCode(), pcpp::DoIpDiagnosticAckCodes::ACK, enumclass); + PTF_ASSERT_FALSE(doipLayer->hasPreviousMessage()); + const std::vector* nullprev = doipLayer->getPreviousMessage(); + PTF_ASSERT_TRUE(nullprev == nullptr); + + PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x4010\nTarget Address: 0xe80\nACK code: ACK (0x0)\n"); + + doipLayer->setSourceAddress(0x7080); + doipLayer->setTargetAddress(0x9010); + const std::vector& prev = { 0x10, 0x20, 0x30, 0x40, 0x50 }; + doipLayer->setPreviousMessage(prev); + PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x7080); + PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x9010); + PTF_ASSERT_TRUE(doipLayer->hasPreviousMessage()); + PTF_ASSERT_TRUE(*doipLayer->getPreviousMessage() == prev); + + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "Source Address: 0x7080\nTarget Address: 0x9010\nACK code: ACK (0x0)\nPrevious message: 1020304050\n"); + unsigned char newBytes[] = { 0x2, 0xfd, 0x80, 0x2, 0x0, 0x0, 0x0, 0xa, 0x70, + 0x80, 0x90, 0x10, 0x0, 0x10, 0x20, 0x30, 0x40, 0x50 }; + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 72); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (72 - 18), newBytes, 18); } -// ------------------ + // DiagnosticNackMessagePacket PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) { @@ -1160,38 +1009,37 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpDiagnosticNackMessagePacket.dat"); - pcpp::Packet DiagnosticNackMessage(&rawPacket1); - PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::IPv4)); - PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::TCP)); - PTF_ASSERT_TRUE(DiagnosticNackMessage.isPacketOfType(pcpp::DOIP)); + pcpp::Packet diagnosticNackPacket(&rawPacket1); + PTF_ASSERT_TRUE(diagnosticNackPacket.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(diagnosticNackPacket.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_TRUE(diagnosticNackPacket.isPacketOfType(pcpp::DOIP)); - pcpp::TcpLayer* tcpLayer = DiagnosticNackMessage.getLayerOfType(); + pcpp::TcpLayer* tcpLayer = diagnosticNackPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53854); PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0x47a1)); - pcpp::DoIpLayer* doipLayer = DiagnosticNackMessage.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); + auto* nackLayer = diagnosticNackPacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(nackLayer); - pcpp::DiagnosticNackMessageData data; - if (data.buildFromLayer(*doipLayer)) - // std::cout << data.toString(); - PTF_ASSERT_EQUAL( - data.toString(), - "source address: 0x4010\ntarget address: 0xe80\nnack code: Invalid source address (0x2)\nprevious message: 22f101\n"); - // wrong build + PTF_ASSERT_EQUAL(nackLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(nackLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(nackLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); + PTF_ASSERT_EQUAL(nackLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); - pcpp::RoutingActivationRequestData routingData; - PTF_ASSERT_FALSE(routingData.buildFromLayer(*doipLayer)); + PTF_ASSERT_EQUAL(nackLayer->getPayloadLength(), 8); + PTF_ASSERT_EQUAL(nackLayer->toString(), "DoIP Layer, Diagnostic message Nack (0x8003)"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 8); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic message Nack (0x8003)") + PTF_ASSERT_EQUAL(nackLayer->getSourceAddress(), 0x4010); + PTF_ASSERT_EQUAL(nackLayer->getTargetAddress(), 0x0e80); + PTF_ASSERT_EQUAL(nackLayer->getNackCode(), pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, enumclass); + + PTF_ASSERT_TRUE(nackLayer->hasPreviousMessage()); + const std::vector expectedPrev = { 0x22, 0xF1, 0x01 }; + PTF_ASSERT_TRUE(*nackLayer->getPreviousMessage() == expectedPrev); + + PTF_ASSERT_EQUAL( + nackLayer->getSummary(), + "Source Address: 0x4010\nTarget Address: 0xe80\nNACK code: Invalid source address (0x2)\nPrevious message: 22f101\n"); } PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) @@ -1200,7 +1048,6 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400); - ipLayer.getIPv4Header()->timeToLive = 128; PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); @@ -1208,30 +1055,225 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&tcpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x3, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0xe, 0x80, 0x2 }; + // Create NACK message with no previous message + pcpp::DiagnosticNackMessage nackMsg(0x4010, 0x0e80, pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&nackMsg)); + doIpPacket.computeCalculateFields(); + + // Validate buffer content (13 bytes with no previous message) + unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x3, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0x0e, 0x80, 0x02 }; + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); + + auto* layer = doIpPacket.getLayerOfType(); + PTF_ASSERT_EQUAL(layer->getSourceAddress(), 0x4010); + PTF_ASSERT_EQUAL(layer->getTargetAddress(), 0x0e80); + PTF_ASSERT_EQUAL(layer->getNackCode(), pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, enumclass); + PTF_ASSERT_FALSE(layer->hasPreviousMessage()); + PTF_ASSERT_TRUE(layer->getPreviousMessage() == nullptr); + + // Update fields and add previous message + layer->setSourceAddress(0xDEAD); + layer->setTargetAddress(0xBEEF); + const std::vector prevMsg = { 0xAA, 0xBB, 0xCC }; + layer->setPreviousMessage(prevMsg); + + PTF_ASSERT_EQUAL(layer->getSourceAddress(), 0xDEAD); + PTF_ASSERT_EQUAL(layer->getTargetAddress(), 0xBEEF); + PTF_ASSERT_TRUE(layer->hasPreviousMessage()); + PTF_ASSERT_TRUE(*layer->getPreviousMessage() == prevMsg); + + PTF_ASSERT_EQUAL( + layer->getSummary(), + "Source Address: 0xdead\nTarget Address: 0xbeef\nNACK code: Invalid source address (0x2)\nPrevious message: aabbcc\n"); + + // Validate full buffer again + unsigned char newBytes[] = { 0x2, 0xfd, 0x80, 0x3, 0x0, 0x0, 0x0, 0x8, + 0xde, 0xad, 0xbe, 0xef, 0x02, 0xaa, 0xbb, 0xcc }; + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 70); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (70 - 16), newBytes, 16); +} +// PowerModeRequestPacket +PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpPowerModeRequestPacket.dat"); + + pcpp::Packet PowerModeRequest(&rawPacket1); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(PowerModeRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = PowerModeRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + + auto* doipLayer = PowerModeRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") +} + +PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; - pcpp::DiagnosticNackMessageData data; - data.sourceAddress = be16toh(0x4010); - data.targetAddress = be16toh(0x0e80); - data.nackCode = pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS; - // dont use previous message - data.previousMessage.clear(); + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); - pcpp::DoIpLayer doipLayer_2(pcpp::DoIpProtocolVersion::Version02Iso2012, data); + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; + pcpp::DiagnosticPowerModeRequest req; - PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer_2)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") +} +// EntityStatusRequestPacket +PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpEntityStatusRequestPacket.dat"); + + pcpp::Packet EntityStatusRequest(&rawPacket1); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(EntityStatusRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = EntityStatusRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); + PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4988)); + + auto* doipLayer = EntityStatusRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status request (0x4001)") +} + +PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; + pcpp::EntityStatusRequest req; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); + doIpPacket.computeCalculateFields(); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic message Nack"); - PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 5); - PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic message Nack (0x8003)"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status request (0x4001)") +} +// AliveCheckRequestPacket +PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpAliveCheckRequestPacket.dat"); + + pcpp::Packet AliveCheckRequest(&rawPacket1); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::UDP)); + PTF_ASSERT_TRUE(AliveCheckRequest.isPacketOfType(pcpp::DOIP)); + + pcpp::UdpLayer* udpLayer = AliveCheckRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(udpLayer); + + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + + auto* doipLayer = AliveCheckRequest.getLayerOfType(); + PTF_ASSERT_NOT_NULL(doipLayer); + + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); + PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check request (0x0007)") +} + +PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) +{ + pcpp::Packet doIpPacket(100); + pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240")); + pcpp::UdpLayer udpLayer((uint16_t)13400, (uint16_t)13400); + + ipLayer.getIPv4Header()->timeToLive = 128; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(ðLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&ipLayer)); + PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); + doIpPacket.computeCalculateFields(); + + unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; + pcpp::AliveCheckRequest req; + + PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); + doIpPacket.computeCalculateFields(); + + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); + auto* _doipLayer2 = doIpPacket.getLayerOfType(); + + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); + PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); + PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check request (0x0007)") } // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) @@ -1246,16 +1288,13 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::UDP)); PTF_ASSERT_TRUE(vehicleIdentificationRequest.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); + auto* udpLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x8988)); - PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->length, be16toh(0x10)); // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012); @@ -1265,9 +1304,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); - -} // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing - +} // DoIpInvalidPayloadTypePacketPacketParsing PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) { @@ -1279,24 +1316,21 @@ PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) pcpp::Packet InvalidPayloadTypePacket(&rawPacket1); PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::IPv4)); PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::UDP)); - PTF_ASSERT_TRUE(InvalidPayloadTypePacket.isPacketOfType(pcpp::DOIP)); + PTF_ASSERT_FALSE(InvalidPayloadTypePacket.isPacketOfType(pcpp::DOIP)); - pcpp::UdpLayer* udpLayer = InvalidPayloadTypePacket.getLayerOfType(); - PTF_ASSERT_NOT_NULL(udpLayer); +} // DoIpInvalidPayloadTypePacketParsing - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); +// DoIpInvalidPayloadTypePacketPacketParsing +PTF_TEST_CASE(DoIpInvalidPayloadLenPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); - // DOIP fields for vehicle identification request - pcpp::DoIpLayer* doipLayer = InvalidPayloadTypePacket.getLayerOfType(); - PTF_ASSERT_NOT_NULL(doipLayer); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpWrongLengthRoutingActivationRequestPacket.dat"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xfd); - PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, enumclass); - PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Unknown payload type"); - PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Unknown payload type (0x7777)"); - PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); + pcpp::Packet InvalidPayloadLenPacket(&rawPacket1); + PTF_ASSERT_TRUE(InvalidPayloadLenPacket.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(InvalidPayloadLenPacket.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_FALSE(InvalidPayloadLenPacket.isPacketOfType(pcpp::DOIP)); } // DoIpInvalidPayloadTypePacketParsing -DISABLE_WARNING_POP diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 37e34c9d1e..a6b4772f0f 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -187,40 +187,41 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DnsOverTcpCreationTest, "dns"); PTF_RUN_TEST(DnsLayerAddDnsKeyTest, "dns"); + PTF_RUN_TEST(DoIpRoutingActivationRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpRoutingActivationResponsePacketCreation, "doip"); PTF_RUN_TEST(DoIpGenericHeaderNackPacketParsing, "doip"); PTF_RUN_TEST(DoIpGenericHeaderNackPacketCreation, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketParsing, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketCreation, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketParsing, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketCreation, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketParsing, "doip"); PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketCreation, "doip"); PTF_RUN_TEST(DoIpVehicleAnnouncementPacketParsing, "doip"); PTF_RUN_TEST(DoIpVehicleAnnouncementPacketCreation, "doip"); - PTF_RUN_TEST(DoIpRoutingActivationRequestPacketParsing, "doip"); - PTF_RUN_TEST(DoIpRoutingActivationRequestPacketCreation, "doip"); - PTF_RUN_TEST(DoIpRoutingActivationResponsePacketParsing, "doip"); - PTF_RUN_TEST(DoIpRoutingActivationResponsePacketCreation, "doip"); - PTF_RUN_TEST(DoIpAliveCheckRequestPacketParsing, "doip"); - PTF_RUN_TEST(DoIpAliveCheckRequestPacketCreation, "doip"); PTF_RUN_TEST(DoIpAliveCheckResponsePacketParsing, "doip"); PTF_RUN_TEST(DoIpAliveCheckResponsePacketCreation, "doip"); - PTF_RUN_TEST(DoIpEntityStatusRequestPacketParsing, "doip"); - PTF_RUN_TEST(DoIpEntityStatusRequestPacketCreation, "doip"); - PTF_RUN_TEST(DoIpEntityStatusResponsePacketParsing, "doip"); - PTF_RUN_TEST(DoIpEntityStatusResponsePacketCreation, "doip"); - PTF_RUN_TEST(DoIpPowerModeRequestPacketParsing, "doip"); - PTF_RUN_TEST(DoIpPowerModeRequestPacketCreation, "doip"); PTF_RUN_TEST(DoIpPowerModeResponsePacketParsing, "doip"); PTF_RUN_TEST(DoIpPowerModeResponsePacketCreation, "doip"); + PTF_RUN_TEST(DoIpEntityStatusResponsePacketParsing, "doip"); + PTF_RUN_TEST(DoIpEntityStatusResponsePacketCreation, "doip"); PTF_RUN_TEST(DoIpDiagnosticMessagePacketParsing, "doip"); PTF_RUN_TEST(DoIpDiagnosticMessagePacketCreation, "doip"); PTF_RUN_TEST(DoIpDiagnosticAckMessagePacketParsing, "doip"); PTF_RUN_TEST(DoIpDiagnosticAckMessagePacketCreation, "doip"); PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketParsing, "doip"); PTF_RUN_TEST(DoIpDiagnosticNackMessagePacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpPowerModeRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpPowerModeRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpEntityStatusRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpEntityStatusRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpAliveCheckRequestPacketParsing, "doip"); + PTF_RUN_TEST(DoIpAliveCheckRequestPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing, "doip"); PTF_RUN_TEST(DoIpInvalidPayloadTypePacketParsing, "doip"); + PTF_RUN_TEST(DoIpInvalidPayloadLenPacketParsing, "doip"); PTF_RUN_TEST(IcmpParsingTest, "icmp"); PTF_RUN_TEST(IcmpCreationTest, "icmp"); From f06112e2d925297a9f395244815b94786761e762 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sat, 19 Apr 2025 14:38:03 -0400 Subject: [PATCH 28/43] fix clang indentation error --- Packet++/src/TcpLayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 91b17889e5..079ad3c114 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -367,7 +367,7 @@ namespace pcpp const uint16_t portSrc = getSrcPort(); const char* payloadChar = reinterpret_cast(payload); - if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && + if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(payload, payloadLen))) m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); if (HttpMessage::isHttpPort(portDst) && From 0c7a19a81e791b5502a18c6ae633a1272944e02f Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 20 Apr 2025 03:13:52 -0400 Subject: [PATCH 29/43] try fix pipeline --- Packet++/header/DoIpLayer.h | 96 +++++------ Packet++/src/DoIpLayer.cpp | 26 +-- Packet++/src/TcpLayer.cpp | 8 +- .../DoIpInvalidProtocolVersionPacket.dat | 1 + Tests/Packet++Test/TestDefinition.h | 1 + Tests/Packet++Test/Tests/DoIpTests.cpp | 157 +++++++++++------- Tests/Packet++Test/main.cpp | 1 + 7 files changed, 164 insertions(+), 126 deletions(-) create mode 100644 Tests/Packet++Test/PacketExamples/DoIpInvalidProtocolVersionPacket.dat diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 447e7772ab..d49227aacf 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -4,6 +4,7 @@ #include "IpAddress.h" #include "MacAddress.h" #include "Logger.h" +#include "EndianPortable.h" #include /// @file @@ -12,22 +13,23 @@ /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { + /// @brief Length of the Equiepement Identifier (EID) field. + constexpr size_t DOIP_EID_LEN = 6; -/// @brief Length of the External Identifier (EID) field. -#define DOIP_EID_LEN 6 + /// @brief Length of the Group Identifier (GID) field. + constexpr size_t DOIP_GID_LEN = 6; -/// @brief Length of the Group Identifier (GID) field. -#define DOIP_GID_LEN 6 + /// @brief Length of the Vehicle Identification Number (VIN) field. + constexpr size_t DOIP_VIN_LEN = 17; -/// @brief Length of the Vehicle Identification Number (VIN) field. -#define DOIP_VIN_LEN 17 + /// @brief Length of the Reserved ISO field. + constexpr size_t DOIP_RESERVED_ISO_LEN = 4; -/// @brief Length of the Reserved ISO field. -#define DOIP_RESERVED_ISO_LEN 4 - -/// @brief Length of the Reserved OEM field. -#define DOIP_RESERVED_OEM_LEN 4 + /// @brief Length of the Reserved OEM field. + constexpr size_t DOIP_RESERVED_OEM_LEN = 4; + /// @brief Enum representing DoIP routing activation types. + /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). enum class DoIpActivationTypes : uint8_t { /// Default routing activation type. @@ -73,7 +75,6 @@ namespace pcpp /// Some codes are reserved for future use by ISO standards. enum class DoIpActionCodes : uint8_t { - /// No further action required. /// Indicates that no additional steps are needed after the announcement. NO_FURTHER_ACTION_REQUIRED = 0x00U, @@ -227,7 +228,6 @@ namespace pcpp /// in the DoIP protocol. enum class DoIpDiagnosticMessageNackCodes : uint8_t { - /// Reserved for ISO (0x00). /// Reserved for future use as per ISO standards. RESERVED_ISO_0x00 = 0x00U, @@ -270,7 +270,6 @@ namespace pcpp /// providing information about its readiness for diagnostic operations. enum class DoIpDiagnosticPowerModeCodes : uint8_t { - /// Not ready. /// The DoIP entity is not ready to perform diagnostic operations. NOT_READY = 0x00U, @@ -289,9 +288,8 @@ namespace pcpp /// in the DoIP protocol. enum class DoIpDiagnosticAckCodes : uint8_t { - - /// Acknowledgment./// Indicates successful receipt or acknowledgment of a diagnostic message. - + /// Acknowledgment. + /// Indicates successful receipt or acknowledgment of a diagnostic message. ACK = 0x00U }; @@ -313,7 +311,6 @@ namespace pcpp /// These codes are used to indicate whether GID and VIN are synchronized or not. enum class DoIpSyncStatus : uint8_t { - /// VIN and or GID are synchronized. VIN_AND_OR_GID_ARE_SINCHRONIZED = 0x00, @@ -379,9 +376,6 @@ namespace pcpp /// VIN and or GID are not synchronized. VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, - - /// Check whether this field is initialised or not - NON_INITIALIZED }; /// @brief Represents the DoIP (Diagnostics over IP) protocol versions. @@ -408,7 +402,7 @@ namespace pcpp DefaultVersion = 0xFFU, /// Represents an unknown or unsupported protocol version (not specified by ISO). - /// Used to indicate an unsupported or unknown protocol version for internal handling. + /// Used to indicate an unsupported or unknown protocol version for internal usage. UnknownVersion = 0xEF }; @@ -479,16 +473,11 @@ namespace pcpp /// Diagnostic message negative acknowledgment. /// Indicates an error in processing a diagnostic message. - DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U, - - /// Represents an invalid payload type (not specified by ISO). - /// Used to indicate an unsupported or unrecognized payload type for internal handling. - UNKNOWN_PAYLOAD_TYPE = 0xFFFFU, + DIAGNOSTIC_MESSAGE_NEG_ACK = 0x8003U }; /// @brief Enum representing DoIP diagnostic ports (ISO 13400). /// These ports are used for communication in the DoIP protocol over different transport layers. - enum class DoIpPorts : uint16_t { @@ -546,6 +535,10 @@ namespace pcpp /// @param[in] version the version of DOIP protocol to set, restricted to existent doip version void setProtocolVersion(DoIpProtocolVersion version); + /// Additional setter for raw protocol version (for testing/fuzzing/debugging) + /// @param[in] version the raw version of DOIP protocol to set + void setProtocolVersion(uint8_t Rawversion); + /// Get the invert version of DOIP protocol /// @return A uint8_t presenting the used protocol invert version (DOIPV) uint8_t getInvertProtocolVersion() const; @@ -558,10 +551,6 @@ namespace pcpp /// @return uint16_t presenting the message doip payload type as string std::string getPayloadTypeAsStr() const; - /// Set the doip payload type - /// @param[in] payloadType the payload type to set - void setPayloadType(DoIpPayloadTypes payloadType); - /// Get the doip payload length /// @return uint32_t presenting the length of doip paylad not including the header uint32_t getPayloadLength() const; @@ -610,7 +599,7 @@ namespace pcpp return m_DataLen; } - std::string toString() const; + std::string toString() const override; void computeCalculateFields() override {}; @@ -618,6 +607,9 @@ namespace pcpp { return OsiModelTransportLayer; } + private: + + void setPayloadType(DoIpPayloadTypes payloadType); protected: // protected c'tors, this class cannot be instantiated by users @@ -660,7 +652,7 @@ namespace pcpp if (!isPayloadTypeValid(payloadRaw)) return false; - + // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() if (!isProtocolVersionValid(version, inVersion, payloadType)) return false; @@ -676,24 +668,25 @@ namespace pcpp switch (parsedVersion) { - case DoIpProtocolVersion::DefaultVersion: case DoIpProtocolVersion::ReservedVersion: + { + PCPP_LOG_ERROR("[Malformed doip packet]: Reserved ISO DoIP protocol version detected: 0x" + << std::hex << static_cast(version)); + return false; + } + case DoIpProtocolVersion::DefaultVersion: + if (type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && + type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST) + { + PCPP_LOG_ERROR("[Malformed doip packet]: Invalid/unsupported DoIP version!"); + return false; + } case DoIpProtocolVersion::Version01Iso2010: case DoIpProtocolVersion::Version02Iso2012: case DoIpProtocolVersion::Version03Iso2019: case DoIpProtocolVersion::Version04Iso2019_AMD1: - if (parsedVersion == DoIpProtocolVersion::UnknownVersion || - parsedVersion == DoIpProtocolVersion::ReservedVersion || - (parsedVersion == DoIpProtocolVersion::DefaultVersion && - type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && - type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && - type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST)) - { - PCPP_LOG_ERROR("[Malformed doip packet]: Invalid or unsupported DoIP protocol version: 0x" - << std::hex << static_cast(version)); - return false; - } - + { if (version != static_cast(~inVersion)) { PCPP_LOG_ERROR("[Malformed doip packet]: Protocol version and inverse version mismatch! Version: 0x" @@ -701,9 +694,8 @@ namespace pcpp << static_cast(inVersion)); return false; } - return true; - + } default: PCPP_LOG_ERROR("[Malformed doip packet]: Unknown DoIP protocol version: 0x" << std::hex << static_cast(version)); @@ -796,7 +788,7 @@ namespace pcpp DoIpActivationTypes getActivationType() const; /// @brief Sets the activation type. - void setActivationType(const DoIpActivationTypes& activationType); + void setActivationType(DoIpActivationTypes activationType); /// @brief Gets the reserved ISO bytes. std::array getReservedIso() const; @@ -1393,7 +1385,7 @@ namespace pcpp /// @brief Represents a positive acknowledgment message in response to a DiagnosticMessage. /// /// This message is sent by a DoIP node to acknowledge the correct reception and processing - /// of a diagnostic message. Optionally, the original message may be echoed back. + /// of a diagnostic message. Optionally, the original message (or part of it) may be echoed back. class DiagnosticAckMessage : public DoIpLayer { public: @@ -1434,7 +1426,7 @@ namespace pcpp /// @brief Checks if a previous message is attached. /// @return True if a previous message is present. - bool hasPreviousMessage(); + bool hasPreviousMessage() const; /// @brief Sets the previous echoed diagnostic message. void setPreviousMessage(const std::vector& msg); diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 6c09015279..9453a9e489 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -143,8 +143,7 @@ namespace pcpp { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, - { DoIpSyncStatus::NON_INITIALIZED, "NULL" } + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" } }; // This unordered map provides human-readable descriptions for each version of the @@ -180,8 +179,7 @@ namespace pcpp { DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, "Diagnostic power mode response information" }, { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, "Diagnostic message" }, { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, "Diagnostic message Ack" }, - { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" }, - { DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE, "Unknown payload type" } + { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } }; DoIpProtocolVersion DoIpLayer::getProtocolVersion() const @@ -269,6 +267,11 @@ namespace pcpp getDoIpHeader()->protocolVersion = static_cast(version); } + void DoIpLayer::setProtocolVersion(uint8_t version) + { + getDoIpHeader()->protocolVersion = version; + } + uint8_t DoIpLayer::getInvertProtocolVersion() const { return getDoIpHeader()->invertProtocolVersion; @@ -307,9 +310,7 @@ namespace pcpp DoIpPayloadTypes type = getPayloadType(); oss << "DoIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') - << (type == DoIpPayloadTypes::UNKNOWN_PAYLOAD_TYPE ? (be16toh(getDoIpHeader()->payloadType)) - : static_cast(type)) - << ")"; + << static_cast(type) << ")"; return oss.str(); } @@ -378,12 +379,14 @@ namespace pcpp } RoutingActivationRequest::RoutingActivationRequest(uint16_t sourrceAddress, DoIpActivationTypes activationType) - : _reservedIso{}, _hasReservedOem(false) + : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); extendLayer(sizeof(doiphdr), FIXED_LEN); + setSourceAddress(sourrceAddress); setActivationType(activationType); + setReservedIso({}); } DoIpActivationTypes RoutingActivationRequest::getActivationType() const @@ -391,7 +394,7 @@ namespace pcpp return _activationType; } - void RoutingActivationRequest::setActivationType(const DoIpActivationTypes& activationType) + void RoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) { uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)); memcpy(dataPtr, &activationType, sizeof(activationType)); @@ -522,7 +525,7 @@ namespace pcpp } RoutingActivationResponse::RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode) - : _reservedIso{}, _reservedOem{}, _hasReservedOem(false) + : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); extendLayer(sizeof(doiphdr), FIXED_LEN); @@ -530,6 +533,7 @@ namespace pcpp setLogicalAddressExternalTester(logicalAddressExternalTester); setSourceAddress(sourceAddress); setResponseCode(responseCode); + setReservedIso({}); } uint16_t RoutingActivationResponse::getLogicalAddressExternalTester() const @@ -1320,7 +1324,7 @@ namespace pcpp *ptr = static_cast(code); } - bool DiagnosticAckMessage::hasPreviousMessage() + bool DiagnosticAckMessage::hasPreviousMessage() const { return _hasPreviousMessage; } diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 079ad3c114..425e2a9d36 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -369,9 +369,11 @@ namespace pcpp if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(payload, payloadLen))) - m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); - if (HttpMessage::isHttpPort(portDst) && - HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) + { + setNextLayer(DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet)); + } + else if (HttpMessage::isHttpPort(portDst) && + HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) { constructNextLayer(payload, payloadLen, m_Packet); } diff --git a/Tests/Packet++Test/PacketExamples/DoIpInvalidProtocolVersionPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpInvalidProtocolVersionPacket.dat new file mode 100644 index 0000000000..1574f0088e --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/DoIpInvalidProtocolVersionPacket.dat @@ -0,0 +1 @@ +001a37bfee7454e1ad6bac1508004500003bf0e44000400609fea9fe75efa9fe75eed25a345849689c4200186ab95018faf04008000002ff00050000000b0e80000000000000000000 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index a61a534dde..5435ddce22 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -124,6 +124,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation); PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing); PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing); PTF_TEST_CASE(DoIpInvalidPayloadLenPacketParsing); +PTF_TEST_CASE(DoIpInvalidProtocolVersionPacketParsing); // Implemented in IcmpTests.cpp PTF_TEST_CASE(IcmpParsingTest); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 1dd87c4f3a..99c8878bfc 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -91,7 +91,12 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); - + // check for setting invalid protocol version, will be applicable for all derived classes + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + doipLayer.setProtocolVersion(0x55); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::UnknownVersion, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersionAsStr(), "Unknown Protocol Version"); + doipLayer.setProtocolVersion(pcpp::DoIpProtocolVersion::Version02Iso2012); PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); @@ -104,15 +109,12 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); PTF_ASSERT_VECTORS_EQUAL(*doipLayer.getReservedOem(), oemField); - // std::cout << pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(), - // doIpPacket.getRawPacket()->getRawDataLen()) << "\n"; + doipLayer.clearReserveOem(); - // std::cout << - // pcpp::byteArrayToHexString(doIpPacket.getRawPacket()->getRawData(),doIpPacket.getRawPacket()->getRawDataLen()) << - // "\n"; + PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); - PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - DOIP_RESERVED_OEM_LEN); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - DOIP_RESERVED_OEM_LEN) - 15, bytes, 15); + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - 4); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 4) - 15, bytes, 15); PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), isoReserved); PTF_ASSERT_TRUE(doipLayer.getReservedOem() == nullptr); PTF_ASSERT_EQUAL(doipLayer.getSummary(), @@ -250,6 +252,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Generic header nack code: Unknown payload type (0x1)\n"); } +// DoIpGenericHeaderNackPacketCreation PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) { pcpp::Packet doIpPacket(100); @@ -315,11 +318,12 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request with EID"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x6); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)") - std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; + std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); } // VehicleIdentificationWithEIDacketParsing +// DoIpVehicleIdentificationRequestEIDPacketCreation PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) { pcpp::Packet doIpPacket(100); @@ -335,7 +339,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; - std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; + std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; pcpp::VehicleIdentificationRequestEID withEID(eid); withEID.setEID(eid); @@ -355,9 +359,9 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) PTF_ASSERT_EQUAL(withEID.toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)"); PTF_ASSERT_VECTORS_EQUAL(withEID.getEID(), eid); PTF_ASSERT_EQUAL(withEID.getSummary(), "EID: 4241554e4545\n"); -} +} // DoIpVehicleIdentificationRequestEIDPacketCreation -// VehicleIdentificationWithVIN +// DoIpVehicleIdentificationRequestVINPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) { // Dissect Vehicle identification Request with VIN @@ -387,8 +391,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x11); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)"); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\n"); - std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, - 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getVIN(), vin); @@ -411,8 +415,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x3, 0x0, 0x0, 0x0, 0x11, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, - 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; pcpp::VehicleIdentificationRequestVIN withVin(vin); withVin.setVIN(vin); @@ -432,9 +436,9 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) PTF_ASSERT_EQUAL(withVin.toString(), "DoIP Layer, Vehicle identification request with VIN (0x0003)"); PTF_ASSERT_EQUAL(withVin.getSummary(), "VIN: BAUNEE4MZ17042403\n"); PTF_ASSERT_VECTORS_EQUAL(withVin.getVIN(), vin); -} +} // DoIpVehicleIdentificationRequestVINPacketCreation -// VehicleAnnouncement +// DoIpVehicleAnnouncementPacketParsing PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) { // Dissect Vehicle Announcement message @@ -443,10 +447,10 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleAnnouncementPacket.dat"); - std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; - std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; - std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, - 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; pcpp::Packet VehicleAnnouncement(&rawPacket1); PTF_ASSERT_TRUE(VehicleAnnouncement.isPacketOfType(pcpp::UDP)); @@ -482,6 +486,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_NULL(doipLayer->getSyncStatus()); } // DoIpVehicleAnnouncementPacketParsing +// DoIpVehicleAnnouncementPacketCreation PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) { pcpp::Packet doIpPacket(100); @@ -499,10 +504,10 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x4, 0x0, 0x0, 0x0, 0x21, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33, 0x40, 0x10, 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74, 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74, 0x0, 0x0 }; - std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; - std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; - std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, - 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; + std::array eid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array gid{ 0x0, 0x1a, 0x37, 0xbf, 0xee, 0x74 }; + std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, + 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; pcpp::VehicleAnnouncement ann(vin, 0x4010, eid, gid, pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED); ann.setSyncStatus(pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED); @@ -535,7 +540,8 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_EQUAL( doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\n"); -} +} // DoIpVehicleIdentificationRequestPacketParsing + // DoIpVehicleIdentificationRequestPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) { @@ -566,6 +572,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) } // DoIpVehicleIdentificationRequestPacketParsing +// DoIpVehicleIdentificationRequestPacketCreation PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) { pcpp::Packet doIpPacket(100); @@ -596,8 +603,9 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0x0); -} -// AliveCheckResponsePacket +} // DoIpVehicleIdentificationRequestPacketCreation + +// DoIpAliveCheckResponsePacketParsing PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) { timeval time; @@ -626,8 +634,9 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 2); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check response (0x0008)"); PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x00); -} +} // DoIpAliveCheckResponsePacketParsing +// DoIpAliveCheckResponsePacketCreation PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) { pcpp::Packet doIpPacket(100); @@ -661,8 +670,9 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) doipLayer->setSourceAddress(0x3040); PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x3040); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x3040\n"); -} -// PowerModeResponsePacket +} // DoIpAliveCheckResponsePacketCreation + +// DoIpPowerModeResponsePacketParsing PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) { timeval time; @@ -693,7 +703,9 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 1); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode response information (0x4004)"); PTF_ASSERT_EQUAL(doipLayer->getPowerModeCode(), pcpp::DoIpDiagnosticPowerModeCodes::NOT_READY, enumclass); -} +} // DoIpPowerModeResponsePacketParsing + +// DoIpPowerModeResponsePacketCreation PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) { pcpp::Packet doIpPacket(100); @@ -729,9 +741,9 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) doipLayer->setPowerModeCode(pcpp::DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED); PTF_ASSERT_EQUAL(doipLayer->getPowerModeCode(), pcpp::DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, enumclass); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: not supported (0x2)\n"); -} +} // DoIpPowerModeResponsePacketCreation -// EntityStatusResponsePacket +// DoIpEntityStatusResponsePacketParsing PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) { timeval time; @@ -765,10 +777,11 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatus::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 1); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 0); - std::array maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; + const std::array& maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; PTF_ASSERT_TRUE(*doipLayer->getMaxDataSize() == maxDataSize); -} +} // DoIpEntityStatusResponsePacketParsing +// DoIpEntityStatusResponsePacketCreation PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) { pcpp::Packet doIpPacket(100); @@ -814,9 +827,9 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) doipLayer->clearMaxDataSize(); PTF_ASSERT_FALSE(doipLayer->hasMaxDataSize()); PTF_ASSERT_TRUE(doipLayer->getMaxDataSize() == nullptr); -} +} // DoIpEntityStatusResponsePacketCreation -// DiagnosticMessagePacket +// DoIpDiagnosticMessagePacketParsing PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) { timeval time; @@ -854,8 +867,9 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4010); const std::vector& diagData{ 0x10, 0x03 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getDiagnosticData(), diagData); -} +} // DoIpDiagnosticMessagePacketParsing +// DoIpDiagnosticMessagePacketCreation PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) { pcpp::Packet doIpPacket(100); @@ -903,9 +917,9 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4343); PTF_ASSERT_VECTORS_EQUAL(doipLayer->getDiagnosticData(), newDiagnosticData); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x8080\nTarget Address: 0x4343\n"); -} +} // DoIpDiagnosticMessagePacketCreation -// DiagnosticAckMessagePacket +// DoIpDiagnosticAckMessagePacketParsing PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) { timeval time; @@ -941,8 +955,9 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_TRUE(doipLayer->hasPreviousMessage()); const std::vector& prev{ 0X22, 0Xf1, 0x01 }; PTF_ASSERT_TRUE(*doipLayer->getPreviousMessage() == prev); -} +} // DoIpDiagnosticAckMessagePacketParsing +// DoIpDiagnosticAckMessagePacketCreation PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) { pcpp::Packet doIpPacket(100); @@ -999,9 +1014,9 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) 0x80, 0x90, 0x10, 0x0, 0x10, 0x20, 0x30, 0x40, 0x50 }; PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 72); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (72 - 18), newBytes, 18); -} +} // DoIpDiagnosticAckMessagePacketCreation -// DiagnosticNackMessagePacket +// DoIpDiagnosticNackMessagePacketParsing PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) { timeval time; @@ -1040,8 +1055,9 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_EQUAL( nackLayer->getSummary(), "Source Address: 0x4010\nTarget Address: 0xe80\nNACK code: Invalid source address (0x2)\nPrevious message: 22f101\n"); -} +} // DoIpDiagnosticNackMessagePacketParsing +// DoIpDiagnosticNackMessagePacketCreation PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) { pcpp::Packet doIpPacket(100); @@ -1092,8 +1108,9 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) 0xde, 0xad, 0xbe, 0xef, 0x02, 0xaa, 0xbb, 0xcc }; PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 70); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (70 - 16), newBytes, 16); -} -// PowerModeRequestPacket +} // DoIpDiagnosticNackMessagePacketCreation + +// DoIpPowerModeRequestPacketParsing PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) { timeval time; @@ -1120,8 +1137,9 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") -} +} // DoIpPowerModeRequestPacketParsing +// DoIpPowerModeRequestPacketCreation PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) { pcpp::Packet doIpPacket(100); @@ -1152,8 +1170,9 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Diagnostic power mode request information (0x4003)") -} -// EntityStatusRequestPacket +} // DoIpPowerModeRequestPacketCreation + +// DoIpEntityStatusRequestPacketParsing PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) { timeval time; @@ -1182,8 +1201,9 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status request (0x4001)") -} +} // DoIpEntityStatusRequestPacketParsing +// DoIpEntityStatusRequestPacketCreation PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) { pcpp::Packet doIpPacket(100); @@ -1214,8 +1234,9 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status request (0x4001)") -} -// AliveCheckRequestPacket +} // DoIpEntityStatusRequestPacketCreation + +// DoIpAliveCheckRequestPacketParsing PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) { timeval time; @@ -1242,8 +1263,9 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Alive check request (0x0007)") -} +} // DoIpAliveCheckRequestPacketParsing +// DoIpAliveCheckRequestPacketCreation PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) { pcpp::Packet doIpPacket(100); @@ -1274,7 +1296,8 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 0); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, Alive check request (0x0007)") -} +} // DoIpAliveCheckRequestPacketCreation + // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) { @@ -1293,19 +1316,18 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - // DOIP fields for vehicle identification request auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - // PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::DefaultVersion, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0x00); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); -} -// DoIpInvalidPayloadTypePacketPacketParsing +} // DoIpInvalidPayloadTypePacketPacketParsing + +// DoIpInvalidPayloadTypePacketParsing PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) { timeval time; @@ -1334,3 +1356,18 @@ PTF_TEST_CASE(DoIpInvalidPayloadLenPacketParsing) PTF_ASSERT_FALSE(InvalidPayloadLenPacket.isPacketOfType(pcpp::DOIP)); } // DoIpInvalidPayloadTypePacketParsing + +// DoIpInvalidProtocolVersion +PTF_TEST_CASE(DoIpInvalidProtocolVersionPacketParsing) +{ + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpInvalidProtocolVersionPacket.dat"); + + pcpp::Packet InvalidPayloadLenPacket(&rawPacket1); + PTF_ASSERT_TRUE(InvalidPayloadLenPacket.isPacketOfType(pcpp::IPv4)); + PTF_ASSERT_TRUE(InvalidPayloadLenPacket.isPacketOfType(pcpp::TCP)); + PTF_ASSERT_FALSE(InvalidPayloadLenPacket.isPacketOfType(pcpp::DOIP)); + +} // DoIpInvalidProtocolVersion diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index a6b4772f0f..2a6b60ce53 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -222,6 +222,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing, "doip"); PTF_RUN_TEST(DoIpInvalidPayloadTypePacketParsing, "doip"); PTF_RUN_TEST(DoIpInvalidPayloadLenPacketParsing, "doip"); + PTF_RUN_TEST(DoIpInvalidProtocolVersionPacketParsing, "doip"); PTF_RUN_TEST(IcmpParsingTest, "icmp"); PTF_RUN_TEST(IcmpCreationTest, "icmp"); From 51e5de40cddac322d10149de7909b2c6a61e08b5 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 20 Apr 2025 15:06:51 -0400 Subject: [PATCH 30/43] group doipConstants in struct and other improvements --- Packet++/header/DoIpLayer.h | 147 +++++++++--------- Packet++/src/DoIpLayer.cpp | 293 +++++++++++++++++++----------------- 2 files changed, 232 insertions(+), 208 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index d49227aacf..0614a16f13 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -13,20 +13,27 @@ /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /// @brief Length of the Equiepement Identifier (EID) field. - constexpr size_t DOIP_EID_LEN = 6; + /// @brief Represent doip constants fields length + struct DoIpConstants + { + /// @brief Length of the Equiepement Identifier (EID) field. + static constexpr size_t DOIP_EID_LEN = 6; + + /// @brief Length of the Group Identifier (GID) field. + static constexpr size_t DOIP_GID_LEN = 6; - /// @brief Length of the Group Identifier (GID) field. - constexpr size_t DOIP_GID_LEN = 6; + /// @brief Length of the Vehicle Identification Number (VIN) field. + static constexpr size_t DOIP_VIN_LEN = 17; - /// @brief Length of the Vehicle Identification Number (VIN) field. - constexpr size_t DOIP_VIN_LEN = 17; + /// @brief Length of the Reserved ISO field. + static constexpr size_t DOIP_RESERVED_ISO_LEN = 4; - /// @brief Length of the Reserved ISO field. - constexpr size_t DOIP_RESERVED_ISO_LEN = 4; + /// @brief Length of the Reserved OEM field. + static constexpr size_t DOIP_RESERVED_OEM_LEN = 4; - /// @brief Length of the Reserved OEM field. - constexpr size_t DOIP_RESERVED_OEM_LEN = 4; + /// @brief fixed size of valid doip header + static constexpr size_t DOIP_HEADER_LEN = 8; + }; /// @brief Enum representing DoIP routing activation types. /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). @@ -557,12 +564,12 @@ namespace pcpp /// Set the doip payload length /// @param[in] length the doip payload length to set - void setPayloadLength(uint32_t length) const; + void setPayloadLength(uint32_t length); /// A static method that checks whether a port is considered as a DOIP port /// @param[in] port The port number to check /// @return True if this is a DOIP port number, false otherwise - static inline bool isDoIpPort(uint16_t port); + static inline bool isDoIpPort(const uint16_t port); /// A static method that validates the input data /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer @@ -607,8 +614,8 @@ namespace pcpp { return OsiModelTransportLayer; } + private: - void setPayloadType(DoIpPayloadTypes payloadType); protected: @@ -664,7 +671,7 @@ namespace pcpp inline bool DoIpLayer::isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type) { - DoIpProtocolVersion parsedVersion = static_cast(version); + const DoIpProtocolVersion parsedVersion = static_cast(version); switch (parsedVersion) { @@ -705,7 +712,7 @@ namespace pcpp inline bool DoIpLayer::isPayloadTypeValid(uint16_t type) { - DoIpPayloadTypes payloadType = static_cast(htobe16(type)); + const DoIpPayloadTypes payloadType = static_cast(htobe16(type)); switch (payloadType) { @@ -735,15 +742,13 @@ namespace pcpp inline bool DoIpLayer::isPayloadLengthValid(uint32_t payloadLength, size_t dataLen) { - constexpr size_t headerSize = sizeof(doiphdr); - - if (dataLen < headerSize) + if (dataLen < DoIpConstants::DOIP_HEADER_LEN) { PCPP_LOG_ERROR("[Malformed doip packet]: Data length is smaller than DOIP header size!"); return false; } - size_t actualPayloadLen = dataLen - headerSize; + const size_t actualPayloadLen = dataLen - DoIpConstants::DOIP_HEADER_LEN; if (payloadLength != actualPayloadLen) { PCPP_LOG_ERROR("[Malformed doip packet]: Payload length mismatch: expected " @@ -791,16 +796,16 @@ namespace pcpp void setActivationType(DoIpActivationTypes activationType); /// @brief Gets the reserved ISO bytes. - std::array getReservedIso() const; + std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. - void setReservedIso(const std::array& reservedIso); + void setReservedIso(const std::array& reservedIso); /// @brief Gets the reserved OEM bytes if present. - const std::array* getReservedOem() const; + const std::array* getReservedOem() const; /// @brief Sets the reserved OEM bytes. - void setReservedOem(const std::array& reservedOem); + void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. bool hasReservedOem() const; @@ -818,15 +823,16 @@ namespace pcpp } private: - uint16_t _sourceAddress; ///< Source address of the tester. - DoIpActivationTypes _activationType; ///< Routing activation type. - std::array _reservedIso; ///< ISO reserved bytes. - std::array _reservedOem; ///< OEM reserved bytes. - bool _hasReservedOem; ///< Whether OEM bytes are set. + uint16_t _sourceAddress; ///< Source address of the tester. + DoIpActivationTypes _activationType; ///< Routing activation type. + std::array _reservedIso; ///< ISO reserved bytes. + std::array _reservedOem; ///< OEM reserved bytes. + bool _hasReservedOem; ///< Whether OEM bytes are set. - static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_activationType) + DOIP_RESERVED_ISO_LEN; - static constexpr size_t RESERVED_OEM_OFFSET = sizeof(doiphdr) + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; + static constexpr size_t FIXED_LEN = + sizeof(_sourceAddress) + sizeof(_activationType) + DoIpConstants::DOIP_RESERVED_ISO_LEN; + static constexpr size_t RESERVED_OEM_OFFSET = DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DoIpConstants::DOIP_RESERVED_OEM_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -874,16 +880,16 @@ namespace pcpp void setResponseCode(DoIpRoutingResponseCodes code); /// @brief Gets the reserved ISO bytes. - std::array getReservedIso() const; + std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. - void setReservedIso(const std::array& reservedIso); + void setReservedIso(const std::array& reservedIso); /// @brief Gets the reserved OEM bytes if present. - const std::array* getReservedOem() const; + const std::array* getReservedOem() const; /// @brief Sets the reserved OEM bytes. - void setReservedOem(const std::array& reservedOem); + void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. bool hasReservedOem() const; @@ -901,17 +907,17 @@ namespace pcpp } private: - uint16_t _logicalAddressExternalTester; ///< Logical address of the external tester. - uint16_t _sourceAddress; ///< ECU source address. - DoIpRoutingResponseCodes _responseCode; ///< Routing response code. - std::array _reservedIso; ///< ISO reserved bytes. - std::array _reservedOem; ///< OEM reserved bytes. - bool _hasReservedOem; ///< Whether OEM bytes are set. + uint16_t _logicalAddressExternalTester; ///< Logical address of the external tester. + uint16_t _sourceAddress; ///< ECU source address. + DoIpRoutingResponseCodes _responseCode; ///< Routing response code. + std::array _reservedIso; ///< ISO reserved bytes. + std::array _reservedOem; ///< OEM reserved bytes. + bool _hasReservedOem; ///< Whether OEM bytes are set. static constexpr size_t FIXED_LEN = sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress) + - sizeof(_responseCode) + DOIP_RESERVED_ISO_LEN; + sizeof(_responseCode) + DoIpConstants::DOIP_RESERVED_ISO_LEN; static constexpr size_t RESERVED_OEM_OFFSET = sizeof(doiphdr) + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DoIpConstants::DOIP_RESERVED_OEM_LEN; }; //~~~~~~~~~~~~~~~~~~~| @@ -975,13 +981,13 @@ namespace pcpp /// @brief Constructs the message using the specified EID. /// @param[in] eid A 6-byte Entity ID used for vehicle identification. - explicit VehicleIdentificationRequestEID(const std::array& eid); + explicit VehicleIdentificationRequestEID(const std::array& eid); /// @brief Gets the Entity ID (EID). - std::array getEID() const; + std::array getEID() const; /// @brief Sets the Entity ID (EID). - void setEID(const std::array& eid); + void setEID(const std::array& eid); /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -993,7 +999,7 @@ namespace pcpp } private: - std::array _eid; ///< The 6-byte Entity ID used for identification. + std::array _eid; ///< The 6-byte Entity ID used for identification. }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1016,13 +1022,13 @@ namespace pcpp /// @brief Constructs the message using the specified VIN. /// @param[in] vin A 17-byte Vehicle Identification Number. - explicit VehicleIdentificationRequestVIN(const std::array& vin); + explicit VehicleIdentificationRequestVIN(const std::array& vin); /// @brief Gets the Vehicle Identification Number (VIN). - std::array getVIN() const; + std::array getVIN() const; /// @brief Sets the Vehicle Identification Number (VIN). - void setVIN(const std::array& vin); + void setVIN(const std::array& vin); /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -1034,7 +1040,7 @@ namespace pcpp } private: - std::array _vin; ///< The 17-byte Vehicle Identification Number. + std::array _vin; ///< The 17-byte Vehicle Identification Number. }; //~~~~~~~~~~~~~~~~~~~~~| @@ -1062,21 +1068,21 @@ namespace pcpp /// @param[in] eid Entity Identifier (EID). /// @param[in] gid Group Identifier (GID). /// @param[in] actionCode Further action code. - VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, - const std::array& eid, const std::array& gid, - DoIpActionCodes actionCode); + VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, DoIpActionCodes actionCode); /// @brief Gets the Vehicle Identification Number (VIN). - std::array getVIN() const; + std::array getVIN() const; /// @brief Gets the logical address of the vehicle. uint16_t getLogicalAddress() const; /// @brief Gets the Entity Identifier (EID). - std::array getEID() const; + std::array getEID() const; /// @brief Gets the Group Identifier (GID). - std::array getGID() const; + std::array getGID() const; /// @brief Gets the further action required code. DoIpActionCodes getFurtherActionRequired() const; @@ -1085,16 +1091,16 @@ namespace pcpp const DoIpSyncStatus* getSyncStatus() const; /// @brief Sets the Vehicle Identification Number (VIN). - void setVIN(const std::array& vin); + void setVIN(const std::array& vin); /// @brief Sets the logical address. void setLogicalAddress(uint16_t address); /// @brief Sets the Entity Identifier (EID). - void setEID(const std::array& eid); + void setEID(const std::array& eid); /// @brief Sets the Group Identifier (GID). - void setGID(const std::array& gid); + void setGID(const std::array& gid); /// @brief Sets the further action required code. void setFurtherActionRequired(DoIpActionCodes action); @@ -1118,16 +1124,17 @@ namespace pcpp } private: - std::array _vin; ///< Vehicle Identification Number. - uint16_t _logicalAddress; ///< Logical address of the vehicle. - std::array _eid; ///< Entity Identifier. - std::array _gid; ///< Group Identifier. - DoIpActionCodes _actionCode; ///< Further action required code. - DoIpSyncStatus _syncStatus; ///< Optional synchronization status. - bool _hasSyncStatus; ///< Indicates if sync status is set. - - static constexpr size_t FIXED_LEN = - DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN + sizeof(_actionCode); + std::array _vin; ///< Vehicle Identification Number. + uint16_t _logicalAddress; ///< Logical address of the vehicle. + std::array _eid; ///< Entity Identifier. + std::array _gid; ///< Group Identifier. + DoIpActionCodes _actionCode; ///< Further action required code. + DoIpSyncStatus _syncStatus; ///< Optional synchronization status. + bool _hasSyncStatus; ///< Indicates if sync status is set. + + static constexpr size_t FIXED_LEN = DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress) + + DoIpConstants::DOIP_EID_LEN + DoIpConstants::DoIpConstants::DOIP_GID_LEN + + sizeof(_actionCode); static constexpr size_t SYNC_STATUS_OFFSET = sizeof(doiphdr) + FIXED_LEN; static constexpr size_t OPT_LEN = FIXED_LEN + sizeof(_syncStatus); }; diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 9453a9e489..773110b820 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -203,7 +203,7 @@ namespace pcpp DoIpLayer::DoIpLayer() { - m_DataLen = sizeof(doiphdr); + m_DataLen = DoIpConstants::DOIP_HEADER_LEN; m_Protocol = DOIP; m_Data = new uint8_t[m_DataLen]{}; } @@ -299,7 +299,7 @@ namespace pcpp return htobe32(getDoIpHeader()->payloadLength); } - void DoIpLayer::setPayloadLength(uint32_t payloadLength) const + void DoIpLayer::setPayloadLength(const uint32_t payloadLength) { getDoIpHeader()->payloadLength = be32toh(payloadLength); } @@ -327,13 +327,11 @@ namespace pcpp { if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) { - constexpr size_t headerLen = sizeof(doiphdr); - - if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/) + if (m_DataLen <= DoIpConstants::DOIP_HEADER_LEN + 2 /*source address size*/ + 2 /*target address size*/) return; - uint8_t* payload = m_Data + (headerLen + 2 + 2); - size_t payloadLen = m_DataLen - (headerLen + 2 + 2); + uint8_t* payload = m_Data + (DoIpConstants::DOIP_HEADER_LEN + 2 + 2); + size_t payloadLen = m_DataLen - (DoIpConstants::DOIP_HEADER_LEN + 2 + 2); m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } } @@ -344,18 +342,18 @@ namespace pcpp RoutingActivationRequest::RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t headerLength = sizeof(doiphdr); - - if (dataLen < (headerLength + FIXED_LEN) || dataLen > (headerLength + OPT_LEN)) + if (dataLen < (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) || + dataLen > (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) { throw std::runtime_error("RoutingActivationRequest: Invalid payload length"); } - if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + if (dataLen > (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) && + dataLen < (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) { throw std::runtime_error("RoutingActivationRequest: Invalid OEM field length"); } - uint8_t* dataPtr = getDataPtr(headerLength); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); dataPtr += sizeof(_sourceAddress); @@ -363,12 +361,12 @@ namespace pcpp _activationType = static_cast(*dataPtr); dataPtr += sizeof(_activationType); - memcpy(dataPtr, &_reservedIso, DOIP_RESERVED_ISO_LEN); - dataPtr += DOIP_RESERVED_ISO_LEN; + memcpy(dataPtr, &_reservedIso, DoIpConstants::DOIP_RESERVED_ISO_LEN); + dataPtr += DoIpConstants::DOIP_RESERVED_ISO_LEN; - if (dataLen - (RESERVED_OEM_OFFSET) == DOIP_RESERVED_OEM_LEN) + if (dataLen - (RESERVED_OEM_OFFSET) == DoIpConstants::DOIP_RESERVED_OEM_LEN) { - memcpy(dataPtr, &_reservedOem, DOIP_RESERVED_OEM_LEN); + memcpy(dataPtr, &_reservedOem, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } else @@ -382,7 +380,7 @@ namespace pcpp : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setSourceAddress(sourrceAddress); setActivationType(activationType); @@ -396,7 +394,7 @@ namespace pcpp void RoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) { - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)); memcpy(dataPtr, &activationType, sizeof(activationType)); _activationType = activationType; } @@ -409,20 +407,22 @@ namespace pcpp void RoutingActivationRequest::setSourceAddress(uint16_t sourceAddress) { _sourceAddress = htobe16(sourceAddress); - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); } - std::array RoutingActivationRequest::getReservedIso() const + std::array RoutingActivationRequest::getReservedIso() const { return _reservedIso; } - void RoutingActivationRequest::setReservedIso(const std::array& reservedIso) + void RoutingActivationRequest::setReservedIso( + const std::array& reservedIso) { _reservedIso = reservedIso; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_activationType)); - memcpy(dataPtr, &_reservedIso, DOIP_RESERVED_ISO_LEN); + uint8_t* dataPtr = + getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_activationType)); + memcpy(dataPtr, &_reservedIso, DoIpConstants::DOIP_RESERVED_ISO_LEN); } bool RoutingActivationRequest::hasReservedOem() const @@ -430,17 +430,18 @@ namespace pcpp return _hasReservedOem; } - const std::array* RoutingActivationRequest::getReservedOem() const + const std::array* RoutingActivationRequest::getReservedOem() const { return _hasReservedOem ? &_reservedOem : nullptr; } - void RoutingActivationRequest::setReservedOem(const std::array& reservedOem) + void RoutingActivationRequest::setReservedOem( + const std::array& reservedOem) { _reservedOem = reservedOem; if (!_hasReservedOem) { - extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + extendLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN); memcpy(getDataPtr(RESERVED_OEM_OFFSET), &reservedOem, sizeof(_reservedOem)); @@ -449,9 +450,9 @@ namespace pcpp void RoutingActivationRequest::clearReserveOem() { - if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) { - shortenLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + shortenLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); } @@ -473,11 +474,12 @@ namespace pcpp { oss << "Activation type: Unknown" << std::hex << " (0x" << unsigned(_activationType) << ")\n"; } - oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(_reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; + oss << "Reserved by ISO: " + << pcpp::byteArrayToHexString(_reservedIso.data(), DoIpConstants::DOIP_RESERVED_ISO_LEN) << "\n"; if (_hasReservedOem) { - oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(_reservedOem.data(), DOIP_RESERVED_OEM_LEN) - << '\n'; + oss << "Reserved by OEM: " + << pcpp::byteArrayToHexString(_reservedOem.data(), DoIpConstants::DOIP_RESERVED_OEM_LEN) << '\n'; } return oss.str(); } @@ -489,18 +491,18 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t headerLength = sizeof(doiphdr); - if (dataLen < headerLength + FIXED_LEN || dataLen > headerLength + OPT_LEN) + if (dataLen < DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN || dataLen > DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) { throw std::runtime_error("RoutingActivationResponse: Invalid payload length!"); } - if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + if (dataLen > (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) && + dataLen < (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) { throw std::runtime_error("RoutingActivationRequest: invalid OEM field length"); } - const uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + const uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); memcpy(&_logicalAddressExternalTester, dataPtr, sizeof(_logicalAddressExternalTester)); dataPtr += sizeof(_logicalAddressExternalTester); @@ -509,12 +511,12 @@ namespace pcpp dataPtr += sizeof(_sourceAddress); _responseCode = static_cast(*dataPtr++); - memcpy(&_reservedIso, dataPtr, DOIP_RESERVED_ISO_LEN); - dataPtr += DOIP_RESERVED_ISO_LEN; + memcpy(&_reservedIso, dataPtr, DoIpConstants::DOIP_RESERVED_ISO_LEN); + dataPtr += DoIpConstants::DOIP_RESERVED_ISO_LEN; - if (dataLen - (RESERVED_OEM_OFFSET) == DOIP_RESERVED_OEM_LEN) + if (dataLen - (RESERVED_OEM_OFFSET) == DoIpConstants::DOIP_RESERVED_OEM_LEN) { - memcpy(&_reservedOem, dataPtr, DOIP_RESERVED_OEM_LEN); + memcpy(&_reservedOem, dataPtr, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } else @@ -528,7 +530,7 @@ namespace pcpp : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setLogicalAddressExternalTester(logicalAddressExternalTester); setSourceAddress(sourceAddress); @@ -543,7 +545,7 @@ namespace pcpp void RoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) { _logicalAddressExternalTester = htobe16(addr); - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); memcpy(dataPtr, &_logicalAddressExternalTester, sizeof(_logicalAddressExternalTester)); } @@ -554,7 +556,7 @@ namespace pcpp void RoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) { _sourceAddress = htobe16(sourceAddress); - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_logicalAddressExternalTester)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_logicalAddressExternalTester)); memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); } @@ -566,18 +568,20 @@ namespace pcpp void RoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) { _responseCode = code; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress)); + uint8_t* dataPtr = + getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress)); *dataPtr = static_cast(code); } - std::array RoutingActivationResponse::getReservedIso() const + std::array RoutingActivationResponse::getReservedIso() const { return _reservedIso; } - void RoutingActivationResponse::setReservedIso(const std::array& reservedIso) + void RoutingActivationResponse::setReservedIso( + const std::array& reservedIso) { _reservedIso = reservedIso; - uint8_t* dataPtr = getDataPtr(RESERVED_OEM_OFFSET - DOIP_RESERVED_ISO_LEN); + uint8_t* dataPtr = getDataPtr(RESERVED_OEM_OFFSET - DoIpConstants::DOIP_RESERVED_ISO_LEN); memcpy(dataPtr, &_reservedIso, sizeof(reservedIso)); } @@ -586,17 +590,18 @@ namespace pcpp return _hasReservedOem; } - const std::array* RoutingActivationResponse::getReservedOem() const + const std::array* RoutingActivationResponse::getReservedOem() const { return _hasReservedOem ? &_reservedOem : nullptr; } - void RoutingActivationResponse::setReservedOem(const std::array& reservedOem) + void RoutingActivationResponse::setReservedOem( + const std::array& reservedOem) { _reservedOem = reservedOem; if (!_hasReservedOem) { - extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + extendLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN); memcpy(getDataPtr(RESERVED_OEM_OFFSET), &_reservedOem, sizeof(_reservedOem)); @@ -605,9 +610,9 @@ namespace pcpp void RoutingActivationResponse::clearReservedOem() { - if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) { - shortenLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + shortenLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); } @@ -628,9 +633,11 @@ namespace pcpp else ss << "Response Code: Unknown (0x" << std::hex << unsigned(_responseCode) << ")\n"; - ss << "Reserved by ISO: " << pcpp::byteArrayToHexString(_reservedIso.data(), DOIP_RESERVED_ISO_LEN) << "\n"; + ss << "Reserved by ISO: " + << pcpp::byteArrayToHexString(_reservedIso.data(), DoIpConstants::DOIP_RESERVED_ISO_LEN) << "\n"; if (_hasReservedOem) - ss << "Reserved by OEM: " << pcpp::byteArrayToHexString(_reservedOem.data(), DOIP_RESERVED_OEM_LEN) << "\n"; + ss << "Reserved by OEM: " + << pcpp::byteArrayToHexString(_reservedOem.data(), DoIpConstants::DOIP_RESERVED_OEM_LEN) << "\n"; return ss.str(); } @@ -641,16 +648,16 @@ namespace pcpp GenericHeaderNack::GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != (sizeof(doiphdr) + sizeof(_nackCode))) + if (dataLen != (DoIpConstants::DOIP_HEADER_LEN + sizeof(_nackCode))) throw std::runtime_error("GenericHeaderNack: Invalid payload length!"); - _nackCode = static_cast(data[sizeof(doiphdr)]); + _nackCode = static_cast(data[DoIpConstants::DOIP_HEADER_LEN]); } GenericHeaderNack::GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), sizeof(_nackCode)); - extendLayer(sizeof(doiphdr), sizeof(_nackCode)); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, sizeof(_nackCode)); setNackCode(nackCode); } @@ -662,7 +669,7 @@ namespace pcpp void GenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) { _nackCode = nackCode; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); *dataPtr = static_cast(nackCode); } @@ -689,36 +696,37 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != sizeof(doiphdr) + DOIP_EID_LEN) + if (dataLen != DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_EID_LEN) throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); - memcpy(&_eid, data + sizeof(doiphdr), DOIP_EID_LEN); + memcpy(&_eid, data + DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_EID_LEN); } - VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid) + VehicleIdentificationRequestEID::VehicleIdentificationRequestEID( + const std::array& eid) : _eid(eid) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); - extendLayer(sizeof(doiphdr), DOIP_EID_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DoIpConstants::DOIP_EID_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_EID_LEN); setEID(eid); } - std::array VehicleIdentificationRequestEID::getEID() const + std::array VehicleIdentificationRequestEID::getEID() const { return _eid; } - void VehicleIdentificationRequestEID::setEID(const std::array& eid) + void VehicleIdentificationRequestEID::setEID(const std::array& eid) { _eid = eid; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); - memcpy(dataPtr, &_eid, DOIP_EID_LEN); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); + memcpy(dataPtr, &_eid, DoIpConstants::DOIP_EID_LEN); } std::string VehicleIdentificationRequestEID::getSummary() const { std::ostringstream oss; - oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DOIP_EID_LEN) << "\n"; + oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DoIpConstants::DOIP_EID_LEN) << "\n"; return oss.str(); } @@ -729,29 +737,30 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != sizeof(doiphdr) + DOIP_VIN_LEN) + if (dataLen != DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN) throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length"); - memcpy(&_vin, data + sizeof(doiphdr), DOIP_VIN_LEN); + memcpy(&_vin, data + DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_VIN_LEN); } - VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin) + VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN( + const std::array& vin) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); - extendLayer(sizeof(doiphdr), DOIP_VIN_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DoIpConstants::DOIP_VIN_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_VIN_LEN); setVIN(vin); } - std::array VehicleIdentificationRequestVIN::getVIN() const + std::array VehicleIdentificationRequestVIN::getVIN() const { return _vin; } - void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) + void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) { _vin = vin; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); - memcpy(dataPtr, &_vin, DOIP_VIN_LEN); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); + memcpy(dataPtr, &_vin, DoIpConstants::DOIP_VIN_LEN); } std::string VehicleIdentificationRequestVIN::getSummary() const @@ -767,24 +776,24 @@ namespace pcpp VehicleAnnouncement::VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - uint8_t* dataPtr = data + sizeof(doiphdr); + uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; - if (dataLen < SYNC_STATUS_OFFSET || dataLen > sizeof(doiphdr) + OPT_LEN) + if (dataLen < SYNC_STATUS_OFFSET || dataLen > DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) { throw std::runtime_error("VehicleAnnouncement: invalid payload length!"); } - memcpy(&_vin, dataPtr, DOIP_VIN_LEN); - dataPtr += DOIP_VIN_LEN; + memcpy(&_vin, dataPtr, DoIpConstants::DOIP_VIN_LEN); + dataPtr += DoIpConstants::DOIP_VIN_LEN; memcpy(&_logicalAddress, dataPtr, sizeof(_logicalAddress)); dataPtr += sizeof(_logicalAddress); - memcpy(&_eid, dataPtr, DOIP_EID_LEN); - dataPtr += DOIP_EID_LEN; + memcpy(&_eid, dataPtr, DoIpConstants::DOIP_EID_LEN); + dataPtr += DoIpConstants::DOIP_EID_LEN; - memcpy(&_gid, dataPtr, DOIP_GID_LEN); - dataPtr += DOIP_GID_LEN; + memcpy(&_gid, dataPtr, DoIpConstants::DOIP_GID_LEN); + dataPtr += DoIpConstants::DOIP_GID_LEN; _actionCode = static_cast(*(dataPtr++)); @@ -800,15 +809,17 @@ namespace pcpp } } - VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, - const std::array& eid, - const std::array& gid, DoIpActionCodes actionCode) + VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, + uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, + DoIpActionCodes actionCode) : _vin(vin), _logicalAddress(logicalAddress), _eid(eid), _gid(gid), _actionCode(actionCode), _hasSyncStatus(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setVIN(vin); setLogicalAddress(logicalAddress); @@ -816,7 +827,7 @@ namespace pcpp setGID(gid); setFurtherActionRequired(actionCode); } - std::array VehicleAnnouncement::getVIN() const + std::array VehicleAnnouncement::getVIN() const { return _vin; } @@ -825,11 +836,11 @@ namespace pcpp return htobe16(_logicalAddress); } - std::array VehicleAnnouncement::getEID() const + std::array VehicleAnnouncement::getEID() const { return _eid; } - std::array VehicleAnnouncement::getGID() const + std::array VehicleAnnouncement::getGID() const { return _gid; } @@ -844,7 +855,7 @@ namespace pcpp void VehicleAnnouncement::clearSyncStatus() { - if (getDataLen() == sizeof(doiphdr) + OPT_LEN) + if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) { shortenLayer(FIXED_LEN, sizeof(_syncStatus)); _hasSyncStatus = false; @@ -855,38 +866,41 @@ namespace pcpp PCPP_LOG_DEBUG("doip packet has no syncStatus!"); } } - void VehicleAnnouncement::setVIN(const std::array& vin) + void VehicleAnnouncement::setVIN(const std::array& vin) { _vin = vin; - memcpy(getDataPtr(sizeof(doiphdr)), &_vin, DOIP_VIN_LEN); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_vin, DoIpConstants::DOIP_VIN_LEN); } void VehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) { _logicalAddress = htobe16(logicalAddress); - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN); memcpy(dataPtr, &_logicalAddress, sizeof(_logicalAddress)); } - void VehicleAnnouncement::setEID(const std::array& eid) + void VehicleAnnouncement::setEID(const std::array& eid) { _eid = eid; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress)); - memcpy(dataPtr, &_eid, DOIP_EID_LEN); + uint8_t* dataPtr = + getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress)); + memcpy(dataPtr, &_eid, DoIpConstants::DOIP_EID_LEN); } - void VehicleAnnouncement::setGID(const std::array& gid) + void VehicleAnnouncement::setGID(const std::array& gid) { _gid = gid; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN); - memcpy(dataPtr, &_gid, DOIP_GID_LEN); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + + sizeof(_logicalAddress) + DoIpConstants::DOIP_EID_LEN); + memcpy(dataPtr, &_gid, DoIpConstants::DOIP_GID_LEN); } void VehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) { _actionCode = action; uint8_t* dataPtr = - getDataPtr(sizeof(doiphdr) + DOIP_VIN_LEN + sizeof(_logicalAddress) + DOIP_EID_LEN + DOIP_GID_LEN); + getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress) + + DoIpConstants::DOIP_EID_LEN + DoIpConstants::DOIP_GID_LEN); *dataPtr = static_cast(action); } @@ -913,8 +927,8 @@ namespace pcpp oss << "VIN: " << std::string(reinterpret_cast(_vin.data()), _vin.size()) << "\n"; oss << "Logical address: " << std::hex << "0x" << htobe16(_logicalAddress) << "\n"; - oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DOIP_EID_LEN) << "\n"; - oss << "GID: " << pcpp::byteArrayToHexString(_gid.data(), DOIP_GID_LEN) << "\n"; + oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DoIpConstants::DOIP_EID_LEN) << "\n"; + oss << "GID: " << pcpp::byteArrayToHexString(_gid.data(), DoIpConstants::DOIP_GID_LEN) << "\n"; auto it = DoIpEnumToStringActionCodes.find(_actionCode); if (it != DoIpEnumToStringActionCodes.end()) { @@ -947,10 +961,10 @@ namespace pcpp AliveCheckResponse::AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < sizeof(doiphdr) + sizeof(_sourceAddress)) + if (dataLen < DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)) throw std::runtime_error("AliveCheckResponse: insufficient payload length"); - const uint8_t* dataPtr = data + sizeof(doiphdr); + const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); } @@ -958,7 +972,7 @@ namespace pcpp { const size_t payloadLen = sizeof(_sourceAddress); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(sizeof(doiphdr), payloadLen); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); setSourceAddress(sourceAddress); } @@ -970,7 +984,7 @@ namespace pcpp void AliveCheckResponse::setSourceAddress(uint16_t address) { _sourceAddress = htobe16(address); - memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); } std::string AliveCheckResponse::getSummary() const @@ -987,11 +1001,11 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t payloadLen = sizeof(doiphdr) + sizeof(_powerModeCode); + constexpr size_t payloadLen = DoIpConstants::DOIP_HEADER_LEN + sizeof(_powerModeCode); if (dataLen != payloadLen) throw std::runtime_error("DiagnosticPowerModeResponse: invalid payload length!"); - const uint8_t* payloadPtr = data + sizeof(doiphdr); + const uint8_t* payloadPtr = data + DoIpConstants::DOIP_HEADER_LEN; _powerModeCode = static_cast(*payloadPtr); } @@ -999,7 +1013,7 @@ namespace pcpp { const size_t payloadLen = sizeof(_powerModeCode); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(sizeof(doiphdr), payloadLen); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); setPowerModeCode(code); } @@ -1011,7 +1025,7 @@ namespace pcpp void DiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) { _powerModeCode = code; - uint8_t* dataPtr = getDataPtr(sizeof(doiphdr)); + uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); *dataPtr = static_cast(code); } @@ -1036,7 +1050,7 @@ namespace pcpp EntityStatusResponse::EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t headerLength = sizeof(doiphdr); + constexpr size_t headerLength = DoIpConstants::DOIP_HEADER_LEN; if (dataLen < headerLength + FIXED_LEN || dataLen > headerLength + OPT_LEN) { throw std::runtime_error("EntityStatusResponse: Invalid payload length!"); @@ -1047,7 +1061,7 @@ namespace pcpp throw std::runtime_error("EntityStatusResponse: Invalid MaxDataSize field length!"); } - const uint8_t* dataPtr = data + sizeof(doiphdr); + const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; _nodeType = static_cast(*dataPtr); dataPtr += sizeof(_nodeType); @@ -1073,7 +1087,7 @@ namespace pcpp uint8_t currentlyOpenSockets) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setNodeType(nodeType); setMaxConcurrentSockets(maxConcurrentSockets); @@ -1098,7 +1112,7 @@ namespace pcpp void EntityStatusResponse::setNodeType(DoIpEntityStatus nodeType) { _nodeType = nodeType; - getDataPtr(sizeof(doiphdr))[0] = static_cast(nodeType); + getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[0] = static_cast(nodeType); } bool EntityStatusResponse::hasMaxDataSize() const { @@ -1106,7 +1120,7 @@ namespace pcpp } void EntityStatusResponse::clearMaxDataSize() { - if (getDataLen() == sizeof(doiphdr) + OPT_LEN && _hasMaxDataSize) + if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN && _hasMaxDataSize) { shortenLayer(FIXED_LEN, sizeof(_maxDataSize)); _hasMaxDataSize = false; @@ -1120,13 +1134,13 @@ namespace pcpp void EntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) { _maxConcurrentSockets = sockets; - getDataPtr(sizeof(doiphdr))[1] = sockets; + getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[1] = sockets; } void EntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) { _currentlyOpenSockets = sockets; - getDataPtr(sizeof(doiphdr))[2] = sockets; + getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[2] = sockets; } void EntityStatusResponse::setMaxDataSize(const std::array& data) @@ -1169,18 +1183,18 @@ namespace pcpp DiagnosticMessage::DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < - sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress) + 1 /*Minimum diag payload len*/) + if (dataLen < DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress) + + 1 /*Minimum diag payload len*/) throw std::runtime_error("DiagnosticMessage: insufficient payload"); - const uint8_t* dataPtr = data + sizeof(doiphdr); + const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); dataPtr += (sizeof(_sourceAddress)); memcpy(&_targetAddress, dataPtr, sizeof(_targetAddress)); dataPtr += (sizeof(_targetAddress)); - _diagnosticData.assign( - dataPtr, dataPtr + (dataLen - (sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)))); + _diagnosticData.assign(dataPtr, dataPtr + (dataLen - (DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + + sizeof(_targetAddress)))); } DiagnosticMessage::DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, @@ -1188,7 +1202,7 @@ namespace pcpp { size_t payloadLen = sizeof(_sourceAddress) + sizeof(_targetAddress) + _diagnosticData.size(); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(sizeof(doiphdr), payloadLen); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); setDiagnosticData(diagData); @@ -1210,18 +1224,19 @@ namespace pcpp void DiagnosticMessage::setSourceAddress(uint16_t address) { _sourceAddress = htobe16(address); - memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); } void DiagnosticMessage::setTargetAddress(uint16_t targetAddress) { _targetAddress = htobe16(targetAddress); - memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, + sizeof(_targetAddress)); } void DiagnosticMessage::setDiagnosticData(const std::vector& data) { - constexpr size_t fixedLen = sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress); + constexpr size_t fixedLen = DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress); const size_t newPayloadlLength = sizeof(_sourceAddress) + sizeof(_targetAddress) + data.size(); uint8_t* dataPtr = getDataPtr(fixedLen); setPayloadLength(newPayloadlLength); @@ -1252,7 +1267,7 @@ namespace pcpp if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); - const uint8_t* ptr = data + sizeof(doiphdr); + const uint8_t* ptr = data + DoIpConstants::DOIP_HEADER_LEN; memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); ptr += sizeof(_sourceAddress); @@ -1279,7 +1294,7 @@ namespace pcpp : _hasPreviousMessage(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); @@ -1308,19 +1323,20 @@ namespace pcpp { _sourceAddress = htobe16(address); // Write sourceAddress into payload at offset 0 (immediately after doiphdr) - memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); } void DiagnosticAckMessage::setTargetAddress(uint16_t address) { _targetAddress = htobe16(address); - memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, + sizeof(_targetAddress)); } void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) { _ackCode = code; - uint8_t* ptr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)); + uint8_t* ptr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress)); *ptr = static_cast(code); } @@ -1391,7 +1407,7 @@ namespace pcpp if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticNackMessage: Invalid payload length"); - const uint8_t* ptr = data + sizeof(doiphdr); + const uint8_t* ptr = data + DoIpConstants::DOIP_HEADER_LEN; memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); ptr += sizeof(_sourceAddress); @@ -1418,7 +1434,7 @@ namespace pcpp : _hasPreviousMessage(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(sizeof(doiphdr), FIXED_LEN); + extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); @@ -1449,19 +1465,20 @@ namespace pcpp void DiagnosticNackMessage::setSourceAddress(uint16_t address) { _sourceAddress = htobe16(address); - memcpy(getDataPtr(sizeof(doiphdr)), &_sourceAddress, sizeof(_sourceAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); } void DiagnosticNackMessage::setTargetAddress(uint16_t address) { _targetAddress = htobe16(address); - memcpy(getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress)), &_targetAddress, sizeof(_targetAddress)); + memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, + sizeof(_targetAddress)); } void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) { _nackCode = code; - uint8_t* ptr = getDataPtr(sizeof(doiphdr) + sizeof(_sourceAddress) + sizeof(_targetAddress)); + uint8_t* ptr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress)); *ptr = static_cast(code); } From bb0078667632bc3e8b46096ac6812a0ffcad8655 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 20 Apr 2025 15:57:44 -0400 Subject: [PATCH 31/43] fix doxygene and bool data initialisation --- Packet++/header/DoIpLayer.h | 2 +- Packet++/src/DoIpLayer.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 0614a16f13..75f90e3820 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -543,7 +543,7 @@ namespace pcpp void setProtocolVersion(DoIpProtocolVersion version); /// Additional setter for raw protocol version (for testing/fuzzing/debugging) - /// @param[in] version the raw version of DOIP protocol to set + /// @param[in] Rawversion the raw version of DOIP protocol to set void setProtocolVersion(uint8_t Rawversion); /// Get the invert version of DOIP protocol diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 773110b820..1fad920d7a 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -361,7 +361,7 @@ namespace pcpp _activationType = static_cast(*dataPtr); dataPtr += sizeof(_activationType); - memcpy(dataPtr, &_reservedIso, DoIpConstants::DOIP_RESERVED_ISO_LEN); + memcpy(&_reservedIso, dataPtr, DoIpConstants::DOIP_RESERVED_ISO_LEN); dataPtr += DoIpConstants::DOIP_RESERVED_ISO_LEN; if (dataLen - (RESERVED_OEM_OFFSET) == DoIpConstants::DOIP_RESERVED_OEM_LEN) @@ -1085,6 +1085,7 @@ namespace pcpp EntityStatusResponse::EntityStatusResponse(DoIpEntityStatus nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) + : _hasMaxDataSize(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); From 66002a89ec9e7dc95bc9e0d683fe26a215a6ab85 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 24 Apr 2025 02:31:02 -0400 Subject: [PATCH 32/43] serval improvements --- Packet++/header/DoIpLayer.h | 448 +++++++++----- Packet++/src/DoIpLayer.cpp | 804 ++++++++++--------------- Tests/Packet++Test/Tests/DoIpTests.cpp | 62 +- 3 files changed, 644 insertions(+), 670 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 75f90e3820..157fb9089a 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -13,9 +13,11 @@ /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /// @brief Represent doip constants fields length - struct DoIpConstants + namespace DoIpConstants { + // @brief Length of doip header + static constexpr size_t DOIP_HEADER_LEN = 8; + /// @brief Length of the Equiepement Identifier (EID) field. static constexpr size_t DOIP_EID_LEN = 6; @@ -31,9 +33,12 @@ namespace pcpp /// @brief Length of the Reserved OEM field. static constexpr size_t DOIP_RESERVED_OEM_LEN = 4; - /// @brief fixed size of valid doip header - static constexpr size_t DOIP_HEADER_LEN = 8; - }; + /// @brief Length of the source address + static constexpr size_t DOIP_SOURCE_ADDRESS_LEN = 2; + + /// @brief Length of the target address + static constexpr size_t DOIP_TARGET_ADDRESS_LEN = 2; + } // namespace DoIpConstants /// @brief Enum representing DoIP routing activation types. /// These values specify the type of routing activation used in DoIP(Diagnostic over IP). @@ -41,7 +46,7 @@ namespace pcpp { /// Default routing activation type. /// Used when no specific type is required. - Default = 0x00U, + DEFAULT = 0x00U, /// WWH-OBD (Worldwide Harmonized On-Board Diagnostics) routing activation type. /// Used for vehicle diagnostics in compliance with WWH-OBD standards. @@ -302,7 +307,7 @@ namespace pcpp /// @brief Enum representing DoIP entity status response codes (ISO 13400). /// These codes are used to indicate the role or type of a DoIP entity in the network. - enum class DoIpEntityStatus : uint8_t + enum class DoIpEntityStatusResponse : uint8_t { /// Gateway. /// The entity functions as a gateway, @@ -518,6 +523,8 @@ namespace pcpp #pragma pack(pop) static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes."); + using namespace DoIpConstants; + /// @class DoIpLayer /// Represents an DoIP protocol layer. Currently only IPv4 DoIP messages are supported class DoIpLayer : public Layer @@ -742,13 +749,13 @@ namespace pcpp inline bool DoIpLayer::isPayloadLengthValid(uint32_t payloadLength, size_t dataLen) { - if (dataLen < DoIpConstants::DOIP_HEADER_LEN) + if (dataLen < DOIP_HEADER_LEN) { PCPP_LOG_ERROR("[Malformed doip packet]: Data length is smaller than DOIP header size!"); return false; } - const size_t actualPayloadLen = dataLen - DoIpConstants::DOIP_HEADER_LEN; + const size_t actualPayloadLen = dataLen - DOIP_HEADER_LEN; if (payloadLength != actualPayloadLen) { PCPP_LOG_ERROR("[Malformed doip packet]: Payload length mismatch: expected " @@ -783,6 +790,22 @@ namespace pcpp /// @param[in] activationType Type of routing activation. RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); +/// @struct Represents the Routing Activation Request data in DoIP. +/// Routing Activation Response message structure (extends DoIP header). +#pragma pack(push, 1) + struct routing_activation_request : doiphdr + { + /// @brief Source address of the tester. + uint16_t sourceAddress; + + /// @brief Routing activation type. + DoIpActivationTypes activationType; + + /// @brief ISO reserved bytes. + std::array reservedIso; + }; +#pragma pack(pop) + /// @brief Returns the source address. uint16_t getSourceAddress() const; @@ -796,22 +819,22 @@ namespace pcpp void setActivationType(DoIpActivationTypes activationType); /// @brief Gets the reserved ISO bytes. - std::array getReservedIso() const; + std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. - void setReservedIso(const std::array& reservedIso); + void setReservedIso(const std::array& reservedIso); - /// @brief Gets the reserved OEM bytes if present. - const std::array* getReservedOem() const; + /// @brief Gets pointer to reserved OEM bytes if present. + const uint8_t* getReservedOem() const; /// @brief Sets the reserved OEM bytes. - void setReservedOem(const std::array& reservedOem); + void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. bool hasReservedOem() const; /// @brief Clears the OEM reserved bytes. - void clearReserveOem(); + void clearReservedOem(); /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -822,17 +845,22 @@ namespace pcpp return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; } + /// Get a pointer to Routing activation request message + /// Notice this points directly to the data, so any change will modify + /// the actual packet data + /// @return A pointer to a routing_activation_request structure containing the data + routing_activation_request* getRoutingRequest() const + { + return reinterpret_cast(m_Data); + } + private: - uint16_t _sourceAddress; ///< Source address of the tester. - DoIpActivationTypes _activationType; ///< Routing activation type. - std::array _reservedIso; ///< ISO reserved bytes. - std::array _reservedOem; ///< OEM reserved bytes. - bool _hasReservedOem; ///< Whether OEM bytes are set. + bool _hasReservedOem; ///< Whether OEM bytes are set. + static constexpr size_t ACTIVATION_TYPE_LEN = 1; static constexpr size_t FIXED_LEN = - sizeof(_sourceAddress) + sizeof(_activationType) + DoIpConstants::DOIP_RESERVED_ISO_LEN; - static constexpr size_t RESERVED_OEM_OFFSET = DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + DoIpConstants::DOIP_RESERVED_OEM_LEN; + DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + ACTIVATION_TYPE_LEN + DOIP_RESERVED_ISO_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -861,6 +889,25 @@ namespace pcpp RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode); +/// @struct Represents the Routing Activation Response data in DoIP. +/// Routing Activation Response message structure (extends DoIP header). +#pragma pack(push, 1) + struct routing_activation_response : doiphdr + { + /// @brief External tester's logical address. + uint16_t logicalAddressExternalTester; + + /// @brief ECU source address. + uint16_t sourceAddress; + + /// @brief Response code. + DoIpRoutingResponseCodes responseCode; + + /// @brief ISO reserved bytes. + std::array reservedIso; + }; +#pragma pack(pop) + /// @brief Gets the logical address of the external tester. uint16_t getLogicalAddressExternalTester() const; @@ -880,16 +927,16 @@ namespace pcpp void setResponseCode(DoIpRoutingResponseCodes code); /// @brief Gets the reserved ISO bytes. - std::array getReservedIso() const; + std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. - void setReservedIso(const std::array& reservedIso); + void setReservedIso(const std::array& reservedIso); - /// @brief Gets the reserved OEM bytes if present. - const std::array* getReservedOem() const; + /// @brief Gets pointer to reserved OEM bytes if present. + const uint8_t* getReservedOem() const; /// @brief Sets the reserved OEM bytes. - void setReservedOem(const std::array& reservedOem); + void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. bool hasReservedOem() const; @@ -906,18 +953,23 @@ namespace pcpp return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE; } + /// Get a pointer to Routing activation response message + /// Notice this points directly to the data, so any change will modify + /// the actual packet data + /// @return A pointer to a routing_activation_response structure containing the data + routing_activation_response* getRoutingResponse() const + { + return reinterpret_cast(m_Data); + } + private: - uint16_t _logicalAddressExternalTester; ///< Logical address of the external tester. - uint16_t _sourceAddress; ///< ECU source address. - DoIpRoutingResponseCodes _responseCode; ///< Routing response code. - std::array _reservedIso; ///< ISO reserved bytes. - std::array _reservedOem; ///< OEM reserved bytes. - bool _hasReservedOem; ///< Whether OEM bytes are set. - - static constexpr size_t FIXED_LEN = sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress) + - sizeof(_responseCode) + DoIpConstants::DOIP_RESERVED_ISO_LEN; - static constexpr size_t RESERVED_OEM_OFFSET = sizeof(doiphdr) + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + DoIpConstants::DOIP_RESERVED_OEM_LEN; + bool _hasReservedOem; ///< Whether OEM bytes are set. + + static constexpr size_t LOGICAL_ADDRESS_LEN = 2; + static constexpr size_t RESPONSE_CODE_LEN = 1; + static constexpr size_t FIXED_LEN = + DOIP_HEADER_LEN + LOGICAL_ADDRESS_LEN + DOIP_SOURCE_ADDRESS_LEN + RESPONSE_CODE_LEN + DOIP_RESERVED_ISO_LEN; + static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; //~~~~~~~~~~~~~~~~~~~| @@ -948,6 +1000,9 @@ namespace pcpp /// @brief Sets the NACK code. void setNackCode(DoIpGenericHeaderNackCodes code); + /// @brief Sets the Raw NACK code for debugging/testing. + void setNackCode(uint8_t code); + /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -958,7 +1013,9 @@ namespace pcpp } private: - DoIpGenericHeaderNackCodes _nackCode; ///< The NACK code indicating the error type. + static constexpr size_t NACK_CODE_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t NACK_CODE_LEN = sizeof(uint8_t); + static constexpr size_t FIXED_LEN = NACK_CODE_OFFSET + NACK_CODE_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -981,13 +1038,13 @@ namespace pcpp /// @brief Constructs the message using the specified EID. /// @param[in] eid A 6-byte Entity ID used for vehicle identification. - explicit VehicleIdentificationRequestEID(const std::array& eid); + explicit VehicleIdentificationRequestEID(const std::array& eid); /// @brief Gets the Entity ID (EID). - std::array getEID() const; + std::array getEID() const; /// @brief Sets the Entity ID (EID). - void setEID(const std::array& eid); + void setEID(const std::array& eid); /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -999,7 +1056,8 @@ namespace pcpp } private: - std::array _eid; ///< The 6-byte Entity ID used for identification. + static constexpr size_t EID_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t FIXED_LEN = EID_OFFSET + DOIP_EID_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1022,13 +1080,13 @@ namespace pcpp /// @brief Constructs the message using the specified VIN. /// @param[in] vin A 17-byte Vehicle Identification Number. - explicit VehicleIdentificationRequestVIN(const std::array& vin); + explicit VehicleIdentificationRequestVIN(const std::array& vin); /// @brief Gets the Vehicle Identification Number (VIN). - std::array getVIN() const; + std::array getVIN() const; /// @brief Sets the Vehicle Identification Number (VIN). - void setVIN(const std::array& vin); + void setVIN(const std::array& vin); /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -1040,7 +1098,8 @@ namespace pcpp } private: - std::array _vin; ///< The 17-byte Vehicle Identification Number. + static constexpr size_t VIN_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t FIXED_LEN = VIN_OFFSET + DOIP_VIN_LEN; }; //~~~~~~~~~~~~~~~~~~~~~| @@ -1068,21 +1127,39 @@ namespace pcpp /// @param[in] eid Entity Identifier (EID). /// @param[in] gid Group Identifier (GID). /// @param[in] actionCode Further action code. - VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, - const std::array& eid, - const std::array& gid, DoIpActionCodes actionCode); + VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, const std::array& gid, + DoIpActionCodes actionCode); +#pragma pack(push, 1) + struct vehicle_announcement : doiphdr + { + /// @brief Vehicle Identification Number. + std::array vin; + /// @brief Logical address of the vehicle. + uint16_t logicalAddress; + + /// @brief Entity Identifier. + std::array eid; + + /// @brief Group Identifier. + std::array gid; + + /// @brief Further action required code. + DoIpActionCodes actionCode; + }; +#pragma pack(pop) /// @brief Gets the Vehicle Identification Number (VIN). - std::array getVIN() const; + std::array getVIN() const; /// @brief Gets the logical address of the vehicle. uint16_t getLogicalAddress() const; /// @brief Gets the Entity Identifier (EID). - std::array getEID() const; + std::array getEID() const; /// @brief Gets the Group Identifier (GID). - std::array getGID() const; + std::array getGID() const; /// @brief Gets the further action required code. DoIpActionCodes getFurtherActionRequired() const; @@ -1091,16 +1168,16 @@ namespace pcpp const DoIpSyncStatus* getSyncStatus() const; /// @brief Sets the Vehicle Identification Number (VIN). - void setVIN(const std::array& vin); + void setVIN(const std::array& vin); /// @brief Sets the logical address. void setLogicalAddress(uint16_t address); /// @brief Sets the Entity Identifier (EID). - void setEID(const std::array& eid); + void setEID(const std::array& eid); /// @brief Sets the Group Identifier (GID). - void setGID(const std::array& gid); + void setGID(const std::array& gid); /// @brief Sets the further action required code. void setFurtherActionRequired(DoIpActionCodes action); @@ -1123,20 +1200,28 @@ namespace pcpp return DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE; } + /// Get a pointer to Routing vehicle announcement data + /// Notice this points directly to the data, so any change will modify + /// the actual packet data + /// @return A pointer to a vehicle_announcement structure containing the data + vehicle_announcement* getVehicleAnnouncement() const + { + return reinterpret_cast(m_Data); + } + private: - std::array _vin; ///< Vehicle Identification Number. - uint16_t _logicalAddress; ///< Logical address of the vehicle. - std::array _eid; ///< Entity Identifier. - std::array _gid; ///< Group Identifier. - DoIpActionCodes _actionCode; ///< Further action required code. - DoIpSyncStatus _syncStatus; ///< Optional synchronization status. - bool _hasSyncStatus; ///< Indicates if sync status is set. - - static constexpr size_t FIXED_LEN = DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress) + - DoIpConstants::DOIP_EID_LEN + DoIpConstants::DoIpConstants::DOIP_GID_LEN + - sizeof(_actionCode); - static constexpr size_t SYNC_STATUS_OFFSET = sizeof(doiphdr) + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + sizeof(_syncStatus); + bool _hasSyncStatus; + + static constexpr size_t VIN_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t LOGICAL_ADDRESS_LEN = 2; + static constexpr size_t ACTION_CODE_LEN = 1; + static constexpr size_t FIXED_LEN = + VIN_OFFSET + DOIP_VIN_LEN + LOGICAL_ADDRESS_LEN + DOIP_EID_LEN + DOIP_GID_LEN + ACTION_CODE_LEN; + + static constexpr size_t SYNC_STATUS_OFFSET = FIXED_LEN; + static constexpr size_t SYNC_STATUS_LEN = 1; + + static constexpr size_t OPT_LEN = FIXED_LEN + SYNC_STATUS_LEN; }; //~~~~~~~~~~~~~~~~~~~~| @@ -1182,7 +1267,8 @@ namespace pcpp } private: - uint16_t _sourceAddress; ///< Source address of the responder. + static constexpr size_t SOURCE_ADDRESS_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t FIXED_LEN = SOURCE_ADDRESS_OFFSET + DOIP_SOURCE_ADDRESS_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1254,7 +1340,22 @@ namespace pcpp /// @param[in] nodeType Type of the DoIP node (default: GATEWAY). /// @param[in] maxConcurrentSockets Maximum supported concurrent sockets. /// @param[in] currentlyOpenSockets Currently active sockets. - EntityStatusResponse(DoIpEntityStatus nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets); + EntityStatusResponse(DoIpEntityStatusResponse nodeType, uint8_t maxConcurrentSockets, + uint8_t currentlyOpenSockets); + + /// @struct Represents the Routing Activation Request data in DoIP. + /// Routing Activation Response message structure (extends DoIP header). + struct entity_status_response : doiphdr + { + /// @brief Type of the DoIP node (e.g., gateway, ECU). + DoIpEntityStatusResponse nodeType; + + /// @brief Maximum number of concurrent sockets supported. + uint8_t maxConcurrentSockets; + + /// @brief Number of currently open sockets. + uint8_t currentlyOpenSockets; + }; /// @brief Returns the DoIP payload type. /// @return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE @@ -1265,7 +1366,7 @@ namespace pcpp /// @brief Gets the type of the DoIP node. /// @return The DoIP entity status value. - DoIpEntityStatus getNodeType() const; + DoIpEntityStatusResponse getNodeType() const; /// @brief Gets the maximum number of concurrent sockets supported. /// @return Max supported concurrent sockets. @@ -1277,11 +1378,11 @@ namespace pcpp /// @brief Gets the optional maximum data size field. /// @return Pointer to a 4-byte array representing max data size, or nullptr if not set. - const std::array* getMaxDataSize() const; + const uint8_t* getMaxDataSize() const; /// @brief Sets the DoIP node type. /// @param[in] status New DoIP entity status. - void setNodeType(DoIpEntityStatus status); + void setNodeType(DoIpEntityStatusResponse status); /// @brief Sets the maximum number of concurrent sockets. /// @param[in] sockets New maximum concurrent socket count. @@ -1306,28 +1407,36 @@ namespace pcpp /// @return A string summarizing the Entity Status Response. std::string getSummary() const; + /// Get a pointer to entity status response data + /// Notice this points directly to the data, so any change will modify + /// the actual packet data + /// @return A pointer to a routing_activation_response structure containing the data + entity_status_response* getEntityStatusResponsePtr() const + { + return reinterpret_cast(m_Data); + } + private: - DoIpEntityStatus _nodeType; ///< Type of the DoIP node (e.g., gateway, ECU). - uint8_t _maxConcurrentSockets; ///< Maximum number of concurrent sockets supported. - uint8_t _currentlyOpenSockets; ///< Number of currently open sockets. - std::array _maxDataSize; ///< Optional max data size field. - bool _hasMaxDataSize; ///< Indicates if max data size is set. + bool _hasMaxDataSize; ///< Indicates if max data size is set. + static constexpr size_t NODE_TYPE_LEN = 1; + static constexpr size_t MAX_CONCURRENT_SOCKETS_LEN = 1; + static constexpr size_t CURRENTLY_OPEN_SOCKETS_LEN = 1; static constexpr size_t FIXED_LEN = - sizeof(_nodeType) + sizeof(_maxConcurrentSockets) + sizeof(_currentlyOpenSockets); - static constexpr size_t MAX_DATA_SIZE_OFFSET = sizeof(doiphdr) + FIXED_LEN; - static constexpr size_t OPT_LEN = FIXED_LEN + sizeof(_maxDataSize); + DOIP_HEADER_LEN + NODE_TYPE_LEN + MAX_CONCURRENT_SOCKETS_LEN + CURRENTLY_OPEN_SOCKETS_LEN; + static constexpr size_t MAX_DATA_SIZE_OFFSET = FIXED_LEN; + static constexpr size_t MAX_DATA_SIZE_LEN = 4; + static constexpr size_t OPT_LEN = FIXED_LEN + MAX_DATA_SIZE_LEN; }; - //~~~~~~~~~~~~~~~~~~| - // DiagnosticMessage| - //~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~| + // DiagnosticBase| + //~~~~~~~~~~~~~~~| - /// @class DiagnosticMessage + /// @class DiagnosticBase /// @brief Represents a DoIP Diagnostic Message sent between tester and ECU. - /// /// This message includes source and target addresses and carries diagnostic service data. - class DiagnosticMessage : public DoIpLayer + class DiagnosticBase : public DoIpLayer { public: /// @brief Constructs the DiagnosticMessage from raw packet data. @@ -1335,20 +1444,22 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - /// @brief Constructs a DiagnosticMessage from specified field values. - /// @param[in] sourceAddress Address of the sending ECU/tester. - /// @param[in] targetAddress Address of the target ECU. - /// @param[in] diagData Vector containing UDS diagnostic service data. - DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData); + /// @brief default c'tor. + DiagnosticBase() {}; - /// @brief Returns the DoIP payload type. - /// @return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE - DoIpPayloadTypes getPayloadType() const override + /// @struct Common first diagnostic data in DoIP + /// messages (diagnostic/diagnosticAck/diagnosticNack). + /// common_diagnostic_header message structure (extends DoIP header). + struct common_diagnostic_header : doiphdr { - return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; - } + /// @brief Diagnostic source address + uint16_t sourceAddress; + + /// @brief Diagnostic target address + uint16_t targetAddress; + }; /// @brief Gets the source logical address of the message. /// @return 16-bit address of the source ECU. @@ -1358,10 +1469,6 @@ namespace pcpp /// @return 16-bit address of the destination ECU. uint16_t getTargetAddress() const; - /// @brief Gets the diagnostic data payload. - /// @return Reference to the vector containing UDS data. - const std::vector& getDiagnosticData() const; - /// @brief Sets the source logical address. /// @param[in] addr New 16-bit source address. void setSourceAddress(uint16_t addr); @@ -1370,18 +1477,71 @@ namespace pcpp /// @param[in] addr New 16-bit target address. void setTargetAddress(uint16_t addr); - /// @brief Sets the diagnostic data payload. - /// @param[in] data New diagnostic data to send. + /// @brief Returns a human-readable summary of the message content. + /// @return A string summarizing the diagnostic message. + virtual std::string getSummary() const = 0; + + /// Get a pointer to diagnostic message data + /// Notice this points directly to the data, so any change will modify + /// the actual packet data + /// @return A pointer to a common_diagnostic_header structure containing the data + common_diagnostic_header* getCommonDiagnosticHeader() const + { + return reinterpret_cast(m_Data); + } + + private: + static constexpr size_t FIX_LEN = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; + }; + + //~~~~~~~~~~~~~~~~~~| + // DiagnosticMessage| + //~~~~~~~~~~~~~~~~~~| + + /// @class DiagnosticMessage + /// @brief Represents a DoIP Diagnostic message sent between tester and ECU. + /// + /// This message includes source and target addresses and carries diagnostic service data. + class DiagnosticMessage : public DiagnosticBase + { + public: + /// @brief Constructs the DiagnosticMessage from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief Constructs a DiagnosticMessage from specified field values. + /// @param[in] sourceAddress Address of the sending ECU/tester. + /// @param[in] targetAddress Address of the target ECU. + /// @param[in] diagData Vector containing UDS diagnostic service data. + DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData); + + /// @brief Set the diagnostic data payload. + /// @param[in] data A vector containing the diagnostic data bytes to be stored. void setDiagnosticData(const std::vector& data); + /// @brief Get the diagnostic data payload. + /// @return A vector containing the diagnostic data bytes. + const std::vector getDiagnosticData() const; + /// @brief Returns a human-readable summary of the message content. /// @return A string summarizing the diagnostic message. - std::string getSummary() const; + std::string getSummary() const override; + + /// @brief Returns the DoIP payload type. + /// @return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE + DoIpPayloadTypes getPayloadType() const override + { + return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; + } private: - uint16_t _sourceAddress; ///< Logical address of the sender. - uint16_t _targetAddress; ///< Logical address of the receiver. - std::vector _diagnosticData; ///< Diagnostic (UDS) data payload. + static constexpr size_t DIAGNOSTIC_DATA_OFFSET = + DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; + static constexpr size_t MIN_LEN = + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + 1; /*Min diagnostic message Len*/ }; //~~~~~~~~~~~~~~~~~~~~~| @@ -1393,7 +1553,7 @@ namespace pcpp /// /// This message is sent by a DoIP node to acknowledge the correct reception and processing /// of a diagnostic message. Optionally, the original message (or part of it) may be echoed back. - class DiagnosticAckMessage : public DoIpLayer + class DiagnosticAckMessage : public DiagnosticBase { public: /// @brief Constructs a DiagnosticAckMessage from raw packet data. @@ -1409,24 +1569,12 @@ namespace pcpp /// @param[in] ackCode Acknowledgment code describing the result. DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode); - /// @brief Gets the source logical address of the message. - uint16_t getSourceAddress() const; - - /// @brief Gets the target logical address of the message. - uint16_t getTargetAddress() const; - /// @brief Gets the diagnostic acknowledgment code. DoIpDiagnosticAckCodes getAckCode() const; /// @brief Gets the optional previously echoed diagnostic message. /// @return Pointer to the echoed message or nullptr if not present. - const std::vector* getPreviousMessage() const; - - /// @brief Sets the source logical address. - void setSourceAddress(uint16_t address); - - /// @brief Sets the target logical address. - void setTargetAddress(uint16_t address); + const std::vector getPreviousMessage() const; /// @brief Sets the acknowledgment code. void setAckCode(DoIpDiagnosticAckCodes code); @@ -1442,7 +1590,7 @@ namespace pcpp void clearPreviousMessage(); /// @brief Returns a human-readable summary of the message. - std::string getSummary() const; + std::string getSummary() const override; /// @brief Returns the DoIP payload type. DoIpPayloadTypes getPayloadType() const override @@ -1451,13 +1599,12 @@ namespace pcpp } private: - uint16_t _sourceAddress; ///< Logical address of the sender. - uint16_t _targetAddress; ///< Logical address of the receiver. - DoIpDiagnosticAckCodes _ackCode; ///< Acknowledgment result code. - std::vector _previousMessage; ///< Optional echoed diagnostic message. - bool _hasPreviousMessage; ///< True if a previous message is present. - static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_targetAddress) + sizeof(_ackCode); - static constexpr size_t PREVIOUS_MSG_OFFSET = sizeof(doiphdr) + FIXED_LEN; + bool _hasPreviousMessage; ///< True if a previous message is present. + static constexpr size_t DIAGNOSTIC_ACK_CODE_OFFSET = + DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; + static constexpr size_t DIAGNOSTIC_ACK_CODE_LEN = 1; + static constexpr size_t FIXED_LEN = DIAGNOSTIC_ACK_CODE_OFFSET + DIAGNOSTIC_ACK_CODE_LEN; + static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~| @@ -1469,7 +1616,7 @@ namespace pcpp /// /// This message is sent by a DoIP node when a diagnostic message is received but could not /// be processed successfully. It may include the original message for reference. - class DiagnosticNackMessage : public DoIpLayer + class DiagnosticNackMessage : public DiagnosticBase { public: /// @brief Constructs a DiagnosticNackMessage from raw packet data. @@ -1485,28 +1632,16 @@ namespace pcpp /// @param[in] nackCode Negative acknowledgment code describing the failure. DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticMessageNackCodes nackCode); - /// @brief Gets the source logical address of the message. - uint16_t getSourceAddress() const; - - /// @brief Gets the target logical address of the message. - uint16_t getTargetAddress() const; - /// @brief Gets the negative acknowledgment code. DoIpDiagnosticMessageNackCodes getNackCode() const; - /// @brief Gets the optional previously echoed diagnostic message. - /// @return Pointer to the echoed message or nullptr if not present. - const std::vector* getPreviousMessage() const; - - /// @brief Sets the source logical address. - void setSourceAddress(uint16_t address); - - /// @brief Sets the target logical address. - void setTargetAddress(uint16_t address); - /// @brief Sets the negative acknowledgment code. void setNackCode(DoIpDiagnosticMessageNackCodes code); + /// @brief Gets the optional previously echoed diagnostic message. + /// @return Pointer to the echoed message or nullptr if not present. + const std::vector getPreviousMessage() const; + /// @brief Checks if a previous message is attached. /// @return True if a previous message is present. bool hasPreviousMessage() const; @@ -1518,7 +1653,7 @@ namespace pcpp void clearPreviousMessage(); /// @brief Returns a human-readable summary of the message. - std::string getSummary() const; + std::string getSummary() const override; /// @brief Returns the DoIP payload type. DoIpPayloadTypes getPayloadType() const override @@ -1527,13 +1662,12 @@ namespace pcpp } private: - uint16_t _sourceAddress; ///< Logical address of the sender. - uint16_t _targetAddress; ///< Logical address of the receiver. - DoIpDiagnosticMessageNackCodes _nackCode; ///< Negative acknowledgment result code. - std::vector _previousMessage; ///< Optional echoed diagnostic message. - bool _hasPreviousMessage; ///< True if a previous message is present. - static constexpr size_t FIXED_LEN = sizeof(_sourceAddress) + sizeof(_targetAddress) + sizeof(_nackCode); - static constexpr size_t PREVIOUS_MSG_OFFSET = sizeof(doiphdr) + FIXED_LEN; + bool _hasPreviousMessage; ///< True if a previous message is present. + static constexpr size_t DIAGNOSTIC_NACK_CODE_OFFSET = + DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; + static constexpr size_t DIAGNOSTIC_NACK_CODE_LEN = 1; + static constexpr size_t FIXED_LEN = DIAGNOSTIC_NACK_CODE_OFFSET + DIAGNOSTIC_NACK_CODE_LEN; + static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; //~~~~~~~~~~~~~~~~~~| diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 1fad920d7a..0726bfe59c 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -17,7 +17,7 @@ namespace pcpp // defined in the DoIP protocol as per ISO 13400. It maps the `DoIpActivationTypes` enum values // to their corresponding descriptions. static const std::unordered_map DoIpEnumToStringActivationTypes{ - { DoIpActivationTypes::Default, "Default" }, + { DoIpActivationTypes::DEFAULT, "Default" }, { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, }; @@ -112,9 +112,9 @@ namespace pcpp // This unordered map provides human-readable descriptions for the entity status codes // in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values // to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." - static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatus::NODE, "DoIp node" }, - { DoIpEntityStatus::GATEWAY, "DoIP gateway" }, + static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatusResponse::NODE, "DoIp node" }, + { DoIpEntityStatusResponse::GATEWAY, "DoIP gateway" }, }; // This unordered map provides a human-readable description for the DoIP acknowledgement @@ -203,7 +203,7 @@ namespace pcpp DoIpLayer::DoIpLayer() { - m_DataLen = DoIpConstants::DOIP_HEADER_LEN; + m_DataLen = DOIP_HEADER_LEN; m_Protocol = DOIP; m_Data = new uint8_t[m_DataLen]{}; } @@ -289,8 +289,7 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { - auto it = - DoIpEnumToStringPayloadType.find(static_cast(be16toh(getDoIpHeader()->payloadType))); + auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); return it->second; } @@ -299,7 +298,7 @@ namespace pcpp return htobe32(getDoIpHeader()->payloadLength); } - void DoIpLayer::setPayloadLength(const uint32_t payloadLength) + void DoIpLayer::setPayloadLength(uint32_t payloadLength) { getDoIpHeader()->payloadLength = be32toh(payloadLength); } @@ -327,102 +326,79 @@ namespace pcpp { if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) { - if (m_DataLen <= DoIpConstants::DOIP_HEADER_LEN + 2 /*source address size*/ + 2 /*target address size*/) + if (m_DataLen <= DOIP_HEADER_LEN + 2 /*source address size*/ + 2 /*target address size*/) return; - uint8_t* payload = m_Data + (DoIpConstants::DOIP_HEADER_LEN + 2 + 2); - size_t payloadLen = m_DataLen - (DoIpConstants::DOIP_HEADER_LEN + 2 + 2); + uint8_t* payload = m_Data + (DOIP_HEADER_LEN + 2 + 2); + size_t payloadLen = m_DataLen - (DOIP_HEADER_LEN + 2 + 2); m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } } - //~~~~~~~~~~~~~~~~~~~~~~~~~~| - // RoutingActivationRequest | - //~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // RoutingActivationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~| RoutingActivationRequest::RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) || - dataLen > (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) - { - throw std::runtime_error("RoutingActivationRequest: Invalid payload length"); - } - if (dataLen > (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) && - dataLen < (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) - { - throw std::runtime_error("RoutingActivationRequest: Invalid OEM field length"); - } - - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - - memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); - dataPtr += sizeof(_sourceAddress); - - _activationType = static_cast(*dataPtr); - dataPtr += sizeof(_activationType); + if (dataLen < FIXED_LEN || dataLen > OPT_LEN) + throw std::runtime_error("RoutingActivationRequest: Invalid payload length!"); - memcpy(&_reservedIso, dataPtr, DoIpConstants::DOIP_RESERVED_ISO_LEN); - dataPtr += DoIpConstants::DOIP_RESERVED_ISO_LEN; + if (dataLen > FIXED_LEN && dataLen < OPT_LEN) + throw std::runtime_error("RoutingActivationRequest: Invalid OEM field length!"); - if (dataLen - (RESERVED_OEM_OFFSET) == DoIpConstants::DOIP_RESERVED_OEM_LEN) + if (dataLen == OPT_LEN) { - memcpy(dataPtr, &_reservedOem, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } else { - PCPP_LOG_DEBUG("Reserved OEM field is empty !"); _hasReservedOem = false; + PCPP_LOG_DEBUG("Reserved OEM field is empty!"); } } - RoutingActivationRequest::RoutingActivationRequest(uint16_t sourrceAddress, DoIpActivationTypes activationType) + RoutingActivationRequest::RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType) : _hasReservedOem(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + extendLayer(DOIP_HEADER_LEN, FIXED_LEN - DOIP_HEADER_LEN); - setSourceAddress(sourrceAddress); - setActivationType(activationType); - setReservedIso({}); + auto* payload = getRoutingRequest(); + payload->sourceAddress = htobe16(sourceAddress); + payload->activationType = activationType; + // Reserved ISO is always all zeros + payload->reservedIso.fill(0); } - DoIpActivationTypes RoutingActivationRequest::getActivationType() const + uint16_t RoutingActivationRequest::getSourceAddress() const { - return _activationType; + return be16toh(getRoutingRequest()->sourceAddress); } - void RoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) + void RoutingActivationRequest::setSourceAddress(uint16_t value) { - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)); - memcpy(dataPtr, &activationType, sizeof(activationType)); - _activationType = activationType; + getRoutingRequest()->sourceAddress = htobe16(value); } - uint16_t RoutingActivationRequest::getSourceAddress() const + DoIpActivationTypes RoutingActivationRequest::getActivationType() const { - return htobe16(_sourceAddress); + return getRoutingRequest()->activationType; } - void RoutingActivationRequest::setSourceAddress(uint16_t sourceAddress) + void RoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) { - _sourceAddress = htobe16(sourceAddress); - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); + getRoutingRequest()->activationType = activationType; } - std::array RoutingActivationRequest::getReservedIso() const + std::array RoutingActivationRequest::getReservedIso() const { - return _reservedIso; + return getRoutingRequest()->reservedIso; } - void RoutingActivationRequest::setReservedIso( - const std::array& reservedIso) + void RoutingActivationRequest::setReservedIso(const std::array& reservedIso) { - _reservedIso = reservedIso; - uint8_t* dataPtr = - getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_activationType)); - memcpy(dataPtr, &_reservedIso, DoIpConstants::DOIP_RESERVED_ISO_LEN); + getRoutingRequest()->reservedIso = reservedIso; } bool RoutingActivationRequest::hasReservedOem() const @@ -430,159 +406,139 @@ namespace pcpp return _hasReservedOem; } - const std::array* RoutingActivationRequest::getReservedOem() const + const uint8_t* RoutingActivationRequest::getReservedOem() const { - return _hasReservedOem ? &_reservedOem : nullptr; + return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; } - void RoutingActivationRequest::setReservedOem( - const std::array& reservedOem) + void RoutingActivationRequest::setReservedOem(const std::array& reservedOem) { - _reservedOem = reservedOem; if (!_hasReservedOem) { - extendLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); + extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); } - setPayloadLength(OPT_LEN); - memcpy(getDataPtr(RESERVED_OEM_OFFSET), &reservedOem, sizeof(_reservedOem)); + setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); + memcpy((m_Data + FIXED_LEN), reservedOem.data(), DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } - void RoutingActivationRequest::clearReserveOem() + void RoutingActivationRequest::clearReservedOem() { - if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) + if (m_DataLen == OPT_LEN) { - shortenLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); + shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); } - if (getDataLen() == RESERVED_OEM_OFFSET) + else if (m_DataLen == FIXED_LEN) { - PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); + PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); } } std::string RoutingActivationRequest::getSummary() const { std::ostringstream oss; + DoIpActivationTypes type = getActivationType(); oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; - auto it = DoIpEnumToStringActivationTypes.find(_activationType); + auto it = DoIpEnumToStringActivationTypes.find(type); if (it != DoIpEnumToStringActivationTypes.end()) { - oss << "Activation type: " << it->second << std::hex << " (0x" << unsigned(_activationType) << ")\n"; + oss << "Activation type: " << it->second << std::hex << " (0x" << unsigned(type) << ")\n"; } else { - oss << "Activation type: Unknown" << std::hex << " (0x" << unsigned(_activationType) << ")\n"; + oss << "Activation type: Unknown" << std::hex << " (0x" << unsigned(type) << ")\n"; } - oss << "Reserved by ISO: " - << pcpp::byteArrayToHexString(_reservedIso.data(), DoIpConstants::DOIP_RESERVED_ISO_LEN) << "\n"; + oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) + << "\n"; if (_hasReservedOem) { - oss << "Reserved by OEM: " - << pcpp::byteArrayToHexString(_reservedOem.data(), DoIpConstants::DOIP_RESERVED_OEM_LEN) << '\n'; + oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << '\n'; } return oss.str(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~| - // RoutingActivationResponse | + // RoutingActivationResponse| //~~~~~~~~~~~~~~~~~~~~~~~~~~| RoutingActivationResponse::RoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN || dataLen > DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) + if (dataLen < FIXED_LEN || dataLen > OPT_LEN) { throw std::runtime_error("RoutingActivationResponse: Invalid payload length!"); } - if (dataLen > (DoIpConstants::DOIP_HEADER_LEN + FIXED_LEN) && - dataLen < (DoIpConstants::DOIP_HEADER_LEN + OPT_LEN)) + if (dataLen > FIXED_LEN && dataLen < OPT_LEN) { - throw std::runtime_error("RoutingActivationRequest: invalid OEM field length"); + throw std::runtime_error("RoutingActivationResponse: invalid OEM field length"); } - const uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - - memcpy(&_logicalAddressExternalTester, dataPtr, sizeof(_logicalAddressExternalTester)); - dataPtr += sizeof(_logicalAddressExternalTester); - - memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); - dataPtr += sizeof(_sourceAddress); - - _responseCode = static_cast(*dataPtr++); - memcpy(&_reservedIso, dataPtr, DoIpConstants::DOIP_RESERVED_ISO_LEN); - dataPtr += DoIpConstants::DOIP_RESERVED_ISO_LEN; - - if (dataLen - (RESERVED_OEM_OFFSET) == DoIpConstants::DOIP_RESERVED_OEM_LEN) + // Optional OEM part + if (dataLen == OPT_LEN) { - memcpy(&_reservedOem, dataPtr, DoIpConstants::DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } else { - PCPP_LOG_DEBUG("Reserved OEM field is empty !"); _hasReservedOem = false; + PCPP_LOG_DEBUG("Reserved OEM field is empty!"); } } + RoutingActivationResponse::RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode) : _hasReservedOem(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); + extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); - setLogicalAddressExternalTester(logicalAddressExternalTester); - setSourceAddress(sourceAddress); - setResponseCode(responseCode); - setReservedIso({}); + auto* payload = getRoutingResponse(); + payload->logicalAddressExternalTester = htobe16(logicalAddressExternalTester); + payload->sourceAddress = htobe16(sourceAddress); + payload->responseCode = responseCode; + payload->reservedIso.fill(0); } uint16_t RoutingActivationResponse::getLogicalAddressExternalTester() const { - return htobe16(_logicalAddressExternalTester); + return htobe16(getRoutingResponse()->logicalAddressExternalTester); } + void RoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) { - _logicalAddressExternalTester = htobe16(addr); - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - memcpy(dataPtr, &_logicalAddressExternalTester, sizeof(_logicalAddressExternalTester)); + getRoutingResponse()->logicalAddressExternalTester = htobe16(addr); } uint16_t RoutingActivationResponse::getSourceAddress() const { - return htobe16(_sourceAddress); + return htobe16(getRoutingResponse()->sourceAddress); } + void RoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) { - _sourceAddress = htobe16(sourceAddress); - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_logicalAddressExternalTester)); - memcpy(dataPtr, &_sourceAddress, sizeof(_sourceAddress)); + getRoutingResponse()->sourceAddress = htobe16(sourceAddress); } DoIpRoutingResponseCodes RoutingActivationResponse::getResponseCode() const { - return _responseCode; + return getRoutingResponse()->responseCode; } void RoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) { - _responseCode = code; - uint8_t* dataPtr = - getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_logicalAddressExternalTester) + sizeof(_sourceAddress)); - *dataPtr = static_cast(code); + getRoutingResponse()->responseCode = code; } - std::array RoutingActivationResponse::getReservedIso() const + std::array RoutingActivationResponse::getReservedIso() const { - return _reservedIso; + return getRoutingResponse()->reservedIso; } - void RoutingActivationResponse::setReservedIso( - const std::array& reservedIso) + + void RoutingActivationResponse::setReservedIso(const std::array& reservedIso) { - _reservedIso = reservedIso; - uint8_t* dataPtr = getDataPtr(RESERVED_OEM_OFFSET - DoIpConstants::DOIP_RESERVED_ISO_LEN); - memcpy(dataPtr, &_reservedIso, sizeof(reservedIso)); + getRoutingResponse()->reservedIso = reservedIso; } bool RoutingActivationResponse::hasReservedOem() const @@ -590,54 +546,51 @@ namespace pcpp return _hasReservedOem; } - const std::array* RoutingActivationResponse::getReservedOem() const + const uint8_t* RoutingActivationResponse::getReservedOem() const { - return _hasReservedOem ? &_reservedOem : nullptr; + return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; } - void RoutingActivationResponse::setReservedOem( - const std::array& reservedOem) + void RoutingActivationResponse::setReservedOem(const std::array& reservedOem) { - _reservedOem = reservedOem; if (!_hasReservedOem) { - extendLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); + extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); } - setPayloadLength(OPT_LEN); - memcpy(getDataPtr(RESERVED_OEM_OFFSET), &_reservedOem, sizeof(_reservedOem)); + setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); + memcpy((m_Data + FIXED_LEN), &reservedOem, DOIP_RESERVED_OEM_LEN); _hasReservedOem = true; } void RoutingActivationResponse::clearReservedOem() { - if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) + if (m_DataLen == OPT_LEN) { - shortenLayer(RESERVED_OEM_OFFSET, DoIpConstants::DOIP_RESERVED_OEM_LEN); + shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); } - if (getDataLen() == RESERVED_OEM_OFFSET) + if (m_DataLen == FIXED_LEN) { PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); } } + std::string RoutingActivationResponse::getSummary() const { std::ostringstream ss; - ss << "Logical Address (Tester): 0x" << std::hex << htobe16(_logicalAddressExternalTester) << "\n"; - ss << "Source Address: 0x" << std::hex << htobe16(_sourceAddress) << "\n"; - auto it = DoIpEnumToStringRoutingResponseCodes.find(_responseCode); + DoIpRoutingResponseCodes code = getResponseCode(); + ss << "Logical Address (Tester): 0x" << std::hex << getLogicalAddressExternalTester() << "\n"; + ss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; + auto it = DoIpEnumToStringRoutingResponseCodes.find(code); if (it != DoIpEnumToStringRoutingResponseCodes.end()) - ss << "Routing activation response code: " << it->second << " (0x" << std::hex << unsigned(_responseCode) - << ")\n"; + ss << "Routing activation response code: " << it->second << " (0x" << std::hex << unsigned(code) << ")\n"; else - ss << "Response Code: Unknown (0x" << std::hex << unsigned(_responseCode) << ")\n"; + ss << "Response Code: Unknown (0x" << std::hex << unsigned(code) << ")\n"; - ss << "Reserved by ISO: " - << pcpp::byteArrayToHexString(_reservedIso.data(), DoIpConstants::DOIP_RESERVED_ISO_LEN) << "\n"; + ss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (_hasReservedOem) - ss << "Reserved by OEM: " - << pcpp::byteArrayToHexString(_reservedOem.data(), DoIpConstants::DOIP_RESERVED_OEM_LEN) << "\n"; + ss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << "\n"; return ss.str(); } @@ -648,43 +601,45 @@ namespace pcpp GenericHeaderNack::GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != (DoIpConstants::DOIP_HEADER_LEN + sizeof(_nackCode))) + if (dataLen != FIXED_LEN) throw std::runtime_error("GenericHeaderNack: Invalid payload length!"); - - _nackCode = static_cast(data[DoIpConstants::DOIP_HEADER_LEN]); } GenericHeaderNack::GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), sizeof(_nackCode)); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, sizeof(_nackCode)); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), NACK_CODE_LEN); + extendLayer(NACK_CODE_OFFSET, NACK_CODE_LEN); setNackCode(nackCode); } DoIpGenericHeaderNackCodes GenericHeaderNack::getNackCode() const { - return _nackCode; + return static_cast(*(m_Data + NACK_CODE_OFFSET)); } void GenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) { - _nackCode = nackCode; - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - *dataPtr = static_cast(nackCode); + *(m_Data + NACK_CODE_OFFSET) = static_cast(nackCode); + } + + void GenericHeaderNack::setNackCode(uint8_t nackCode) + { + *(m_Data + NACK_CODE_OFFSET) = nackCode; } std::string GenericHeaderNack::getSummary() const { std::ostringstream ss; - auto it = DoIpEnumToStringGenericHeaderNackCodes.find(_nackCode); + DoIpGenericHeaderNackCodes nackCode = getNackCode(); + auto it = DoIpEnumToStringGenericHeaderNackCodes.find(nackCode); if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) { - ss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(_nackCode) + ss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(nackCode) << ")\n"; } else { - ss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(_nackCode) << ")\n"; + ss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(nackCode) << ")\n"; } return ss.str(); } @@ -696,37 +651,31 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_EID_LEN) + if (dataLen != FIXED_LEN) throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); - - memcpy(&_eid, data + DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_EID_LEN); } - VehicleIdentificationRequestEID::VehicleIdentificationRequestEID( - const std::array& eid) - : _eid(eid) + VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid = {}) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DoIpConstants::DOIP_EID_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_EID_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); + extendLayer(EID_OFFSET, DOIP_EID_LEN); setEID(eid); } - std::array VehicleIdentificationRequestEID::getEID() const + std::array VehicleIdentificationRequestEID::getEID() const { - return _eid; + return *reinterpret_cast*>(m_Data + EID_OFFSET); } - void VehicleIdentificationRequestEID::setEID(const std::array& eid) + void VehicleIdentificationRequestEID::setEID(const std::array& eid) { - _eid = eid; - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - memcpy(dataPtr, &_eid, DoIpConstants::DOIP_EID_LEN); + memcpy(m_Data + EID_OFFSET, &eid, DOIP_EID_LEN); } std::string VehicleIdentificationRequestEID::getSummary() const { std::ostringstream oss; - oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DoIpConstants::DOIP_EID_LEN) << "\n"; + oss << "EID: " << pcpp::byteArrayToHexString(getEID().data(), DOIP_EID_LEN) << "\n"; return oss.str(); } @@ -737,36 +686,31 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen != DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN) - throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length"); - - memcpy(&_vin, data + DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_VIN_LEN); + if (dataLen != FIXED_LEN) + throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length!"); } - VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN( - const std::array& vin) + VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin = {}) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DoIpConstants::DOIP_VIN_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, DoIpConstants::DOIP_VIN_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); + extendLayer(VIN_OFFSET, DOIP_VIN_LEN); setVIN(vin); } - std::array VehicleIdentificationRequestVIN::getVIN() const + std::array VehicleIdentificationRequestVIN::getVIN() const { - return _vin; + return *reinterpret_cast*>(m_Data + VIN_OFFSET); } - void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) + void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) { - _vin = vin; - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); - memcpy(dataPtr, &_vin, DoIpConstants::DOIP_VIN_LEN); + memcpy(m_Data + VIN_OFFSET, &vin, DOIP_VIN_LEN); } std::string VehicleIdentificationRequestVIN::getSummary() const { std::ostringstream oss; - oss << "VIN: " << std::string(reinterpret_cast(_vin.data()), _vin.size()) << "\n"; + oss << "VIN: " << std::string(reinterpret_cast(getVIN().data()), DOIP_VIN_LEN) << "\n"; return oss.str(); } @@ -776,50 +720,27 @@ namespace pcpp VehicleAnnouncement::VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; - - if (dataLen < SYNC_STATUS_OFFSET || dataLen > DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) - { + if (dataLen < FIXED_LEN || dataLen > OPT_LEN) throw std::runtime_error("VehicleAnnouncement: invalid payload length!"); - } - - memcpy(&_vin, dataPtr, DoIpConstants::DOIP_VIN_LEN); - dataPtr += DoIpConstants::DOIP_VIN_LEN; - - memcpy(&_logicalAddress, dataPtr, sizeof(_logicalAddress)); - dataPtr += sizeof(_logicalAddress); - - memcpy(&_eid, dataPtr, DoIpConstants::DOIP_EID_LEN); - dataPtr += DoIpConstants::DOIP_EID_LEN; - - memcpy(&_gid, dataPtr, DoIpConstants::DOIP_GID_LEN); - dataPtr += DoIpConstants::DOIP_GID_LEN; - - _actionCode = static_cast(*(dataPtr++)); - if (dataLen - SYNC_STATUS_OFFSET == sizeof(_syncStatus)) + if (dataLen == OPT_LEN) { - _syncStatus = static_cast(*(dataPtr)); _hasSyncStatus = true; } else { - PCPP_LOG_INFO("Sync status field is empty!"); + PCPP_LOG_DEBUG("Sync status field is empty!"); _hasSyncStatus = false; } } - VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, - uint16_t logicalAddress, - const std::array& eid, - const std::array& gid, - DoIpActionCodes actionCode) - - : _vin(vin), _logicalAddress(logicalAddress), _eid(eid), _gid(gid), _actionCode(actionCode), - _hasSyncStatus(false) + VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, DoIpActionCodes actionCode) + : _hasSyncStatus(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setVIN(vin); setLogicalAddress(logicalAddress); @@ -827,92 +748,78 @@ namespace pcpp setGID(gid); setFurtherActionRequired(actionCode); } - std::array VehicleAnnouncement::getVIN() const + std::array VehicleAnnouncement::getVIN() const { - return _vin; + return getVehicleAnnouncement()->vin; } uint16_t VehicleAnnouncement::getLogicalAddress() const { - return htobe16(_logicalAddress); + return htobe16(getVehicleAnnouncement()->logicalAddress); } - std::array VehicleAnnouncement::getEID() const + std::array VehicleAnnouncement::getEID() const { - return _eid; + return getVehicleAnnouncement()->eid; } - std::array VehicleAnnouncement::getGID() const + std::array VehicleAnnouncement::getGID() const { - return _gid; + return getVehicleAnnouncement()->gid; } DoIpActionCodes VehicleAnnouncement::getFurtherActionRequired() const { - return _actionCode; + return getVehicleAnnouncement()->actionCode; } const DoIpSyncStatus* VehicleAnnouncement::getSyncStatus() const { - return _hasSyncStatus ? &_syncStatus : nullptr; + return _hasSyncStatus ? reinterpret_cast(m_Data + SYNC_STATUS_OFFSET) : nullptr; } void VehicleAnnouncement::clearSyncStatus() { - if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN) + if (m_DataLen == OPT_LEN) { - shortenLayer(FIXED_LEN, sizeof(_syncStatus)); + shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); _hasSyncStatus = false; PCPP_LOG_INFO("Sync status has been removed successfully!"); } - if (getDataLen() == SYNC_STATUS_OFFSET) + if (m_DataLen == FIXED_LEN) { PCPP_LOG_DEBUG("doip packet has no syncStatus!"); } } - void VehicleAnnouncement::setVIN(const std::array& vin) + void VehicleAnnouncement::setVIN(const std::array& vin) { - _vin = vin; - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_vin, DoIpConstants::DOIP_VIN_LEN); + getVehicleAnnouncement()->vin = vin; } void VehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) { - _logicalAddress = htobe16(logicalAddress); - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN); - memcpy(dataPtr, &_logicalAddress, sizeof(_logicalAddress)); + getVehicleAnnouncement()->logicalAddress = be16toh(logicalAddress); } - void VehicleAnnouncement::setEID(const std::array& eid) + void VehicleAnnouncement::setEID(const std::array& eid) { - _eid = eid; - uint8_t* dataPtr = - getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress)); - memcpy(dataPtr, &_eid, DoIpConstants::DOIP_EID_LEN); + getVehicleAnnouncement()->eid = eid; } - void VehicleAnnouncement::setGID(const std::array& gid) + void VehicleAnnouncement::setGID(const std::array& gid) { - _gid = gid; - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + - sizeof(_logicalAddress) + DoIpConstants::DOIP_EID_LEN); - memcpy(dataPtr, &_gid, DoIpConstants::DOIP_GID_LEN); + getVehicleAnnouncement()->gid = gid; } void VehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) { - _actionCode = action; - uint8_t* dataPtr = - getDataPtr(DoIpConstants::DOIP_HEADER_LEN + DoIpConstants::DOIP_VIN_LEN + sizeof(_logicalAddress) + - DoIpConstants::DOIP_EID_LEN + DoIpConstants::DOIP_GID_LEN); - *dataPtr = static_cast(action); + getVehicleAnnouncement()->actionCode = action; } - void VehicleAnnouncement::setSyncStatus(DoIpSyncStatus sync) + void VehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) { - _syncStatus = sync; if (!_hasSyncStatus) { - extendLayer(SYNC_STATUS_OFFSET, sizeof(_syncStatus)); + extendLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); } - setPayloadLength(OPT_LEN); - *getDataPtr(SYNC_STATUS_OFFSET) = static_cast(_syncStatus); + setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); + *(m_Data + SYNC_STATUS_OFFSET) = static_cast(syncStatus); _hasSyncStatus = true; } @@ -924,32 +831,33 @@ namespace pcpp std::string VehicleAnnouncement::getSummary() const { std::ostringstream oss; - - oss << "VIN: " << std::string(reinterpret_cast(_vin.data()), _vin.size()) << "\n"; - oss << "Logical address: " << std::hex << "0x" << htobe16(_logicalAddress) << "\n"; - oss << "EID: " << pcpp::byteArrayToHexString(_eid.data(), DoIpConstants::DOIP_EID_LEN) << "\n"; - oss << "GID: " << pcpp::byteArrayToHexString(_gid.data(), DoIpConstants::DOIP_GID_LEN) << "\n"; - auto it = DoIpEnumToStringActionCodes.find(_actionCode); + DoIpActionCodes actionCode = getFurtherActionRequired(); + oss << "VIN: " << std::string(reinterpret_cast(getVIN().data()), DOIP_VIN_LEN) << "\n"; + oss << "Logical address: " << std::hex << "0x" << getLogicalAddress() << "\n"; + oss << "EID: " << pcpp::byteArrayToHexString(getEID().data(), DOIP_EID_LEN) << "\n"; + oss << "GID: " << pcpp::byteArrayToHexString(getGID().data(), DOIP_GID_LEN) << "\n"; + auto it = DoIpEnumToStringActionCodes.find(actionCode); if (it != DoIpEnumToStringActionCodes.end()) { - oss << "Further action required: " << it->second << std::hex << " (0x" << unsigned(_actionCode) << ")" + oss << "Further action required: " << it->second << std::hex << " (0x" << unsigned(actionCode) << ")" << "\n"; } else { - oss << "Further action required: Unknown" << std::hex << " (0x" << unsigned(_actionCode) << ")" + oss << "Further action required: Unknown" << std::hex << " (0x" << unsigned(actionCode) << ")" << "\n"; } if (_hasSyncStatus) { - auto it_ = DoIpEnumToStringSyncStatus.find(_syncStatus); + DoIpSyncStatus syncStatus = *getSyncStatus(); + auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); if (it_ != DoIpEnumToStringSyncStatus.end()) { oss << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte } else { - oss << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(_syncStatus) << ")" << "\n"; + oss << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(syncStatus) << ")" << "\n"; } } return oss.str(); @@ -961,30 +869,28 @@ namespace pcpp AliveCheckResponse::AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)) + if (dataLen < DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN) throw std::runtime_error("AliveCheckResponse: insufficient payload length"); - - const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; - memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); } AliveCheckResponse::AliveCheckResponse(uint16_t sourceAddress) { - const size_t payloadLen = sizeof(_sourceAddress); - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_SOURCE_ADDRESS_LEN); + extendLayer(DOIP_HEADER_LEN, DOIP_SOURCE_ADDRESS_LEN); setSourceAddress(sourceAddress); } uint16_t AliveCheckResponse::getSourceAddress() const { + uint16_t _sourceAddress; + memcpy(&_sourceAddress, (m_Data + SOURCE_ADDRESS_OFFSET), DOIP_SOURCE_ADDRESS_LEN); return htobe16(_sourceAddress); } - void AliveCheckResponse::setSourceAddress(uint16_t address) + void AliveCheckResponse::setSourceAddress(uint16_t sourceAddress) { - _sourceAddress = htobe16(address); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); + uint16_t _sourceAddress = htobe16(sourceAddress); + memcpy((m_Data + SOURCE_ADDRESS_OFFSET), &_sourceAddress, DOIP_SOURCE_ADDRESS_LEN); } std::string AliveCheckResponse::getSummary() const @@ -1001,11 +907,11 @@ namespace pcpp Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t payloadLen = DoIpConstants::DOIP_HEADER_LEN + sizeof(_powerModeCode); + constexpr size_t payloadLen = DOIP_HEADER_LEN + sizeof(_powerModeCode); if (dataLen != payloadLen) throw std::runtime_error("DiagnosticPowerModeResponse: invalid payload length!"); - const uint8_t* payloadPtr = data + DoIpConstants::DOIP_HEADER_LEN; + const uint8_t* payloadPtr = data + DOIP_HEADER_LEN; _powerModeCode = static_cast(*payloadPtr); } @@ -1013,7 +919,7 @@ namespace pcpp { const size_t payloadLen = sizeof(_powerModeCode); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); + extendLayer(DOIP_HEADER_LEN, payloadLen); setPowerModeCode(code); } @@ -1025,7 +931,7 @@ namespace pcpp void DiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) { _powerModeCode = code; - uint8_t* dataPtr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN); + uint8_t* dataPtr = getDataPtr(DOIP_HEADER_LEN); *dataPtr = static_cast(code); } @@ -1050,30 +956,18 @@ namespace pcpp EntityStatusResponse::EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - constexpr size_t headerLength = DoIpConstants::DOIP_HEADER_LEN; - if (dataLen < headerLength + FIXED_LEN || dataLen > headerLength + OPT_LEN) + if (dataLen < FIXED_LEN || dataLen > OPT_LEN) { throw std::runtime_error("EntityStatusResponse: Invalid payload length!"); } - if (dataLen > (headerLength + FIXED_LEN) && dataLen < (headerLength + OPT_LEN)) + if (dataLen > FIXED_LEN && dataLen < OPT_LEN) { throw std::runtime_error("EntityStatusResponse: Invalid MaxDataSize field length!"); } - const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; - _nodeType = static_cast(*dataPtr); - dataPtr += sizeof(_nodeType); - - _maxConcurrentSockets = (*dataPtr); - dataPtr += sizeof(_maxConcurrentSockets); - - _currentlyOpenSockets = (*dataPtr); - dataPtr += sizeof(_currentlyOpenSockets); - - if (dataLen - (MAX_DATA_SIZE_OFFSET) == sizeof(_maxDataSize)) + if (dataLen == OPT_LEN) { - memcpy(&_maxDataSize, dataPtr, sizeof(_maxDataSize)); _hasMaxDataSize = true; } else @@ -1083,37 +977,36 @@ namespace pcpp } } - EntityStatusResponse::EntityStatusResponse(DoIpEntityStatus nodeType, uint8_t maxConcurrentSockets, + EntityStatusResponse::EntityStatusResponse(DoIpEntityStatusResponse nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) : _hasMaxDataSize(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setNodeType(nodeType); setMaxConcurrentSockets(maxConcurrentSockets); setCurrentlyOpenSockets(currentlyOpenSockets); } - DoIpEntityStatus EntityStatusResponse::getNodeType() const + DoIpEntityStatusResponse EntityStatusResponse::getNodeType() const { - return _nodeType; + return getEntityStatusResponsePtr()->nodeType; } uint8_t EntityStatusResponse::getMaxConcurrentSockets() const { - return _maxConcurrentSockets; + return getEntityStatusResponsePtr()->maxConcurrentSockets; } uint8_t EntityStatusResponse::getCurrentlyOpenSockets() const { - return _currentlyOpenSockets; + return getEntityStatusResponsePtr()->currentlyOpenSockets; } - const std::array* EntityStatusResponse::getMaxDataSize() const + const uint8_t* EntityStatusResponse::getMaxDataSize() const { - return _hasMaxDataSize ? &_maxDataSize : nullptr; + return _hasMaxDataSize ? (m_Data + MAX_DATA_SIZE_OFFSET) : nullptr; } - void EntityStatusResponse::setNodeType(DoIpEntityStatus nodeType) + void EntityStatusResponse::setNodeType(DoIpEntityStatusResponse nodeType) { - _nodeType = nodeType; - getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[0] = static_cast(nodeType); + getEntityStatusResponsePtr()->nodeType = nodeType; } bool EntityStatusResponse::hasMaxDataSize() const { @@ -1121,9 +1014,9 @@ namespace pcpp } void EntityStatusResponse::clearMaxDataSize() { - if (getDataLen() == DoIpConstants::DOIP_HEADER_LEN + OPT_LEN && _hasMaxDataSize) + if (m_DataLen == OPT_LEN && _hasMaxDataSize) { - shortenLayer(FIXED_LEN, sizeof(_maxDataSize)); + shortenLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); _hasMaxDataSize = false; PCPP_LOG_INFO("MaxDataSize has been removed successfully!"); } @@ -1134,121 +1027,119 @@ namespace pcpp } void EntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) { - _maxConcurrentSockets = sockets; - getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[1] = sockets; + getEntityStatusResponsePtr()->maxConcurrentSockets = sockets; } void EntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) { - _currentlyOpenSockets = sockets; - getDataPtr(DoIpConstants::DOIP_HEADER_LEN)[2] = sockets; + getEntityStatusResponsePtr()->currentlyOpenSockets = sockets; } void EntityStatusResponse::setMaxDataSize(const std::array& data) { - _maxDataSize = data; if (!_hasMaxDataSize) { - extendLayer(MAX_DATA_SIZE_OFFSET, sizeof(_maxDataSize)); + extendLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); } - memcpy(getDataPtr(MAX_DATA_SIZE_OFFSET), &_maxDataSize, sizeof(_maxDataSize)); - setPayloadLength(OPT_LEN); + memcpy(m_Data + MAX_DATA_SIZE_OFFSET, &data, MAX_DATA_SIZE_LEN); + setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); _hasMaxDataSize = true; } std::string EntityStatusResponse::getSummary() const { std::ostringstream oos; - auto it = DoIpEnumToStringEntityStatusNodeTypes.find(_nodeType); + DoIpEntityStatusResponse nodeType = getNodeType(); + auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) { - oos << "Entity status: " << it->second << std::hex << " (0x" << unsigned(_nodeType) << ")" << "\n"; + oos << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; } else { - oos << "Node Type: Unknown" << std::hex << " (0x" << unsigned(_nodeType) << ")\n"; + oos << "Node Type: Unknown" << std::hex << " (0x" << unsigned(nodeType) << ")\n"; } - oos << "Max Concurrent Socket: " << unsigned(_maxConcurrentSockets) << "\n"; - oos << "Currently Opened Socket: " << unsigned(_currentlyOpenSockets) << "\n"; + oos << "Max Concurrent Socket: " << unsigned(getMaxConcurrentSockets()) << "\n"; + oos << "Currently Opened Socket: " << unsigned(getCurrentlyOpenSockets()) << "\n"; if (_hasMaxDataSize) { oos << "Max Data Size: " - << "0x" << pcpp::byteArrayToHexString(_maxDataSize.data(), 4) << "\n"; + << "0x" << pcpp::byteArrayToHexString((m_Data + MAX_DATA_SIZE_OFFSET), MAX_DATA_SIZE_LEN) << "\n"; } return oos.str(); } - //~~~~~~~~~~~~~~~~~~| - // DiagnosticMessage| - //~~~~~~~~~~~~~~~~~~| - DiagnosticMessage::DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~| + // DiagnosticBase| + //~~~~~~~~~~~~~~~| + DiagnosticBase::DiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { - if (dataLen < DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress) + - 1 /*Minimum diag payload len*/) - throw std::runtime_error("DiagnosticMessage: insufficient payload"); - - const uint8_t* dataPtr = data + DoIpConstants::DOIP_HEADER_LEN; - memcpy(&_sourceAddress, dataPtr, sizeof(_sourceAddress)); - dataPtr += (sizeof(_sourceAddress)); - memcpy(&_targetAddress, dataPtr, sizeof(_targetAddress)); - dataPtr += (sizeof(_targetAddress)); + if (dataLen < FIX_LEN) + throw std::runtime_error("DiagnosticBase: insufficient payload length!"); + } - _diagnosticData.assign(dataPtr, dataPtr + (dataLen - (DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + - sizeof(_targetAddress)))); + uint16_t DiagnosticBase::getSourceAddress() const + { + return htobe16(getCommonDiagnosticHeader()->sourceAddress); } - DiagnosticMessage::DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, - const std::vector& diagData) + uint16_t DiagnosticBase::getTargetAddress() const { - size_t payloadLen = sizeof(_sourceAddress) + sizeof(_targetAddress) + _diagnosticData.size(); - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, payloadLen); - setSourceAddress(sourceAddress); - setTargetAddress(targetAddress); - setDiagnosticData(diagData); + return htobe16(getCommonDiagnosticHeader()->targetAddress); } - uint16_t DiagnosticMessage::getSourceAddress() const + void DiagnosticBase::setSourceAddress(uint16_t sourceAddress) { - return htobe16(_sourceAddress); + getCommonDiagnosticHeader()->sourceAddress = htobe16(sourceAddress); } - uint16_t DiagnosticMessage::getTargetAddress() const + + void DiagnosticBase::setTargetAddress(uint16_t targetAddress) { - return htobe16(_targetAddress); + getCommonDiagnosticHeader()->targetAddress = htobe16(targetAddress); } - const std::vector& DiagnosticMessage::getDiagnosticData() const + + //~~~~~~~~~~~~~~~~~~| + // DiagnosticMessage| + //~~~~~~~~~~~~~~~~~~| + DiagnosticMessage::DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DiagnosticBase(data, dataLen, prevLayer, packet) { - return _diagnosticData; + if (dataLen < MIN_LEN) + throw std::runtime_error("DiagnosticBase: insufficient payload length!"); } - void DiagnosticMessage::setSourceAddress(uint16_t address) + DiagnosticMessage::DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, + const std::vector& diagData) { - _sourceAddress = htobe16(address); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); + size_t payloadLen = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + diagData.size(); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); + extendLayer(DOIP_HEADER_LEN, payloadLen); + setSourceAddress(sourceAddress); + setTargetAddress(targetAddress); + setDiagnosticData(diagData); } - void DiagnosticMessage::setTargetAddress(uint16_t targetAddress) + const std::vector DiagnosticMessage::getDiagnosticData() const { - _targetAddress = htobe16(targetAddress); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, - sizeof(_targetAddress)); + const uint8_t* diagDataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; + return std::vector(diagDataPtr, diagDataPtr + (m_DataLen - DIAGNOSTIC_DATA_OFFSET)); } void DiagnosticMessage::setDiagnosticData(const std::vector& data) { - constexpr size_t fixedLen = DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress); - const size_t newPayloadlLength = sizeof(_sourceAddress) + sizeof(_targetAddress) + data.size(); - uint8_t* dataPtr = getDataPtr(fixedLen); + const size_t newPayloadlLength = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + data.size(); + const size_t currentDiagnosticDataLen = m_DataLen - DIAGNOSTIC_DATA_OFFSET; + setPayloadLength(newPayloadlLength); // always clear the current diagnostic data and extendLayer with the new provided data - if (_diagnosticData.size() > 0) + if (currentDiagnosticDataLen > 0) { - shortenLayer(fixedLen, _diagnosticData.size()); + shortenLayer(DIAGNOSTIC_DATA_OFFSET, currentDiagnosticDataLen); } - extendLayer(fixedLen, data.size()); + extendLayer(DIAGNOSTIC_DATA_OFFSET, data.size()); + uint8_t* dataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; memcpy(dataPtr, data.data(), data.size()); - _diagnosticData = data; } std::string DiagnosticMessage::getSummary() const @@ -1263,24 +1154,14 @@ namespace pcpp // DiagnosticAckMessage| //~~~~~~~~~~~~~~~~~~~~~| DiagnosticAckMessage::DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DoIpLayer(data, dataLen, prevLayer, packet) + : DiagnosticBase(data, dataLen, prevLayer, packet) { if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); - const uint8_t* ptr = data + DoIpConstants::DOIP_HEADER_LEN; - memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); - ptr += sizeof(_sourceAddress); - - memcpy(&_targetAddress, ptr, sizeof(_targetAddress)); - ptr += sizeof(_targetAddress); - - _ackCode = static_cast(*ptr++); - const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); if (remainingData > 0) { - _previousMessage.assign(ptr, ptr + remainingData); _hasPreviousMessage = true; } else @@ -1294,51 +1175,33 @@ namespace pcpp DoIpDiagnosticAckCodes ackCode) : _hasPreviousMessage(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); - + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); + extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); setAckCode(ackCode); } - uint16_t DiagnosticAckMessage::getSourceAddress() const - { - return htobe16(_sourceAddress); - } - uint16_t DiagnosticAckMessage::getTargetAddress() const - { - return htobe16(_targetAddress); - } DoIpDiagnosticAckCodes DiagnosticAckMessage::getAckCode() const { - return _ackCode; + return static_cast(*(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET)); } - const std::vector* DiagnosticAckMessage::getPreviousMessage() const + const std::vector DiagnosticAckMessage::getPreviousMessage() const { - return _hasPreviousMessage ? &_previousMessage : nullptr; - } - - // Setter implementations. - void DiagnosticAckMessage::setSourceAddress(uint16_t address) - { - _sourceAddress = htobe16(address); - // Write sourceAddress into payload at offset 0 (immediately after doiphdr) - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); - } - - void DiagnosticAckMessage::setTargetAddress(uint16_t address) - { - _targetAddress = htobe16(address); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, - sizeof(_targetAddress)); + if (_hasPreviousMessage) + { + uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; + return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); + } + else + { + return {}; + } } void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) { - _ackCode = code; - uint8_t* ptr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress)); - *ptr = static_cast(code); + *(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET) = static_cast(code); } bool DiagnosticAckMessage::hasPreviousMessage() const @@ -1348,18 +1211,17 @@ namespace pcpp void DiagnosticAckMessage::setPreviousMessage(const std::vector& msg) { - - size_t newPayloadLen = FIXED_LEN + msg.size(); + size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); + size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; + setPayloadLength(newPayloadLen); // clear memory for old previous message if (_hasPreviousMessage) { - shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); } - setPayloadLength(newPayloadLen); extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); memcpy(ptr, msg.data(), msg.size()); - _previousMessage = msg; _hasPreviousMessage = true; } @@ -1367,7 +1229,7 @@ namespace pcpp { if (_hasPreviousMessage) { - shortenLayer(FIXED_LEN, sizeof(_previousMessage)); + shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); _hasPreviousMessage = false; PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); } @@ -1380,21 +1242,22 @@ namespace pcpp std::string DiagnosticAckMessage::getSummary() const { std::ostringstream oss; + DoIpDiagnosticAckCodes ackCode = getAckCode(); oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; oss << "Target Address: " << std::hex << "0x" << getTargetAddress() << "\n"; - auto it = DoIpEnumToStringAckCode.find(_ackCode); + auto it = DoIpEnumToStringAckCode.find(ackCode); if (it != DoIpEnumToStringAckCode.end()) { - oss << "ACK code: " << it->second << " (0x" << unsigned(_ackCode) << ")\n"; + oss << "ACK code: " << it->second << " (0x" << unsigned(ackCode) << ")\n"; } else { - oss << "ACK code: Unknown" << std::hex << " (0x" << unsigned(_ackCode) << ")\n"; + oss << "ACK code: Unknown" << std::hex << " (0x" << unsigned(ackCode) << ")\n"; } if (_hasPreviousMessage) { - oss << "Previous message: " << pcpp::byteArrayToHexString(_previousMessage.data(), _previousMessage.size()) - << "\n"; + oss << "Previous message: " + << pcpp::byteArrayToHexString(getPreviousMessage().data(), getPreviousMessage().size()) << "\n"; } return oss.str(); } @@ -1403,24 +1266,14 @@ namespace pcpp // DiagnosticNackMessage| //~~~~~~~~~~~~~~~~~~~~~~| DiagnosticNackMessage::DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DoIpLayer(data, dataLen, prevLayer, packet) + : DiagnosticBase(data, dataLen, prevLayer, packet) { if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticNackMessage: Invalid payload length"); - const uint8_t* ptr = data + DoIpConstants::DOIP_HEADER_LEN; - memcpy(&_sourceAddress, ptr, sizeof(_sourceAddress)); - ptr += sizeof(_sourceAddress); - - memcpy(&_targetAddress, ptr, sizeof(_targetAddress)); - ptr += sizeof(_targetAddress); - - _nackCode = static_cast(*ptr++); - const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); if (remainingData > 0) { - _previousMessage.assign(ptr, ptr + remainingData); _hasPreviousMessage = true; } else @@ -1434,71 +1287,55 @@ namespace pcpp DoIpDiagnosticMessageNackCodes nackCode) : _hasPreviousMessage(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN); - extendLayer(DoIpConstants::DOIP_HEADER_LEN, FIXED_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); + extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); setNackCode(nackCode); } - uint16_t DiagnosticNackMessage::getSourceAddress() const - { - return htobe16(_sourceAddress); - } - uint16_t DiagnosticNackMessage::getTargetAddress() const - { - return htobe16(_targetAddress); - } DoIpDiagnosticMessageNackCodes DiagnosticNackMessage::getNackCode() const { - return _nackCode; - } - const std::vector* DiagnosticNackMessage::getPreviousMessage() const - { - return _hasPreviousMessage ? &_previousMessage : nullptr; - } - bool DiagnosticNackMessage::hasPreviousMessage() const - { - return _hasPreviousMessage; + return static_cast(*(m_Data + DIAGNOSTIC_NACK_CODE_OFFSET)); } - void DiagnosticNackMessage::setSourceAddress(uint16_t address) + void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) { - _sourceAddress = htobe16(address); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN), &_sourceAddress, sizeof(_sourceAddress)); + *(m_Data + DIAGNOSTIC_NACK_CODE_OFFSET) = static_cast(code); } - void DiagnosticNackMessage::setTargetAddress(uint16_t address) + const std::vector DiagnosticNackMessage::getPreviousMessage() const { - _targetAddress = htobe16(address); - memcpy(getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress)), &_targetAddress, - sizeof(_targetAddress)); + if (_hasPreviousMessage) + { + uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; + return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); + } + else + { + return {}; + } } - void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) + bool DiagnosticNackMessage::hasPreviousMessage() const { - _nackCode = code; - uint8_t* ptr = getDataPtr(DoIpConstants::DOIP_HEADER_LEN + sizeof(_sourceAddress) + sizeof(_targetAddress)); - *ptr = static_cast(code); + return _hasPreviousMessage; } void DiagnosticNackMessage::setPreviousMessage(const std::vector& msg) { - const size_t newPayloadLen = FIXED_LEN + msg.size(); - + size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); + size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; + setPayloadLength(newPayloadLen); + // clear memory for old previous message if (_hasPreviousMessage) { - shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); } - - setPayloadLength(newPayloadLen); extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); - - uint8_t* dataPtr = getDataPtr(PREVIOUS_MSG_OFFSET); - memcpy(dataPtr, msg.data(), msg.size()); - - _previousMessage = msg; + uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); + memcpy(ptr, msg.data(), msg.size()); _hasPreviousMessage = true; } @@ -1506,7 +1343,7 @@ namespace pcpp { if (_hasPreviousMessage) { - shortenLayer(PREVIOUS_MSG_OFFSET, _previousMessage.size()); + shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); _hasPreviousMessage = false; PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); } @@ -1519,23 +1356,24 @@ namespace pcpp std::string DiagnosticNackMessage::getSummary() const { std::ostringstream oss; + DoIpDiagnosticMessageNackCodes nackCode = getNackCode(); oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; oss << "Target Address: 0x" << std::hex << getTargetAddress() << "\n"; - auto it = DoIpEnumToStringDiagnosticNackCodes.find(_nackCode); + auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); if (it != DoIpEnumToStringDiagnosticNackCodes.end()) { - oss << "NACK code: " << it->second << " (0x" << unsigned(_nackCode) << ")\n"; + oss << "NACK code: " << it->second << " (0x" << unsigned(nackCode) << ")\n"; } else { - oss << "NACK code: Unknown (0x" << unsigned(_nackCode) << ")\n"; + oss << "NACK code: Unknown (0x" << unsigned(nackCode) << ")\n"; } if (_hasPreviousMessage) { - oss << "Previous message: " << pcpp::byteArrayToHexString(_previousMessage.data(), _previousMessage.size()) - << "\n"; + oss << "Previous message: " + << pcpp::byteArrayToHexString(getPreviousMessage().data(), getPreviousMessage().size()) << "\n"; } return oss.str(); } diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 99c8878bfc..8fb6a96812 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -45,15 +45,14 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 11); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Routing activation request (0x0005)"); PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x0e80); - PTF_ASSERT_EQUAL(doipLayer->getActivationType(), pcpp::DoIpActivationTypes::Default, enumclass); - std::array isoField{}; + PTF_ASSERT_EQUAL(doipLayer->getActivationType(), pcpp::DoIpActivationTypes::DEFAULT, enumclass); + std::array isoField = { 0x0, 0x0, 0x0, 0x0 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), isoField); PTF_ASSERT_TRUE(doipLayer->hasReservedOem()); PTF_ASSERT_NOT_NULL(doipLayer->getReservedOem()); - std::array oemField = {}; - - PTF_ASSERT_TRUE(*doipLayer->getReservedOem() == oemField); + std::array oemField = { 0x0, 0x0, 0x0, 0x0 }; + PTF_ASSERT_BUF_COMPARE(doipLayer->getReservedOem(), oemField.data(), 4); PTF_ASSERT_EQUAL( doipLayer->getSummary(), @@ -83,7 +82,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) pcpp::RoutingActivationRequest doipLayer(0x00, pcpp::DoIpActivationTypes::WWH_OBD); doipLayer.setSourceAddress(0x0e80); - doipLayer.setActivationType(pcpp::DoIpActivationTypes::Default); + doipLayer.setActivationType(pcpp::DoIpActivationTypes::DEFAULT); doipLayer.setReservedIso(isoReserved); doipLayer.setReservedOem(oemField); @@ -105,12 +104,12 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(doipLayer.toString(), "DoIP Layer, Routing activation request (0x0005)"); PTF_ASSERT_EQUAL(doipLayer.getSourceAddress(), 0x0e80); - PTF_ASSERT_EQUAL(doipLayer.getActivationType(), pcpp::DoIpActivationTypes::Default, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getActivationType(), pcpp::DoIpActivationTypes::DEFAULT, enumclass); PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); - PTF_ASSERT_VECTORS_EQUAL(*doipLayer.getReservedOem(), oemField); + PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem(), oemField.data(), 4); - doipLayer.clearReserveOem(); + doipLayer.clearReservedOem(); PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - 4); @@ -149,10 +148,6 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) auto* doipLayer = RoutingActivationResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL( - doipLayer->getSummary(), - "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 00000000\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); @@ -167,6 +162,9 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), resISO); PTF_ASSERT_FALSE(doipLayer->hasReservedOem()); PTF_ASSERT_TRUE(doipLayer->getReservedOem() == nullptr); + PTF_ASSERT_EQUAL( + doipLayer->getSummary(), + "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 00000000\n"); } PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) @@ -210,7 +208,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) std::array resOEM{ 0x5, 0x5, 0x5, 0x5 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), resISO); PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); - PTF_ASSERT_VECTORS_EQUAL(*doipLayer.getReservedOem(), resOEM); + PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem(), resOEM.data(), 4); PTF_ASSERT_EQUAL( doipLayer.getSummary(), "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 01020304\nReserved by OEM: 05050505\n"); @@ -774,11 +772,11 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); - PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatus::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponse::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 1); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 0); const std::array& maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; - PTF_ASSERT_TRUE(*doipLayer->getMaxDataSize() == maxDataSize); + PTF_ASSERT_BUF_COMPARE(doipLayer->getMaxDataSize(), maxDataSize.data(), 4); } // DoIpEntityStatusResponsePacketParsing // DoIpEntityStatusResponsePacketCreation @@ -797,13 +795,13 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x5, 0x2, 0xff, 0xff, 0xff, 0xff }; - pcpp::EntityStatusResponse data(pcpp::DoIpEntityStatus::GATEWAY, 0, 0); + pcpp::EntityStatusResponse data(pcpp::DoIpEntityStatusResponse::GATEWAY, 0, 0); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); auto* doipLayer = doIpPacket.getLayerOfType(); - doipLayer->setNodeType(pcpp::DoIpEntityStatus::GATEWAY); + doipLayer->setNodeType(pcpp::DoIpEntityStatusResponse::GATEWAY); doipLayer->setMaxConcurrentSockets(5); doipLayer->setCurrentlyOpenSockets(2); const std::array& maxDataSize{ 0xff, 0xff, 0xff, 0xff }; @@ -819,11 +817,11 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); - PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatus::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponse::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 5); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 2); PTF_ASSERT_TRUE(doipLayer->hasMaxDataSize()); - PTF_ASSERT_TRUE(*doipLayer->getMaxDataSize() == maxDataSize); + PTF_ASSERT_BUF_COMPARE(doipLayer->getMaxDataSize(), maxDataSize.data(), 4); doipLayer->clearMaxDataSize(); PTF_ASSERT_FALSE(doipLayer->hasMaxDataSize()); PTF_ASSERT_TRUE(doipLayer->getMaxDataSize() == nullptr); @@ -866,7 +864,9 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0xe80); PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4010); const std::vector& diagData{ 0x10, 0x03 }; - PTF_ASSERT_VECTORS_EQUAL(doipLayer->getDiagnosticData(), diagData); + std::vector actual = doipLayer->getDiagnosticData(); + PTF_ASSERT_VECTORS_EQUAL(actual, diagData); + } // DoIpDiagnosticMessagePacketParsing // DoIpDiagnosticMessagePacketCreation @@ -885,8 +885,8 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0x20, 0x30, 0x40, 0x40, 0x10, 0x02 }; - std::vector diagnosticData{ 0x10, 0x02 }; - std::vector diagnosticData2{ 0x10, 0x02, 0x40, 0x50 }; + const std::vector& diagnosticData{ 0x10, 0x02 }; + const std::vector& diagnosticData2{ 0x10, 0x02, 0x40, 0x50 }; pcpp::DiagnosticMessage data(0x2030, 0x4040, diagnosticData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); @@ -954,7 +954,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getAckCode(), pcpp::DoIpDiagnosticAckCodes::ACK, enumclass); PTF_ASSERT_TRUE(doipLayer->hasPreviousMessage()); const std::vector& prev{ 0X22, 0Xf1, 0x01 }; - PTF_ASSERT_TRUE(*doipLayer->getPreviousMessage() == prev); + PTF_ASSERT_TRUE(doipLayer->getPreviousMessage() == prev); } // DoIpDiagnosticAckMessagePacketParsing // DoIpDiagnosticAckMessagePacketCreation @@ -993,8 +993,9 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x0e80); PTF_ASSERT_EQUAL(doipLayer->getAckCode(), pcpp::DoIpDiagnosticAckCodes::ACK, enumclass); PTF_ASSERT_FALSE(doipLayer->hasPreviousMessage()); - const std::vector* nullprev = doipLayer->getPreviousMessage(); - PTF_ASSERT_TRUE(nullprev == nullptr); + const std::vector nullprev = doipLayer->getPreviousMessage(); + const std::vector expected{}; + PTF_ASSERT_VECTORS_EQUAL(nullprev, expected); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x4010\nTarget Address: 0xe80\nACK code: ACK (0x0)\n"); @@ -1005,7 +1006,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x7080); PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x9010); PTF_ASSERT_TRUE(doipLayer->hasPreviousMessage()); - PTF_ASSERT_TRUE(*doipLayer->getPreviousMessage() == prev); + PTF_ASSERT_TRUE(doipLayer->getPreviousMessage() == prev); PTF_ASSERT_EQUAL( doipLayer->getSummary(), @@ -1050,7 +1051,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_TRUE(nackLayer->hasPreviousMessage()); const std::vector expectedPrev = { 0x22, 0xF1, 0x01 }; - PTF_ASSERT_TRUE(*nackLayer->getPreviousMessage() == expectedPrev); + PTF_ASSERT_TRUE(nackLayer->getPreviousMessage() == expectedPrev); PTF_ASSERT_EQUAL( nackLayer->getSummary(), @@ -1086,7 +1087,8 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_EQUAL(layer->getTargetAddress(), 0x0e80); PTF_ASSERT_EQUAL(layer->getNackCode(), pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, enumclass); PTF_ASSERT_FALSE(layer->hasPreviousMessage()); - PTF_ASSERT_TRUE(layer->getPreviousMessage() == nullptr); + const std::vector expectedPrev = {}; + PTF_ASSERT_TRUE(layer->getPreviousMessage() == expectedPrev); // Update fields and add previous message layer->setSourceAddress(0xDEAD); @@ -1097,7 +1099,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_EQUAL(layer->getSourceAddress(), 0xDEAD); PTF_ASSERT_EQUAL(layer->getTargetAddress(), 0xBEEF); PTF_ASSERT_TRUE(layer->hasPreviousMessage()); - PTF_ASSERT_TRUE(*layer->getPreviousMessage() == prevMsg); + PTF_ASSERT_TRUE(layer->getPreviousMessage() == prevMsg); PTF_ASSERT_EQUAL( layer->getSummary(), From 97ce5d1feec28488e377d49087545ccc5c28c053 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Fri, 25 Apr 2025 01:46:12 -0400 Subject: [PATCH 33/43] try fix doxygene and add base Diagnotic response Class for diagnosticAck and diagnosticNac --- Packet++/header/DoIpLayer.h | 109 ++++++++++++++-------------- Packet++/src/DoIpLayer.cpp | 140 +++++++++++++----------------------- 2 files changed, 106 insertions(+), 143 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 157fb9089a..8b62d55299 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -790,7 +790,8 @@ namespace pcpp /// @param[in] activationType Type of routing activation. RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); -/// @struct Represents the Routing Activation Request data in DoIP. +/// @struct routing_activation_request +/// Represents the Routing Activation Request data in DoIP. /// Routing Activation Response message structure (extends DoIP header). #pragma pack(push, 1) struct routing_activation_request : doiphdr @@ -889,7 +890,8 @@ namespace pcpp RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode); -/// @struct Represents the Routing Activation Response data in DoIP. +/// @struct routing_activation_response +/// Represents the Routing Activation Response data in DoIP. /// Routing Activation Response message structure (extends DoIP header). #pragma pack(push, 1) struct routing_activation_response : doiphdr @@ -1038,7 +1040,7 @@ namespace pcpp /// @brief Constructs the message using the specified EID. /// @param[in] eid A 6-byte Entity ID used for vehicle identification. - explicit VehicleIdentificationRequestEID(const std::array& eid); + explicit VehicleIdentificationRequestEID(const std::array& eid = {}); /// @brief Gets the Entity ID (EID). std::array getEID() const; @@ -1080,7 +1082,7 @@ namespace pcpp /// @brief Constructs the message using the specified VIN. /// @param[in] vin A 17-byte Vehicle Identification Number. - explicit VehicleIdentificationRequestVIN(const std::array& vin); + explicit VehicleIdentificationRequestVIN(const std::array& vin = {}); /// @brief Gets the Vehicle Identification Number (VIN). std::array getVIN() const; @@ -1343,7 +1345,8 @@ namespace pcpp EntityStatusResponse(DoIpEntityStatusResponse nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets); - /// @struct Represents the Routing Activation Request data in DoIP. + /// @struct entity_status_response + /// Represents the Routing Activation Request data in DoIP. /// Routing Activation Response message structure (extends DoIP header). struct entity_status_response : doiphdr { @@ -1449,7 +1452,8 @@ namespace pcpp /// @brief default c'tor. DiagnosticBase() {}; - /// @struct Common first diagnostic data in DoIP + /// @struct common_diagnostic_header + /// Common first diagnostic data in DoIP /// messages (diagnostic/diagnosticAck/diagnosticNack). /// common_diagnostic_header message structure (extends DoIP header). struct common_diagnostic_header : doiphdr @@ -1544,6 +1548,51 @@ namespace pcpp DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + 1; /*Min diagnostic message Len*/ }; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticResponseMessageBase| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + /// @class DiagnosticResponseMessageBase + /// @brief Represents a Basic class for Diagnostic message (ACK/NACK) sent back to tester. + class DiagnosticResponseMessageBase : public DiagnosticBase + { + public: + /// @brief Constructs the DiagnosticMessage from raw packet data. + /// @param[in] data Pointer to the raw payload data. + /// @param[in] dataLen Length of the data buffer. + /// @param[in] prevLayer Pointer to the previous protocol layer. + /// @param[in] packet Pointer to the parent packet. + DiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /// @brief default c'tor + DiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); + + /// @brief Gets the acknowledgment/nack code (1-byte). + uint8_t getResponseCode() const; + + /// @brief Sets the acknowledgment/nack code (1-byte). + void setResponseCode(uint8_t code); + + /// @brief Gets the optional previously echoed diagnostic message. + const std::vector getPreviousMessage() const; + + /// @brief Checks if a previous message is attached. + bool hasPreviousMessage() const; + + /// @brief Sets the previous echoed diagnostic message. + void setPreviousMessage(const std::vector& msg); + + /// @brief Clears the previously stored diagnostic message. + void clearPreviousMessage(); + + protected: + bool _hasPreviousMessage; ///< True if a previous message is present. + static constexpr size_t DIAGNOSTIC_ACK_CODE_OFFSET = + DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; + static constexpr size_t DIAGNOSTIC_ACK_CODE_LEN = 1; + static constexpr size_t FIXED_LEN = DIAGNOSTIC_ACK_CODE_OFFSET + DIAGNOSTIC_ACK_CODE_LEN; + static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; + }; + //~~~~~~~~~~~~~~~~~~~~~| // DiagnosticAckMessage| //~~~~~~~~~~~~~~~~~~~~~| @@ -1553,7 +1602,7 @@ namespace pcpp /// /// This message is sent by a DoIP node to acknowledge the correct reception and processing /// of a diagnostic message. Optionally, the original message (or part of it) may be echoed back. - class DiagnosticAckMessage : public DiagnosticBase + class DiagnosticAckMessage : public DiagnosticResponseMessageBase { public: /// @brief Constructs a DiagnosticAckMessage from raw packet data. @@ -1572,23 +1621,9 @@ namespace pcpp /// @brief Gets the diagnostic acknowledgment code. DoIpDiagnosticAckCodes getAckCode() const; - /// @brief Gets the optional previously echoed diagnostic message. - /// @return Pointer to the echoed message or nullptr if not present. - const std::vector getPreviousMessage() const; - /// @brief Sets the acknowledgment code. void setAckCode(DoIpDiagnosticAckCodes code); - /// @brief Checks if a previous message is attached. - /// @return True if a previous message is present. - bool hasPreviousMessage() const; - - /// @brief Sets the previous echoed diagnostic message. - void setPreviousMessage(const std::vector& msg); - - /// @brief Clears the previously stored diagnostic message. - void clearPreviousMessage(); - /// @brief Returns a human-readable summary of the message. std::string getSummary() const override; @@ -1597,14 +1632,6 @@ namespace pcpp { return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK; } - - private: - bool _hasPreviousMessage; ///< True if a previous message is present. - static constexpr size_t DIAGNOSTIC_ACK_CODE_OFFSET = - DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; - static constexpr size_t DIAGNOSTIC_ACK_CODE_LEN = 1; - static constexpr size_t FIXED_LEN = DIAGNOSTIC_ACK_CODE_OFFSET + DIAGNOSTIC_ACK_CODE_LEN; - static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~| @@ -1616,7 +1643,7 @@ namespace pcpp /// /// This message is sent by a DoIP node when a diagnostic message is received but could not /// be processed successfully. It may include the original message for reference. - class DiagnosticNackMessage : public DiagnosticBase + class DiagnosticNackMessage : public DiagnosticResponseMessageBase { public: /// @brief Constructs a DiagnosticNackMessage from raw packet data. @@ -1638,20 +1665,6 @@ namespace pcpp /// @brief Sets the negative acknowledgment code. void setNackCode(DoIpDiagnosticMessageNackCodes code); - /// @brief Gets the optional previously echoed diagnostic message. - /// @return Pointer to the echoed message or nullptr if not present. - const std::vector getPreviousMessage() const; - - /// @brief Checks if a previous message is attached. - /// @return True if a previous message is present. - bool hasPreviousMessage() const; - - /// @brief Sets the previous echoed diagnostic message. - void setPreviousMessage(const std::vector& msg); - - /// @brief Clears the previously stored diagnostic message. - void clearPreviousMessage(); - /// @brief Returns a human-readable summary of the message. std::string getSummary() const override; @@ -1660,14 +1673,6 @@ namespace pcpp { return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK; } - - private: - bool _hasPreviousMessage; ///< True if a previous message is present. - static constexpr size_t DIAGNOSTIC_NACK_CODE_OFFSET = - DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; - static constexpr size_t DIAGNOSTIC_NACK_CODE_LEN = 1; - static constexpr size_t FIXED_LEN = DIAGNOSTIC_NACK_CODE_OFFSET + DIAGNOSTIC_NACK_CODE_LEN; - static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; //~~~~~~~~~~~~~~~~~~| diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 0726bfe59c..37e56f9437 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -655,7 +655,7 @@ namespace pcpp throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); } - VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid = {}) + VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); extendLayer(EID_OFFSET, DOIP_EID_LEN); @@ -690,7 +690,7 @@ namespace pcpp throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length!"); } - VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin = {}) + VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); extendLayer(VIN_OFFSET, DOIP_VIN_LEN); @@ -1150,16 +1150,17 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticAckMessage| - //~~~~~~~~~~~~~~~~~~~~~| - DiagnosticAckMessage::DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DiagnosticBase(data, dataLen, prevLayer, packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticResponseMessageBase| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DiagnosticResponseMessageBase::DiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DiagnosticBase(data, dataLen, prevLayer, packet), _hasPreviousMessage(false) { if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); - const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); + const size_t remainingData = dataLen - PREVIOUS_MSG_OFFSET; if (remainingData > 0) { _hasPreviousMessage = true; @@ -1171,22 +1172,22 @@ namespace pcpp } } - DiagnosticAckMessage::DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, - DoIpDiagnosticAckCodes ackCode) + DiagnosticResponseMessageBase::DiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, + DoIpPayloadTypes type) : _hasPreviousMessage(false) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); - setAckCode(ackCode); } - DoIpDiagnosticAckCodes DiagnosticAckMessage::getAckCode() const + uint8_t DiagnosticResponseMessageBase::getResponseCode() const { - return static_cast(*(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET)); + return static_cast(*(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET)); } - const std::vector DiagnosticAckMessage::getPreviousMessage() const + + const std::vector DiagnosticResponseMessageBase::getPreviousMessage() const { if (_hasPreviousMessage) { @@ -1199,17 +1200,17 @@ namespace pcpp } } - void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) + void DiagnosticResponseMessageBase::setResponseCode(uint8_t code) { *(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET) = static_cast(code); } - bool DiagnosticAckMessage::hasPreviousMessage() const + bool DiagnosticResponseMessageBase::hasPreviousMessage() const { return _hasPreviousMessage; } - void DiagnosticAckMessage::setPreviousMessage(const std::vector& msg) + void DiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) { size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; @@ -1225,7 +1226,7 @@ namespace pcpp _hasPreviousMessage = true; } - void DiagnosticAckMessage::clearPreviousMessage() + void DiagnosticResponseMessageBase::clearPreviousMessage() { if (_hasPreviousMessage) { @@ -1238,6 +1239,30 @@ namespace pcpp PCPP_LOG_DEBUG("doip packet has no PreviousMessage field!"); } } + + //~~~~~~~~~~~~~~~~~~~~~| + // DiagnosticAckMessage| + //~~~~~~~~~~~~~~~~~~~~~| + DiagnosticAckMessage::DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) + {} + + DiagnosticAckMessage::DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticAckCodes ackCode) + : DiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) + { + setAckCode(ackCode); + } + + DoIpDiagnosticAckCodes DiagnosticAckMessage::getAckCode() const + { + return static_cast(getResponseCode()); + } + + void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) + { + setResponseCode(static_cast(code)); + } // Summary method. std::string DiagnosticAckMessage::getSummary() const { @@ -1266,91 +1291,24 @@ namespace pcpp // DiagnosticNackMessage| //~~~~~~~~~~~~~~~~~~~~~~| DiagnosticNackMessage::DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DiagnosticBase(data, dataLen, prevLayer, packet) - { - if (dataLen < PREVIOUS_MSG_OFFSET) - throw std::runtime_error("DiagnosticNackMessage: Invalid payload length"); - - const size_t remainingData = dataLen - (PREVIOUS_MSG_OFFSET); - if (remainingData > 0) - { - _hasPreviousMessage = true; - } - else - { - PCPP_LOG_INFO("PreviousMessage field is empty!"); - _hasPreviousMessage = false; - } - } + : DiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) + {} DiagnosticNackMessage::DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticMessageNackCodes nackCode) - : _hasPreviousMessage(false) + : DiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); - extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); - - setSourceAddress(sourceAddress); - setTargetAddress(targetAddress); setNackCode(nackCode); } DoIpDiagnosticMessageNackCodes DiagnosticNackMessage::getNackCode() const { - return static_cast(*(m_Data + DIAGNOSTIC_NACK_CODE_OFFSET)); + return static_cast(getResponseCode()); } void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) { - *(m_Data + DIAGNOSTIC_NACK_CODE_OFFSET) = static_cast(code); - } - - const std::vector DiagnosticNackMessage::getPreviousMessage() const - { - if (_hasPreviousMessage) - { - uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; - return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); - } - else - { - return {}; - } - } - - bool DiagnosticNackMessage::hasPreviousMessage() const - { - return _hasPreviousMessage; - } - - void DiagnosticNackMessage::setPreviousMessage(const std::vector& msg) - { - size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); - size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; - setPayloadLength(newPayloadLen); - // clear memory for old previous message - if (_hasPreviousMessage) - { - shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); - } - extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); - uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); - memcpy(ptr, msg.data(), msg.size()); - _hasPreviousMessage = true; - } - - void DiagnosticNackMessage::clearPreviousMessage() - { - if (_hasPreviousMessage) - { - shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); - _hasPreviousMessage = false; - PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); - } - else - { - PCPP_LOG_DEBUG("doip packet has no PreviousMessage field!"); - } + setResponseCode(static_cast(code)); } std::string DiagnosticNackMessage::getSummary() const From a274d7014ab688c51867d71032e5a3dc463452c6 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Fri, 25 Apr 2025 09:21:19 -0400 Subject: [PATCH 34/43] try fix doxygen and remove unused imports --- Packet++/header/DoIpLayer.h | 9 ++++++--- Packet++/src/DoIpLayer.cpp | 7 ++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 8b62d55299..d505881449 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -1,11 +1,10 @@ #pragma once +#include +#include #include "Layer.h" -#include "IpAddress.h" -#include "MacAddress.h" #include "Logger.h" #include "EndianPortable.h" -#include /// @file @@ -1132,6 +1131,10 @@ namespace pcpp VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, const std::array& eid, const std::array& gid, DoIpActionCodes actionCode); + +/// @struct vehicle_announcement +/// Represents the vehicle announcement data in DoIP. +/// Vehicle announcement message structure (extends DoIP header). #pragma pack(push, 1) struct vehicle_announcement : doiphdr { diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 37e56f9437..9d948eb836 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -1,14 +1,11 @@ #define LOG_MODULE PacketLogModuleDoIpLayer -#include "DoIpLayer.h" -#include "Packet.h" -#include "PayloadLayer.h" -#include "EndianPortable.h" #include #include #include -#include +#include "DoIpLayer.h" #include "GeneralUtils.h" +#include "PayloadLayer.h" namespace pcpp { From 6ddfe8e68604b0174a529f20dc6934a1eae628d1 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Wed, 30 Apr 2025 02:06:04 -0400 Subject: [PATCH 35/43] fix review request --- Packet++/header/DoIpLayer.h | 386 +++++++++++---------- Packet++/src/DoIpLayer.cpp | 444 +++++++++++++------------ Packet++/src/TcpLayer.cpp | 4 +- Packet++/src/UdpLayer.cpp | 5 + Tests/Packet++Test/Tests/DoIpTests.cpp | 89 ++--- 5 files changed, 473 insertions(+), 455 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index d505881449..0971134d55 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -12,10 +12,27 @@ /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { +/// @struct doiphdr +/// Represents an DoIP protocol header +#pragma pack(push, 1) + struct doiphdr + { + /// DoIP version (DOIPV) + uint8_t protocolVersion; + /// DoIP invert version (DOIPIV). Inverse of protocol version + uint8_t invertProtocolVersion; + /// DoIP payload type (DOIPT) + uint16_t payloadType; + /// DoIP content payload length (DOIPL) + uint32_t payloadLength; + }; +#pragma pack(pop) + static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes."); + namespace DoIpConstants { // @brief Length of doip header - static constexpr size_t DOIP_HEADER_LEN = 8; + static constexpr size_t DOIP_HEADER_LEN = sizeof(doiphdr); /// @brief Length of the Equiepement Identifier (EID) field. static constexpr size_t DOIP_EID_LEN = 6; @@ -306,7 +323,7 @@ namespace pcpp /// @brief Enum representing DoIP entity status response codes (ISO 13400). /// These codes are used to indicate the role or type of a DoIP entity in the network. - enum class DoIpEntityStatusResponse : uint8_t + enum class DoIpEntityStatusResponseCode : uint8_t { /// Gateway. /// The entity functions as a gateway, @@ -505,23 +522,6 @@ namespace pcpp TLS_PORT = 3496U }; -/// @struct doiphdr -/// Represents an DoIP protocol header -#pragma pack(push, 1) - struct doiphdr - { - /// DoIP version (DOIPV) - uint8_t protocolVersion; - /// DoIP invert version (DOIPIV). Inverse of protocol version - uint8_t invertProtocolVersion; - /// DoIP payload type (DOIPT) - uint16_t payloadType; - /// DoIP content payload length (DOIPL) - uint32_t payloadLength; - }; -#pragma pack(pop) - static_assert(sizeof(doiphdr) == 8, "DoIP header must be exactly 8 bytes."); - using namespace DoIpConstants; /// @class DoIpLayer @@ -529,13 +529,14 @@ namespace pcpp class DoIpLayer : public Layer { public: - // Takes raw data and creates one of the child classes of DoIpLayer, according to the payload type - static DoIpLayer* parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - /// Get the doip payload type /// @return DoIpPayloadTypes presenting the message doip payload type virtual DoIpPayloadTypes getPayloadType() const = 0; + /// Get the doip payload type as string + /// @return uint16_t presenting the message doip payload type as string + std::string getPayloadTypeAsStr() const; + /// Get the version of DOIP protocol /// @return DoIpProtocolVersion presenting the used protocol version (DOIPV) DoIpProtocolVersion getProtocolVersion() const; @@ -560,10 +561,6 @@ namespace pcpp /// @param[in] iVersion the invert version of DOIP protocol to set void setInvertProtocolVersion(uint8_t iVersion); - /// Get the doip payload type as string - /// @return uint16_t presenting the message doip payload type as string - std::string getPayloadTypeAsStr() const; - /// Get the doip payload length /// @return uint32_t presenting the length of doip paylad not including the header uint32_t getPayloadLength() const; @@ -572,10 +569,18 @@ namespace pcpp /// @param[in] length the doip payload length to set void setPayloadLength(uint32_t length); + /// A method that creates a DoIP layer from packet raw data + /// @param[in] data A pointer to the raw data + /// @param[in] dataLen Size of the data in bytes + /// @param[in] prevLayer A pointer to the previous layer + /// @param[in] packet A pointer to the Packet instance where layer will be stored + /// @return A newly allocated DoIP layer of one of the declared types (according to the message type) + static DoIpLayer* parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + /// A static method that checks whether a port is considered as a DOIP port /// @param[in] port The port number to check /// @return True if this is a DOIP port number, false otherwise - static inline bool isDoIpPort(const uint16_t port); + static inline bool isDoIpPort(uint16_t port); /// A static method that validates the input data /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer @@ -583,24 +588,6 @@ namespace pcpp /// @return True if the data is valid and can represent an DOIP layer static inline bool isDataValid(uint8_t* data, size_t dataLen); - /// Check if the payload type is valid. - /// @param type Payload type field from DoIP header. - /// @return True if valid, false otherwise. - static inline bool isPayloadTypeValid(uint16_t type); - - /// Validate protocol version and its inverse. - /// @param version Protocol version field. - /// @param invVersion Inverse version field. - /// @param type Payload type (may affect validation rules). - /// @return True if valid, false otherwise. - static inline bool isProtocolVersionValid(uint8_t version, uint8_t invVersion, DoIpPayloadTypes type); - - /// Check if payload length fits within the given buffer. - /// @param payloadLength Declared payload length from header. - /// @param dataLen Total available buffer length. - /// @return True if the buffer is sufficient, false otherwise. - static inline bool isPayloadLengthValid(uint32_t payloadLength, size_t dataLen); - // implement abstract methods /// parse UDS layer @@ -614,7 +601,8 @@ namespace pcpp std::string toString() const override; - void computeCalculateFields() override {}; + void computeCalculateFields() override + {} OsiModelLayer getOsiModelLayer() const override { @@ -624,6 +612,12 @@ namespace pcpp private: void setPayloadType(DoIpPayloadTypes payloadType); + static inline bool isPayloadTypeValid(uint16_t type); + + static inline bool isProtocolVersionValid(uint8_t version, uint8_t invVersion, DoIpPayloadTypes type); + + static inline bool isPayloadLengthValid(uint32_t payloadLength, size_t dataLen); + protected: // protected c'tors, this class cannot be instantiated by users DoIpLayer(); @@ -641,16 +635,16 @@ namespace pcpp // inline methods definition inline bool DoIpLayer::isDoIpPort(uint16_t port) { - return (static_cast(port) == DoIpPorts::UDP_PORT || - static_cast(port) == DoIpPorts::TCP_PORT || - static_cast(port) == DoIpPorts::TLS_PORT); + auto portAsEnum = static_cast(port); + return (portAsEnum == DoIpPorts::UDP_PORT || portAsEnum == DoIpPorts::TCP_PORT || + portAsEnum == DoIpPorts::TLS_PORT); } inline bool DoIpLayer::isDataValid(uint8_t* data, size_t dataLen) { if (data == nullptr) { - PCPP_LOG_ERROR("Data pointer is null!"); + PCPP_LOG_DEBUG("Data pointer is null!"); return false; } @@ -660,12 +654,12 @@ namespace pcpp const uint16_t payloadRaw = doipHeader->payloadType; const uint32_t lengthRaw = doipHeader->payloadLength; - const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); const uint32_t payloadLen = htobe32(lengthRaw); if (!isPayloadTypeValid(payloadRaw)) return false; // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() + const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); if (!isProtocolVersionValid(version, inVersion, payloadType)) return false; @@ -683,7 +677,7 @@ namespace pcpp { case DoIpProtocolVersion::ReservedVersion: { - PCPP_LOG_ERROR("[Malformed doip packet]: Reserved ISO DoIP protocol version detected: 0x" + PCPP_LOG_DEBUG("[Malformed doip packet]: Reserved ISO DoIP protocol version detected: 0x" << std::hex << static_cast(version)); return false; } @@ -692,7 +686,7 @@ namespace pcpp type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST) { - PCPP_LOG_ERROR("[Malformed doip packet]: Invalid/unsupported DoIP version!"); + PCPP_LOG_DEBUG("[Malformed doip packet]: Invalid/unsupported DoIP version!"); return false; } case DoIpProtocolVersion::Version01Iso2010: @@ -702,7 +696,7 @@ namespace pcpp { if (version != static_cast(~inVersion)) { - PCPP_LOG_ERROR("[Malformed doip packet]: Protocol version and inverse version mismatch! Version: 0x" + PCPP_LOG_DEBUG("[Malformed doip packet]: Protocol version and inverse version mismatch! Version: 0x" << std::hex << static_cast(version) << ", Inverted: 0x" << static_cast(inVersion)); return false; @@ -710,7 +704,7 @@ namespace pcpp return true; } default: - PCPP_LOG_ERROR("[Malformed doip packet]: Unknown DoIP protocol version: 0x" << std::hex + PCPP_LOG_DEBUG("[Malformed doip packet]: Unknown DoIP protocol version: 0x" << std::hex << static_cast(version)); return false; } @@ -741,23 +735,18 @@ namespace pcpp return true; default: - PCPP_LOG_ERROR("[Malformed doip packet]: Invalid DoIP payload type: 0x" << std::hex << type); + PCPP_LOG_DEBUG("[Malformed doip packet]: Invalid DoIP payload type: 0x" << std::hex << type); return false; } } inline bool DoIpLayer::isPayloadLengthValid(uint32_t payloadLength, size_t dataLen) { - if (dataLen < DOIP_HEADER_LEN) - { - PCPP_LOG_ERROR("[Malformed doip packet]: Data length is smaller than DOIP header size!"); - return false; - } - const size_t actualPayloadLen = dataLen - DOIP_HEADER_LEN; + if (payloadLength != actualPayloadLen) { - PCPP_LOG_ERROR("[Malformed doip packet]: Payload length mismatch: expected " + PCPP_LOG_DEBUG("[Malformed doip packet]: Payload length mismatch: expected " << payloadLength << " bytes, but got " << actualPayloadLen << " bytes."); return false; } @@ -769,12 +758,12 @@ namespace pcpp // RoutingActivationRequest| //~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class RoutingActivationRequest + /// @class DoIpRoutingActivationRequest /// @brief Represents a DoIP Routing Activation Request message. /// /// Provides parsing and construction for Routing Activation Request messages /// as defined by the DoIP protocol. - class RoutingActivationRequest : public DoIpLayer + class DoIpRoutingActivationRequest : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -782,12 +771,12 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpRoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message from field values. /// @param[in] sourceAddress Source address of the tester. /// @param[in] activationType Type of routing activation. - RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); + DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); /// @struct routing_activation_request /// Represents the Routing Activation Request data in DoIP. @@ -845,7 +834,7 @@ namespace pcpp return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; } - /// Get a pointer to Routing activation request message + /// @brief Get a pointer to Routing activation request message /// Notice this points directly to the data, so any change will modify /// the actual packet data /// @return A pointer to a routing_activation_request structure containing the data @@ -863,16 +852,16 @@ namespace pcpp static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // RoutingActivationResponse | - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpRoutingActivationResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class RoutingActivationResponse + /// @class DoIpRoutingActivationResponse /// @brief Represents a DoIP Routing Activation Response message. /// /// Provides parsing and construction for Routing Activation Response messages /// as defined by the DoIP protocol. - class RoutingActivationResponse : public DoIpLayer + class DoIpRoutingActivationResponse : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -880,14 +869,14 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - RoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpRoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message from field values. /// @param[in] logicalAddressExternalTester Logical address of the external tester. /// @param[in] sourceAddress ECU source address. /// @param[in] responseCode The routing response code. - RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, - DoIpRoutingResponseCodes responseCode); + DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, + DoIpRoutingResponseCodes responseCode); /// @struct routing_activation_response /// Represents the Routing Activation Response data in DoIP. @@ -973,15 +962,15 @@ namespace pcpp static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; - //~~~~~~~~~~~~~~~~~~~| - // GenericHeaderNack | - //~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~| + // DoIpGenericHeaderNack| + //~~~~~~~~~~~~~~~~~~~~~~| - /// @class GenericHeaderNack + /// @class DoIpGenericHeaderNack /// @brief Represents a DoIP Generic Header Negative Acknowledgement message. /// /// This message indicates that a received DoIP header was invalid or unsupported. - class GenericHeaderNack : public DoIpLayer + class DoIpGenericHeaderNack : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -989,11 +978,11 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpGenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message with a specific NACK code. /// @param[in] nackCode The generic header NACK code. - explicit GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode); + explicit DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode); /// @brief Gets the NACK code. DoIpGenericHeaderNackCodes getNackCode() const; @@ -1019,15 +1008,15 @@ namespace pcpp static constexpr size_t FIXED_LEN = NACK_CODE_OFFSET + NACK_CODE_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequestEID | - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequestEID| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class VehicleIdentificationRequestEID + /// @class DoIpVehicleIdentificationRequestEID /// @brief Represents a DoIP Vehicle Identification Request with EID. /// /// This message is used to identify a vehicle based on its Entity ID (EID). - class VehicleIdentificationRequestEID : public DoIpLayer + class DoIpVehicleIdentificationRequestEID : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1035,11 +1024,11 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - VehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpVehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified EID. /// @param[in] eid A 6-byte Entity ID used for vehicle identification. - explicit VehicleIdentificationRequestEID(const std::array& eid = {}); + explicit DoIpVehicleIdentificationRequestEID(const std::array& eid = {}); /// @brief Gets the Entity ID (EID). std::array getEID() const; @@ -1061,15 +1050,15 @@ namespace pcpp static constexpr size_t FIXED_LEN = EID_OFFSET + DOIP_EID_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequestVIN | - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequestVIN| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class VehicleIdentificationRequestVIN + /// @class DoIpVehicleIdentificationRequestVIN /// @brief Represents a DoIP Vehicle Identification Request with VIN. /// /// This message is used to identify a vehicle based on its Vehicle Identification Number (VIN). - class VehicleIdentificationRequestVIN : public DoIpLayer + class DoIpVehicleIdentificationRequestVIN : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1077,11 +1066,11 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - VehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpVehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified VIN. /// @param[in] vin A 17-byte Vehicle Identification Number. - explicit VehicleIdentificationRequestVIN(const std::array& vin = {}); + explicit DoIpVehicleIdentificationRequestVIN(const std::array& vin = {}); /// @brief Gets the Vehicle Identification Number (VIN). std::array getVIN() const; @@ -1103,16 +1092,16 @@ namespace pcpp static constexpr size_t FIXED_LEN = VIN_OFFSET + DOIP_VIN_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~| - // VehicleAnnouncement | - //~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleAnnouncement| + //~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class VehicleAnnouncement + /// @class DoIpVehicleAnnouncement /// @brief Represents a DoIP Vehicle Announcement message. /// /// This message is broadcasted by a vehicle to announce its presence, including VIN, /// logical address, EID, GID, and optionally synchronization status. - class VehicleAnnouncement : public DoIpLayer + class DoIpVehicleAnnouncement : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1120,7 +1109,7 @@ namespace pcpp /// @param[in] dataLen Size of the data buffer in bytes. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpVehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using specified field values. /// @param[in] vin Vehicle Identification Number (VIN). @@ -1128,9 +1117,9 @@ namespace pcpp /// @param[in] eid Entity Identifier (EID). /// @param[in] gid Group Identifier (GID). /// @param[in] actionCode Further action code. - VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, - const std::array& eid, const std::array& gid, - DoIpActionCodes actionCode); + DoIpVehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, DoIpActionCodes actionCode); /// @struct vehicle_announcement /// Represents the vehicle announcement data in DoIP. @@ -1229,16 +1218,16 @@ namespace pcpp static constexpr size_t OPT_LEN = FIXED_LEN + SYNC_STATUS_LEN; }; - //~~~~~~~~~~~~~~~~~~~~| - // AliveCheckResponse | - //~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpAliveCheckResponse| + //~~~~~~~~~~~~~~~~~~~~~~~| - /// @class AliveCheckResponse + /// @class DoIpAliveCheckResponse /// @brief Represents a DoIP Alive Check Response message. /// /// The Alive Check Response is used to confirm that an entity is still active in the network. /// It contains the source address of the responder. - class AliveCheckResponse : public DoIpLayer + class DoIpAliveCheckResponse : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1246,11 +1235,11 @@ namespace pcpp /// @param[in] dataLen Size of the data buffer in bytes. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpAliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified source address. /// @param[in] sourceAddress The source address of the responder. - explicit AliveCheckResponse(uint16_t sourceAddress); + explicit DoIpAliveCheckResponse(uint16_t sourceAddress); /// @brief Gets the source address. /// @return The 2-byte source address of the responder. @@ -1276,16 +1265,16 @@ namespace pcpp static constexpr size_t FIXED_LEN = SOURCE_ADDRESS_OFFSET + DOIP_SOURCE_ADDRESS_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticPowerModeResponse| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticPowerModeResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticPowerModeResponse + /// @class DoIpDiagnosticPowerModeResponse /// @brief Represents a DoIP Diagnostic Power Mode Response message. /// /// This message is used to communicate the current power mode of the vehicle /// or control unit in response to a diagnostic power mode request. - class DiagnosticPowerModeResponse : public DoIpLayer + class DoIpDiagnosticPowerModeResponse : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1293,11 +1282,11 @@ namespace pcpp /// @param[in] dataLen Size of the data buffer in bytes. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified power mode code. /// @param[in] modeCode Diagnostic power mode code to set. - explicit DiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes modeCode); + explicit DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes modeCode); /// @brief Gets the current power mode code. /// @return The diagnostic power mode code. @@ -1322,16 +1311,16 @@ namespace pcpp DoIpDiagnosticPowerModeCodes _powerModeCode; ///< Diagnostic power mode code. }; - //~~~~~~~~~~~~~~~~~~~~~| - // EntityStatusResponse| - //~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpEntityStatusResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class EntityStatusResponse + /// @class DoIpEntityStatusResponse /// @brief Represents a DoIP Entity Status Response message. /// /// This message provides the status of a DoIP entity, such as its type, /// the number of concurrent sockets it can support, and optionally the max data size. - class EntityStatusResponse : public DoIpLayer + class DoIpEntityStatusResponse : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1339,14 +1328,14 @@ namespace pcpp /// @param[in] dataLen Size of the data buffer in bytes. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpEntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using provided field values. /// @param[in] nodeType Type of the DoIP node (default: GATEWAY). /// @param[in] maxConcurrentSockets Maximum supported concurrent sockets. /// @param[in] currentlyOpenSockets Currently active sockets. - EntityStatusResponse(DoIpEntityStatusResponse nodeType, uint8_t maxConcurrentSockets, - uint8_t currentlyOpenSockets); + DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, uint8_t maxConcurrentSockets, + uint8_t currentlyOpenSockets); /// @struct entity_status_response /// Represents the Routing Activation Request data in DoIP. @@ -1354,7 +1343,7 @@ namespace pcpp struct entity_status_response : doiphdr { /// @brief Type of the DoIP node (e.g., gateway, ECU). - DoIpEntityStatusResponse nodeType; + DoIpEntityStatusResponseCode nodeType; /// @brief Maximum number of concurrent sockets supported. uint8_t maxConcurrentSockets; @@ -1372,7 +1361,7 @@ namespace pcpp /// @brief Gets the type of the DoIP node. /// @return The DoIP entity status value. - DoIpEntityStatusResponse getNodeType() const; + DoIpEntityStatusResponseCode getNodeType() const; /// @brief Gets the maximum number of concurrent sockets supported. /// @return Max supported concurrent sockets. @@ -1388,7 +1377,7 @@ namespace pcpp /// @brief Sets the DoIP node type. /// @param[in] status New DoIP entity status. - void setNodeType(DoIpEntityStatusResponse status); + void setNodeType(DoIpEntityStatusResponseCode status); /// @brief Sets the maximum number of concurrent sockets. /// @param[in] sockets New maximum concurrent socket count. @@ -1435,14 +1424,14 @@ namespace pcpp static constexpr size_t OPT_LEN = FIXED_LEN + MAX_DATA_SIZE_LEN; }; - //~~~~~~~~~~~~~~~| - // DiagnosticBase| - //~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticBase| + //~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticBase + /// @class DoIpDiagnosticBase /// @brief Represents a DoIP Diagnostic Message sent between tester and ECU. - /// This message includes source and target addresses and carries diagnostic service data. - class DiagnosticBase : public DoIpLayer + /// This class includes source and target addresses. + class DoIpDiagnosticBase : public DoIpLayer { public: /// @brief Constructs the DiagnosticMessage from raw packet data. @@ -1450,10 +1439,10 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief default c'tor. - DiagnosticBase() {}; + DoIpDiagnosticBase() {}; /// @struct common_diagnostic_header /// Common first diagnostic data in DoIP @@ -1501,15 +1490,15 @@ namespace pcpp static constexpr size_t FIX_LEN = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; }; - //~~~~~~~~~~~~~~~~~~| - // DiagnosticMessage| - //~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticMessage| + //~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticMessage + /// @class DoIpDiagnosticMessage /// @brief Represents a DoIP Diagnostic message sent between tester and ECU. /// /// This message includes source and target addresses and carries diagnostic service data. - class DiagnosticMessage : public DiagnosticBase + class DoIpDiagnosticMessage : public DoIpDiagnosticBase { public: /// @brief Constructs the DiagnosticMessage from raw packet data. @@ -1517,13 +1506,13 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs a DiagnosticMessage from specified field values. /// @param[in] sourceAddress Address of the sending ECU/tester. /// @param[in] targetAddress Address of the target ECU. /// @param[in] diagData Vector containing UDS diagnostic service data. - DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData); + DoIpDiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData); /// @brief Set the diagnostic data payload. /// @param[in] data A vector containing the diagnostic data bytes to be stored. @@ -1544,6 +1533,12 @@ namespace pcpp return DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE; } + // override getHeaderLen() + size_t getHeaderLen() const override + { + return sizeof(doiphdr) + 2 * sizeof(uint16_t); + } + private: static constexpr size_t DIAGNOSTIC_DATA_OFFSET = DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; @@ -1551,12 +1546,12 @@ namespace pcpp DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + 1; /*Min diagnostic message Len*/ }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticResponseMessageBase| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticResponseMessageBase + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticResponseMessageBase| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + /// @class DoIpDiagnosticResponseMessageBase /// @brief Represents a Basic class for Diagnostic message (ACK/NACK) sent back to tester. - class DiagnosticResponseMessageBase : public DiagnosticBase + class DoIpDiagnosticResponseMessageBase : public DoIpDiagnosticBase { public: /// @brief Constructs the DiagnosticMessage from raw packet data. @@ -1564,10 +1559,10 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief default c'tor - DiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); + DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); /// @brief Gets the acknowledgment/nack code (1-byte). uint8_t getResponseCode() const; @@ -1596,16 +1591,16 @@ namespace pcpp static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; - //~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticAckMessage| - //~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticAckMessage| + //~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticAckMessage + /// @class DoIpDiagnosticAckMessage /// @brief Represents a positive acknowledgment message in response to a DiagnosticMessage. /// /// This message is sent by a DoIP node to acknowledge the correct reception and processing /// of a diagnostic message. Optionally, the original message (or part of it) may be echoed back. - class DiagnosticAckMessage : public DiagnosticResponseMessageBase + class DoIpDiagnosticAckMessage : public DoIpDiagnosticResponseMessageBase { public: /// @brief Constructs a DiagnosticAckMessage from raw packet data. @@ -1613,13 +1608,13 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs a DiagnosticAckMessage from specified field values. /// @param[in] sourceAddress Address of the sending ECU. /// @param[in] targetAddress Address of the receiving ECU. /// @param[in] ackCode Acknowledgment code describing the result. - DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode); + DoIpDiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode); /// @brief Gets the diagnostic acknowledgment code. DoIpDiagnosticAckCodes getAckCode() const; @@ -1637,16 +1632,16 @@ namespace pcpp } }; - //~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticNackMessage| - //~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticNackMessage| + //~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticNackMessage + /// @class DoIpDiagnosticNackMessage /// @brief Represents a negative acknowledgment message in response to a DiagnosticMessage. /// /// This message is sent by a DoIP node when a diagnostic message is received but could not /// be processed successfully. It may include the original message for reference. - class DiagnosticNackMessage : public DiagnosticResponseMessageBase + class DoIpDiagnosticNackMessage : public DoIpDiagnosticResponseMessageBase { public: /// @brief Constructs a DiagnosticNackMessage from raw packet data. @@ -1654,13 +1649,14 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpDiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs a DiagnosticNackMessage from specified field values. /// @param[in] sourceAddress Address of the sending ECU. /// @param[in] targetAddress Address of the receiving ECU. /// @param[in] nackCode Negative acknowledgment code describing the failure. - DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticMessageNackCodes nackCode); + DoIpDiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticMessageNackCodes nackCode); /// @brief Gets the negative acknowledgment code. DoIpDiagnosticMessageNackCodes getNackCode() const; @@ -1678,16 +1674,16 @@ namespace pcpp } }; - //~~~~~~~~~~~~~~~~~~| - // AliveCheckRequest| - //~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~| + // DoIpAliveCheckRequest| + //~~~~~~~~~~~~~~~~~~~~~~| - /// @class AliveCheckRequest + /// @class DoIpAliveCheckRequest /// @brief Represents an Alive Check Request message in the DoIP protocol. /// /// This message is sent by a tester to verify if a DoIP entity is responsive. /// The responding DoIP node should reply with an Alive Check Response. - class AliveCheckRequest : public DoIpLayer + class DoIpAliveCheckRequest : public DoIpLayer { public: /// @brief Constructs an AliveCheckRequest from raw packet data. @@ -1695,12 +1691,12 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - AliveCheckRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + DoIpAliveCheckRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} /// @brief Default constructor to create an empty AliveCheckRequest message. - AliveCheckRequest(); + DoIpAliveCheckRequest(); /// @brief Returns the DoIP payload type for this message. DoIpPayloadTypes getPayloadType() const override @@ -1709,16 +1705,16 @@ namespace pcpp } }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequest| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class VehicleIdentificationRequest + /// @class DoIpVehicleIdentificationRequest /// @brief Represents a Vehicle Identification Request message in the DoIP protocol. /// /// This message is sent by a tester to request vehicle identification information /// such as VIN, logical addresses, and other metadata. It can be broadcast or directed. - class VehicleIdentificationRequest : public DoIpLayer + class DoIpVehicleIdentificationRequest : public DoIpLayer { public: /// @brief Constructs a VehicleIdentificationRequest from raw packet data. @@ -1726,12 +1722,12 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - VehicleIdentificationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + DoIpVehicleIdentificationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} /// @brief Default constructor to create an empty VehicleIdentificationRequest. - VehicleIdentificationRequest(); + DoIpVehicleIdentificationRequest(); /// @brief Returns the DoIP payload type. DoIpPayloadTypes getPayloadType() const override @@ -1740,16 +1736,16 @@ namespace pcpp } }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticPowerModeRequest| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticPowerModeRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DiagnosticPowerModeRequest + /// @class DoIpDiagnosticPowerModeRequest /// @brief Represents a Diagnostic Power Mode Request message in the DoIP protocol. /// /// This message is sent to inquire about the current power mode status of the vehicle, /// which helps determine if diagnostic communication can be initiated or continued. - class DiagnosticPowerModeRequest : public DoIpLayer + class DoIpDiagnosticPowerModeRequest : public DoIpLayer { public: /// @brief Constructs a DiagnosticPowerModeRequest from raw packet data. @@ -1757,12 +1753,12 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - DiagnosticPowerModeRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + DoIpDiagnosticPowerModeRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} /// @brief Default constructor to create an empty DiagnosticPowerModeRequest. - DiagnosticPowerModeRequest(); + DoIpDiagnosticPowerModeRequest(); /// @brief Returns the DoIP payload type. DoIpPayloadTypes getPayloadType() const override @@ -1771,17 +1767,17 @@ namespace pcpp } }; - //~~~~~~~~~~~~~~~~~~~~| - // EntityStatusRequest| - //~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpEntityStatusRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class EntityStatusRequest + /// @class DoIpEntityStatusRequest /// @brief Represents an Entity Status Request message in the DoIP protocol. /// /// This message is sent by a tester to request the current status of the DoIP entity, /// including capabilities such as maximum number of concurrent socket connections /// and optionally the maximum data size supported. - class EntityStatusRequest : public DoIpLayer + class DoIpEntityStatusRequest : public DoIpLayer { public: /// @brief Constructs an EntityStatusRequest from raw packet data. @@ -1789,12 +1785,12 @@ namespace pcpp /// @param[in] dataLen Length of the data buffer. /// @param[in] prevLayer Pointer to the previous protocol layer. /// @param[in] packet Pointer to the parent packet. - EntityStatusRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + DoIpEntityStatusRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} /// @brief Default constructor to create an empty EntityStatusRequest message. - EntityStatusRequest(); + DoIpEntityStatusRequest(); /// @brief Returns the DoIP payload type for this message. DoIpPayloadTypes getPayloadType() const override diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 9d948eb836..e364a121e5 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -109,9 +109,9 @@ namespace pcpp // This unordered map provides human-readable descriptions for the entity status codes // in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values // to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." - static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatusResponse::NODE, "DoIp node" }, - { DoIpEntityStatusResponse::GATEWAY, "DoIP gateway" }, + static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ + { DoIpEntityStatusResponseCode::NODE, "DoIp node" }, + { DoIpEntityStatusResponseCode::GATEWAY, "DoIP gateway" }, }; // This unordered map provides a human-readable description for the DoIP acknowledgement @@ -218,37 +218,37 @@ namespace pcpp switch (detectedPayloadType) { case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: - return new RoutingActivationRequest(data, dataLen, prevLayer, packet); + return new DoIpRoutingActivationRequest(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: - return new RoutingActivationResponse(data, dataLen, prevLayer, packet); + return new DoIpRoutingActivationResponse(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: - return new GenericHeaderNack(data, dataLen, prevLayer, packet); + return new DoIpGenericHeaderNack(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: - return new VehicleIdentificationRequestEID(data, dataLen, prevLayer, packet); + return new DoIpVehicleIdentificationRequestEID(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: - return new VehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet); + return new DoIpVehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: - return new VehicleAnnouncement(data, dataLen, prevLayer, packet); + return new DoIpVehicleAnnouncement(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: - return new AliveCheckResponse(data, dataLen, prevLayer, packet); + return new DoIpAliveCheckResponse(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: - return new DiagnosticPowerModeResponse(data, dataLen, prevLayer, packet); + return new DoIpDiagnosticPowerModeResponse(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: - return new EntityStatusResponse(data, dataLen, prevLayer, packet); + return new DoIpEntityStatusResponse(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: - return new DiagnosticMessage(data, dataLen, prevLayer, packet); + return new DoIpDiagnosticMessage(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: - return new DiagnosticAckMessage(data, dataLen, prevLayer, packet); + return new DoIpDiagnosticAckMessage(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: - return new DiagnosticNackMessage(data, dataLen, prevLayer, packet); + return new DoIpDiagnosticNackMessage(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: - return new VehicleIdentificationRequest(data, dataLen, prevLayer, packet); + return new DoIpVehicleIdentificationRequest(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: - return new AliveCheckRequest(data, dataLen, prevLayer, packet); + return new DoIpAliveCheckRequest(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: - return new DiagnosticPowerModeRequest(data, dataLen, prevLayer, packet); + return new DoIpDiagnosticPowerModeRequest(data, dataLen, prevLayer, packet); case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: - return new EntityStatusRequest(data, dataLen, prevLayer, packet); + return new DoIpEntityStatusRequest(data, dataLen, prevLayer, packet); default: return nullptr; } @@ -323,26 +323,32 @@ namespace pcpp { if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE) { - if (m_DataLen <= DOIP_HEADER_LEN + 2 /*source address size*/ + 2 /*target address size*/) + size_t headerLen = getHeaderLen(); + + if (m_DataLen <= headerLen) + { return; + } - uint8_t* payload = m_Data + (DOIP_HEADER_LEN + 2 + 2); - size_t payloadLen = m_DataLen - (DOIP_HEADER_LEN + 2 + 2); - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + constructNextLayer(payload, payloadLen, m_Packet); } } - //~~~~~~~~~~~~~~~~~~~~~~~~~| - // RoutingActivationRequest| - //~~~~~~~~~~~~~~~~~~~~~~~~~| - RoutingActivationRequest::RoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpRoutingActivationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpRoutingActivationRequest::DoIpRoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < FIXED_LEN || dataLen > OPT_LEN) - throw std::runtime_error("RoutingActivationRequest: Invalid payload length!"); + throw std::runtime_error("DoIpRoutingActivationRequest: Invalid payload length!"); if (dataLen > FIXED_LEN && dataLen < OPT_LEN) - throw std::runtime_error("RoutingActivationRequest: Invalid OEM field length!"); + throw std::runtime_error("DoIpRoutingActivationRequest: Invalid OEM field length!"); if (dataLen == OPT_LEN) { @@ -355,7 +361,8 @@ namespace pcpp } } - RoutingActivationRequest::RoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType) + DoIpRoutingActivationRequest::DoIpRoutingActivationRequest(uint16_t sourceAddress, + DoIpActivationTypes activationType) : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); @@ -368,47 +375,47 @@ namespace pcpp payload->reservedIso.fill(0); } - uint16_t RoutingActivationRequest::getSourceAddress() const + uint16_t DoIpRoutingActivationRequest::getSourceAddress() const { return be16toh(getRoutingRequest()->sourceAddress); } - void RoutingActivationRequest::setSourceAddress(uint16_t value) + void DoIpRoutingActivationRequest::setSourceAddress(uint16_t value) { getRoutingRequest()->sourceAddress = htobe16(value); } - DoIpActivationTypes RoutingActivationRequest::getActivationType() const + DoIpActivationTypes DoIpRoutingActivationRequest::getActivationType() const { return getRoutingRequest()->activationType; } - void RoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) + void DoIpRoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) { getRoutingRequest()->activationType = activationType; } - std::array RoutingActivationRequest::getReservedIso() const + std::array DoIpRoutingActivationRequest::getReservedIso() const { return getRoutingRequest()->reservedIso; } - void RoutingActivationRequest::setReservedIso(const std::array& reservedIso) + void DoIpRoutingActivationRequest::setReservedIso(const std::array& reservedIso) { getRoutingRequest()->reservedIso = reservedIso; } - bool RoutingActivationRequest::hasReservedOem() const + bool DoIpRoutingActivationRequest::hasReservedOem() const { return _hasReservedOem; } - const uint8_t* RoutingActivationRequest::getReservedOem() const + const uint8_t* DoIpRoutingActivationRequest::getReservedOem() const { return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; } - void RoutingActivationRequest::setReservedOem(const std::array& reservedOem) + void DoIpRoutingActivationRequest::setReservedOem(const std::array& reservedOem) { if (!_hasReservedOem) { @@ -419,20 +426,20 @@ namespace pcpp _hasReservedOem = true; } - void RoutingActivationRequest::clearReservedOem() + void DoIpRoutingActivationRequest::clearReservedOem() { if (m_DataLen == OPT_LEN) { shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; - PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); + PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } else if (m_DataLen == FIXED_LEN) { PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); } } - std::string RoutingActivationRequest::getSummary() const + std::string DoIpRoutingActivationRequest::getSummary() const { std::ostringstream oss; DoIpActivationTypes type = getActivationType(); @@ -455,21 +462,21 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~| - // RoutingActivationResponse| - //~~~~~~~~~~~~~~~~~~~~~~~~~~| - RoutingActivationResponse::RoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, - Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpRoutingActivationResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpRoutingActivationResponse::DoIpRoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < FIXED_LEN || dataLen > OPT_LEN) { - throw std::runtime_error("RoutingActivationResponse: Invalid payload length!"); + throw std::runtime_error("DoIpRoutingActivationResponse: Invalid payload length!"); } if (dataLen > FIXED_LEN && dataLen < OPT_LEN) { - throw std::runtime_error("RoutingActivationResponse: invalid OEM field length"); + throw std::runtime_error("DoIpRoutingActivationResponse: invalid OEM field length"); } // Optional OEM part @@ -484,8 +491,9 @@ namespace pcpp } } - RoutingActivationResponse::RoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, - DoIpRoutingResponseCodes responseCode) + DoIpRoutingActivationResponse::DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, + uint16_t sourceAddress, + DoIpRoutingResponseCodes responseCode) : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); @@ -498,57 +506,57 @@ namespace pcpp payload->reservedIso.fill(0); } - uint16_t RoutingActivationResponse::getLogicalAddressExternalTester() const + uint16_t DoIpRoutingActivationResponse::getLogicalAddressExternalTester() const { return htobe16(getRoutingResponse()->logicalAddressExternalTester); } - void RoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) + void DoIpRoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) { getRoutingResponse()->logicalAddressExternalTester = htobe16(addr); } - uint16_t RoutingActivationResponse::getSourceAddress() const + uint16_t DoIpRoutingActivationResponse::getSourceAddress() const { return htobe16(getRoutingResponse()->sourceAddress); } - void RoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) + void DoIpRoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) { getRoutingResponse()->sourceAddress = htobe16(sourceAddress); } - DoIpRoutingResponseCodes RoutingActivationResponse::getResponseCode() const + DoIpRoutingResponseCodes DoIpRoutingActivationResponse::getResponseCode() const { return getRoutingResponse()->responseCode; } - void RoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) + void DoIpRoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) { getRoutingResponse()->responseCode = code; } - std::array RoutingActivationResponse::getReservedIso() const + std::array DoIpRoutingActivationResponse::getReservedIso() const { return getRoutingResponse()->reservedIso; } - void RoutingActivationResponse::setReservedIso(const std::array& reservedIso) + void DoIpRoutingActivationResponse::setReservedIso(const std::array& reservedIso) { getRoutingResponse()->reservedIso = reservedIso; } - bool RoutingActivationResponse::hasReservedOem() const + bool DoIpRoutingActivationResponse::hasReservedOem() const { return _hasReservedOem; } - const uint8_t* RoutingActivationResponse::getReservedOem() const + const uint8_t* DoIpRoutingActivationResponse::getReservedOem() const { return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; } - void RoutingActivationResponse::setReservedOem(const std::array& reservedOem) + void DoIpRoutingActivationResponse::setReservedOem(const std::array& reservedOem) { if (!_hasReservedOem) { @@ -559,13 +567,13 @@ namespace pcpp _hasReservedOem = true; } - void RoutingActivationResponse::clearReservedOem() + void DoIpRoutingActivationResponse::clearReservedOem() { if (m_DataLen == OPT_LEN) { shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); _hasReservedOem = false; - PCPP_LOG_INFO("Reserved OEM field has been removed successfully!"); + PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } if (m_DataLen == FIXED_LEN) { @@ -573,7 +581,7 @@ namespace pcpp } } - std::string RoutingActivationResponse::getSummary() const + std::string DoIpRoutingActivationResponse::getSummary() const { std::ostringstream ss; DoIpRoutingResponseCodes code = getResponseCode(); @@ -592,39 +600,39 @@ namespace pcpp return ss.str(); } - //~~~~~~~~~~~~~~~~~~~| - // GenericHeaderNack | - //~~~~~~~~~~~~~~~~~~~| - GenericHeaderNack::GenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~| + // DoIpGenericHeaderNack| + //~~~~~~~~~~~~~~~~~~~~~~| + DoIpGenericHeaderNack::DoIpGenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen != FIXED_LEN) - throw std::runtime_error("GenericHeaderNack: Invalid payload length!"); + throw std::runtime_error("DoIpGenericHeaderNack: Invalid payload length!"); } - GenericHeaderNack::GenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) + DoIpGenericHeaderNack::DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), NACK_CODE_LEN); extendLayer(NACK_CODE_OFFSET, NACK_CODE_LEN); setNackCode(nackCode); } - DoIpGenericHeaderNackCodes GenericHeaderNack::getNackCode() const + DoIpGenericHeaderNackCodes DoIpGenericHeaderNack::getNackCode() const { return static_cast(*(m_Data + NACK_CODE_OFFSET)); } - void GenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) + void DoIpGenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) { *(m_Data + NACK_CODE_OFFSET) = static_cast(nackCode); } - void GenericHeaderNack::setNackCode(uint8_t nackCode) + void DoIpGenericHeaderNack::setNackCode(uint8_t nackCode) { *(m_Data + NACK_CODE_OFFSET) = nackCode; } - std::string GenericHeaderNack::getSummary() const + std::string DoIpGenericHeaderNack::getSummary() const { std::ostringstream ss; DoIpGenericHeaderNackCodes nackCode = getNackCode(); @@ -644,32 +652,33 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| // VehicleIdentificationRequestEID | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, - Packet* packet) + DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen != FIXED_LEN) throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); } - VehicleIdentificationRequestEID::VehicleIdentificationRequestEID(const std::array& eid) + DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID( + const std::array& eid) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); extendLayer(EID_OFFSET, DOIP_EID_LEN); setEID(eid); } - std::array VehicleIdentificationRequestEID::getEID() const + std::array DoIpVehicleIdentificationRequestEID::getEID() const { return *reinterpret_cast*>(m_Data + EID_OFFSET); } - void VehicleIdentificationRequestEID::setEID(const std::array& eid) + void DoIpVehicleIdentificationRequestEID::setEID(const std::array& eid) { memcpy(m_Data + EID_OFFSET, &eid, DOIP_EID_LEN); } - std::string VehicleIdentificationRequestEID::getSummary() const + std::string DoIpVehicleIdentificationRequestEID::getSummary() const { std::ostringstream oss; oss << "EID: " << pcpp::byteArrayToHexString(getEID().data(), DOIP_EID_LEN) << "\n"; @@ -679,42 +688,43 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| // VehicleIdentificationRequestVIN | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, - Packet* packet) + DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen != FIXED_LEN) throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length!"); } - VehicleIdentificationRequestVIN::VehicleIdentificationRequestVIN(const std::array& vin) + DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN( + const std::array& vin) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); extendLayer(VIN_OFFSET, DOIP_VIN_LEN); setVIN(vin); } - std::array VehicleIdentificationRequestVIN::getVIN() const + std::array DoIpVehicleIdentificationRequestVIN::getVIN() const { return *reinterpret_cast*>(m_Data + VIN_OFFSET); } - void VehicleIdentificationRequestVIN::setVIN(const std::array& vin) + void DoIpVehicleIdentificationRequestVIN::setVIN(const std::array& vin) { memcpy(m_Data + VIN_OFFSET, &vin, DOIP_VIN_LEN); } - std::string VehicleIdentificationRequestVIN::getSummary() const + std::string DoIpVehicleIdentificationRequestVIN::getSummary() const { std::ostringstream oss; oss << "VIN: " << std::string(reinterpret_cast(getVIN().data()), DOIP_VIN_LEN) << "\n"; return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~| - // VehicleAnnouncement | - //~~~~~~~~~~~~~~~~~~~~~| - VehicleAnnouncement::VehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleAnnouncement| + //~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpVehicleAnnouncement::DoIpVehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < FIXED_LEN || dataLen > OPT_LEN) @@ -731,9 +741,11 @@ namespace pcpp } } - VehicleAnnouncement::VehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, - const std::array& eid, - const std::array& gid, DoIpActionCodes actionCode) + DoIpVehicleAnnouncement::DoIpVehicleAnnouncement(const std::array& vin, + uint16_t logicalAddress, + const std::array& eid, + const std::array& gid, + DoIpActionCodes actionCode) : _hasSyncStatus(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); @@ -745,71 +757,71 @@ namespace pcpp setGID(gid); setFurtherActionRequired(actionCode); } - std::array VehicleAnnouncement::getVIN() const + std::array DoIpVehicleAnnouncement::getVIN() const { return getVehicleAnnouncement()->vin; } - uint16_t VehicleAnnouncement::getLogicalAddress() const + uint16_t DoIpVehicleAnnouncement::getLogicalAddress() const { return htobe16(getVehicleAnnouncement()->logicalAddress); } - std::array VehicleAnnouncement::getEID() const + std::array DoIpVehicleAnnouncement::getEID() const { return getVehicleAnnouncement()->eid; } - std::array VehicleAnnouncement::getGID() const + std::array DoIpVehicleAnnouncement::getGID() const { return getVehicleAnnouncement()->gid; } - DoIpActionCodes VehicleAnnouncement::getFurtherActionRequired() const + DoIpActionCodes DoIpVehicleAnnouncement::getFurtherActionRequired() const { return getVehicleAnnouncement()->actionCode; } - const DoIpSyncStatus* VehicleAnnouncement::getSyncStatus() const + const DoIpSyncStatus* DoIpVehicleAnnouncement::getSyncStatus() const { return _hasSyncStatus ? reinterpret_cast(m_Data + SYNC_STATUS_OFFSET) : nullptr; } - void VehicleAnnouncement::clearSyncStatus() + void DoIpVehicleAnnouncement::clearSyncStatus() { if (m_DataLen == OPT_LEN) { shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); _hasSyncStatus = false; - PCPP_LOG_INFO("Sync status has been removed successfully!"); + PCPP_LOG_DEBUG("Sync status has been removed successfully!"); } if (m_DataLen == FIXED_LEN) { PCPP_LOG_DEBUG("doip packet has no syncStatus!"); } } - void VehicleAnnouncement::setVIN(const std::array& vin) + void DoIpVehicleAnnouncement::setVIN(const std::array& vin) { getVehicleAnnouncement()->vin = vin; } - void VehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) + void DoIpVehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) { getVehicleAnnouncement()->logicalAddress = be16toh(logicalAddress); } - void VehicleAnnouncement::setEID(const std::array& eid) + void DoIpVehicleAnnouncement::setEID(const std::array& eid) { getVehicleAnnouncement()->eid = eid; } - void VehicleAnnouncement::setGID(const std::array& gid) + void DoIpVehicleAnnouncement::setGID(const std::array& gid) { getVehicleAnnouncement()->gid = gid; } - void VehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) + void DoIpVehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) { getVehicleAnnouncement()->actionCode = action; } - void VehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) + void DoIpVehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) { if (!_hasSyncStatus) { @@ -820,12 +832,12 @@ namespace pcpp _hasSyncStatus = true; } - bool VehicleAnnouncement::hasSyncStatus() const + bool DoIpVehicleAnnouncement::hasSyncStatus() const { return _hasSyncStatus; } - std::string VehicleAnnouncement::getSummary() const + std::string DoIpVehicleAnnouncement::getSummary() const { std::ostringstream oss; DoIpActionCodes actionCode = getFurtherActionRequired(); @@ -860,48 +872,48 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~| - // AliveCheckResponse | - //~~~~~~~~~~~~~~~~~~~~| - AliveCheckResponse::AliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpAliveCheckResponse| + //~~~~~~~~~~~~~~~~~~~~~~~| + DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN) throw std::runtime_error("AliveCheckResponse: insufficient payload length"); } - AliveCheckResponse::AliveCheckResponse(uint16_t sourceAddress) + DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint16_t sourceAddress) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_SOURCE_ADDRESS_LEN); extendLayer(DOIP_HEADER_LEN, DOIP_SOURCE_ADDRESS_LEN); setSourceAddress(sourceAddress); } - uint16_t AliveCheckResponse::getSourceAddress() const + uint16_t DoIpAliveCheckResponse::getSourceAddress() const { uint16_t _sourceAddress; memcpy(&_sourceAddress, (m_Data + SOURCE_ADDRESS_OFFSET), DOIP_SOURCE_ADDRESS_LEN); return htobe16(_sourceAddress); } - void AliveCheckResponse::setSourceAddress(uint16_t sourceAddress) + void DoIpAliveCheckResponse::setSourceAddress(uint16_t sourceAddress) { uint16_t _sourceAddress = htobe16(sourceAddress); memcpy((m_Data + SOURCE_ADDRESS_OFFSET), &_sourceAddress, DOIP_SOURCE_ADDRESS_LEN); } - std::string AliveCheckResponse::getSummary() const + std::string DoIpAliveCheckResponse::getSummary() const { std::ostringstream oss; oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticPowerModeResponse| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DiagnosticPowerModeResponse::DiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, - Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticPowerModeResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { constexpr size_t payloadLen = DOIP_HEADER_LEN + sizeof(_powerModeCode); @@ -912,7 +924,8 @@ namespace pcpp _powerModeCode = static_cast(*payloadPtr); } - DiagnosticPowerModeResponse::DiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) : _powerModeCode(code) + DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) + : _powerModeCode(code) { const size_t payloadLen = sizeof(_powerModeCode); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); @@ -920,19 +933,19 @@ namespace pcpp setPowerModeCode(code); } - DoIpDiagnosticPowerModeCodes DiagnosticPowerModeResponse::getPowerModeCode() const + DoIpDiagnosticPowerModeCodes DoIpDiagnosticPowerModeResponse::getPowerModeCode() const { return _powerModeCode; } - void DiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) + void DoIpDiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) { _powerModeCode = code; uint8_t* dataPtr = getDataPtr(DOIP_HEADER_LEN); *dataPtr = static_cast(code); } - std::string DiagnosticPowerModeResponse::getSummary() const + std::string DoIpDiagnosticPowerModeResponse::getSummary() const { std::ostringstream oss; auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(_powerModeCode); @@ -947,10 +960,10 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~| - // EntityStatusResponse| - //~~~~~~~~~~~~~~~~~~~~~| - EntityStatusResponse::EntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpEntityStatusResponse| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpEntityStatusResponse::DoIpEntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < FIXED_LEN || dataLen > OPT_LEN) @@ -969,13 +982,13 @@ namespace pcpp } else { - PCPP_LOG_INFO("MaxDataSize field is empty !"); + PCPP_LOG_DEBUG("MaxDataSize field is empty !"); _hasMaxDataSize = false; } } - EntityStatusResponse::EntityStatusResponse(DoIpEntityStatusResponse nodeType, uint8_t maxConcurrentSockets, - uint8_t currentlyOpenSockets) + DoIpEntityStatusResponse::DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, + uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) : _hasMaxDataSize(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); @@ -985,54 +998,54 @@ namespace pcpp setMaxConcurrentSockets(maxConcurrentSockets); setCurrentlyOpenSockets(currentlyOpenSockets); } - DoIpEntityStatusResponse EntityStatusResponse::getNodeType() const + DoIpEntityStatusResponseCode DoIpEntityStatusResponse::getNodeType() const { return getEntityStatusResponsePtr()->nodeType; } - uint8_t EntityStatusResponse::getMaxConcurrentSockets() const + uint8_t DoIpEntityStatusResponse::getMaxConcurrentSockets() const { return getEntityStatusResponsePtr()->maxConcurrentSockets; } - uint8_t EntityStatusResponse::getCurrentlyOpenSockets() const + uint8_t DoIpEntityStatusResponse::getCurrentlyOpenSockets() const { return getEntityStatusResponsePtr()->currentlyOpenSockets; } - const uint8_t* EntityStatusResponse::getMaxDataSize() const + const uint8_t* DoIpEntityStatusResponse::getMaxDataSize() const { return _hasMaxDataSize ? (m_Data + MAX_DATA_SIZE_OFFSET) : nullptr; } - void EntityStatusResponse::setNodeType(DoIpEntityStatusResponse nodeType) + void DoIpEntityStatusResponse::setNodeType(DoIpEntityStatusResponseCode nodeType) { getEntityStatusResponsePtr()->nodeType = nodeType; } - bool EntityStatusResponse::hasMaxDataSize() const + bool DoIpEntityStatusResponse::hasMaxDataSize() const { return _hasMaxDataSize; } - void EntityStatusResponse::clearMaxDataSize() + void DoIpEntityStatusResponse::clearMaxDataSize() { if (m_DataLen == OPT_LEN && _hasMaxDataSize) { shortenLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); _hasMaxDataSize = false; - PCPP_LOG_INFO("MaxDataSize has been removed successfully!"); + PCPP_LOG_DEBUG("MaxDataSize has been removed successfully!"); } else { PCPP_LOG_DEBUG("doip packet has no MaxDataSize field!"); } } - void EntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) + void DoIpEntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) { getEntityStatusResponsePtr()->maxConcurrentSockets = sockets; } - void EntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) + void DoIpEntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) { getEntityStatusResponsePtr()->currentlyOpenSockets = sockets; } - void EntityStatusResponse::setMaxDataSize(const std::array& data) + void DoIpEntityStatusResponse::setMaxDataSize(const std::array& data) { if (!_hasMaxDataSize) { @@ -1043,10 +1056,10 @@ namespace pcpp _hasMaxDataSize = true; } - std::string EntityStatusResponse::getSummary() const + std::string DoIpEntityStatusResponse::getSummary() const { std::ostringstream oos; - DoIpEntityStatusResponse nodeType = getNodeType(); + DoIpEntityStatusResponseCode nodeType = getNodeType(); auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) { @@ -1067,47 +1080,47 @@ namespace pcpp } //~~~~~~~~~~~~~~~| - // DiagnosticBase| + // DoIpDiagnosticBase| //~~~~~~~~~~~~~~~| - DiagnosticBase::DiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + DoIpDiagnosticBase::DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) { if (dataLen < FIX_LEN) throw std::runtime_error("DiagnosticBase: insufficient payload length!"); } - uint16_t DiagnosticBase::getSourceAddress() const + uint16_t DoIpDiagnosticBase::getSourceAddress() const { return htobe16(getCommonDiagnosticHeader()->sourceAddress); } - uint16_t DiagnosticBase::getTargetAddress() const + uint16_t DoIpDiagnosticBase::getTargetAddress() const { return htobe16(getCommonDiagnosticHeader()->targetAddress); } - void DiagnosticBase::setSourceAddress(uint16_t sourceAddress) + void DoIpDiagnosticBase::setSourceAddress(uint16_t sourceAddress) { getCommonDiagnosticHeader()->sourceAddress = htobe16(sourceAddress); } - void DiagnosticBase::setTargetAddress(uint16_t targetAddress) + void DoIpDiagnosticBase::setTargetAddress(uint16_t targetAddress) { getCommonDiagnosticHeader()->targetAddress = htobe16(targetAddress); } //~~~~~~~~~~~~~~~~~~| - // DiagnosticMessage| + // DoIpDiagnosticMessage| //~~~~~~~~~~~~~~~~~~| - DiagnosticMessage::DiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DiagnosticBase(data, dataLen, prevLayer, packet) + DoIpDiagnosticMessage::DoIpDiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpDiagnosticBase(data, dataLen, prevLayer, packet) { if (dataLen < MIN_LEN) throw std::runtime_error("DiagnosticBase: insufficient payload length!"); } - DiagnosticMessage::DiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, - const std::vector& diagData) + DoIpDiagnosticMessage::DoIpDiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, + const std::vector& diagData) { size_t payloadLen = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + diagData.size(); setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); @@ -1117,13 +1130,13 @@ namespace pcpp setDiagnosticData(diagData); } - const std::vector DiagnosticMessage::getDiagnosticData() const + const std::vector DoIpDiagnosticMessage::getDiagnosticData() const { const uint8_t* diagDataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; return std::vector(diagDataPtr, diagDataPtr + (m_DataLen - DIAGNOSTIC_DATA_OFFSET)); } - void DiagnosticMessage::setDiagnosticData(const std::vector& data) + void DoIpDiagnosticMessage::setDiagnosticData(const std::vector& data) { const size_t newPayloadlLength = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + data.size(); const size_t currentDiagnosticDataLen = m_DataLen - DIAGNOSTIC_DATA_OFFSET; @@ -1139,7 +1152,7 @@ namespace pcpp memcpy(dataPtr, data.data(), data.size()); } - std::string DiagnosticMessage::getSummary() const + std::string DoIpDiagnosticMessage::getSummary() const { std::ostringstream oss; oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; @@ -1147,12 +1160,12 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticResponseMessageBase| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DiagnosticResponseMessageBase::DiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, - Packet* packet) - : DiagnosticBase(data, dataLen, prevLayer, packet), _hasPreviousMessage(false) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticResponseMessageBase| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpDiagnosticResponseMessageBase::DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) + : DoIpDiagnosticBase(data, dataLen, prevLayer, packet), _hasPreviousMessage(false) { if (dataLen < PREVIOUS_MSG_OFFSET) throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); @@ -1164,13 +1177,13 @@ namespace pcpp } else { - PCPP_LOG_INFO("PreviousMessage field is empty!"); + PCPP_LOG_DEBUG("PreviousMessage field is empty!"); _hasPreviousMessage = false; } } - DiagnosticResponseMessageBase::DiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, - DoIpPayloadTypes type) + DoIpDiagnosticResponseMessageBase::DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, + DoIpPayloadTypes type) : _hasPreviousMessage(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); @@ -1179,12 +1192,12 @@ namespace pcpp setTargetAddress(targetAddress); } - uint8_t DiagnosticResponseMessageBase::getResponseCode() const + uint8_t DoIpDiagnosticResponseMessageBase::getResponseCode() const { return static_cast(*(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET)); } - const std::vector DiagnosticResponseMessageBase::getPreviousMessage() const + const std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const { if (_hasPreviousMessage) { @@ -1197,17 +1210,17 @@ namespace pcpp } } - void DiagnosticResponseMessageBase::setResponseCode(uint8_t code) + void DoIpDiagnosticResponseMessageBase::setResponseCode(uint8_t code) { *(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET) = static_cast(code); } - bool DiagnosticResponseMessageBase::hasPreviousMessage() const + bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const { return _hasPreviousMessage; } - void DiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) + void DoIpDiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) { size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; @@ -1223,13 +1236,13 @@ namespace pcpp _hasPreviousMessage = true; } - void DiagnosticResponseMessageBase::clearPreviousMessage() + void DoIpDiagnosticResponseMessageBase::clearPreviousMessage() { if (_hasPreviousMessage) { shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); _hasPreviousMessage = false; - PCPP_LOG_INFO("PreviousMessage has been removed successfully!"); + PCPP_LOG_DEBUG("PreviousMessage has been removed successfully!"); } else { @@ -1237,31 +1250,31 @@ namespace pcpp } } - //~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticAckMessage| - //~~~~~~~~~~~~~~~~~~~~~| - DiagnosticAckMessage::DiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticAckMessage| + //~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpDiagnosticAckMessage::DoIpDiagnosticAckMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : DoIpDiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) {} - DiagnosticAckMessage::DiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, - DoIpDiagnosticAckCodes ackCode) - : DiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) + DoIpDiagnosticAckMessage::DoIpDiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticAckCodes ackCode) + : DoIpDiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) { setAckCode(ackCode); } - DoIpDiagnosticAckCodes DiagnosticAckMessage::getAckCode() const + DoIpDiagnosticAckCodes DoIpDiagnosticAckMessage::getAckCode() const { return static_cast(getResponseCode()); } - void DiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) + void DoIpDiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) { setResponseCode(static_cast(code)); } // Summary method. - std::string DiagnosticAckMessage::getSummary() const + std::string DoIpDiagnosticAckMessage::getSummary() const { std::ostringstream oss; DoIpDiagnosticAckCodes ackCode = getAckCode(); @@ -1284,31 +1297,32 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticNackMessage| - //~~~~~~~~~~~~~~~~~~~~~~| - DiagnosticNackMessage::DiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticNackMessage| + //~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpDiagnosticNackMessage::DoIpDiagnosticNackMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : DoIpDiagnosticResponseMessageBase(data, dataLen, prevLayer, packet) {} - DiagnosticNackMessage::DiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, - DoIpDiagnosticMessageNackCodes nackCode) - : DiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) + DoIpDiagnosticNackMessage::DoIpDiagnosticNackMessage(uint16_t sourceAddress, uint16_t targetAddress, + DoIpDiagnosticMessageNackCodes nackCode) + : DoIpDiagnosticResponseMessageBase(sourceAddress, targetAddress, getPayloadType()) { setNackCode(nackCode); } - DoIpDiagnosticMessageNackCodes DiagnosticNackMessage::getNackCode() const + DoIpDiagnosticMessageNackCodes DoIpDiagnosticNackMessage::getNackCode() const { return static_cast(getResponseCode()); } - void DiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) + void DoIpDiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) { setResponseCode(static_cast(code)); } - std::string DiagnosticNackMessage::getSummary() const + std::string DoIpDiagnosticNackMessage::getSummary() const { std::ostringstream oss; DoIpDiagnosticMessageNackCodes nackCode = getNackCode(); @@ -1333,34 +1347,34 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~| - // AliveCheckRequest| - //~~~~~~~~~~~~~~~~~~| - AliveCheckRequest::AliveCheckRequest() + //~~~~~~~~~~~~~~~~~~~~~~| + // DoIpAliveCheckRequest| + //~~~~~~~~~~~~~~~~~~~~~~| + DoIpAliveCheckRequest::DoIpAliveCheckRequest() { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequest| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - VehicleIdentificationRequest::VehicleIdentificationRequest() + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpVehicleIdentificationRequest::DoIpVehicleIdentificationRequest() { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DiagnosticPowerModeRequest| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DiagnosticPowerModeRequest::DiagnosticPowerModeRequest() + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpDiagnosticPowerModeRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpDiagnosticPowerModeRequest::DoIpDiagnosticPowerModeRequest() { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } - //~~~~~~~~~~~~~~~~~~~~| - // EntityStatusRequest| - //~~~~~~~~~~~~~~~~~~~~| - EntityStatusRequest::EntityStatusRequest() + //~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpEntityStatusRequest| + //~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpEntityStatusRequest::DoIpEntityStatusRequest() { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 425e2a9d36..23228c9afd 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -370,7 +370,9 @@ namespace pcpp if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(payload, payloadLen))) { - setNextLayer(DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet)); + m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); + if (!m_NextLayer) + constructNextLayer(payload, payloadLen, m_Packet); } else if (HttpMessage::isHttpPort(portDst) && HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 5a2b4ba271..5a2a12ab7c 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -133,7 +133,12 @@ namespace pcpp m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(udpData, udpDataLen))) + { m_NextLayer = DoIpLayer::parseDoIpLayer(udpData, udpDataLen, this, m_Packet); + if (!m_NextLayer) + constructNextLayer(udpData, udpDataLen, m_Packet); + } + else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && NtpLayer::isDataValid(udpData, udpDataLen)) m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 8fb6a96812..8dda74f51f 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -34,7 +34,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); - auto* doipLayer = RoutingActivationRequest.getLayerOfType(); + auto* doipLayer = RoutingActivationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -79,7 +79,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) std::array isoReserved{ 0x1, 0x2, 0x3, 0x4 }; std::array oemField{ 0x5, 0x5, 0x5, 0x5 }; - pcpp::RoutingActivationRequest doipLayer(0x00, pcpp::DoIpActivationTypes::WWH_OBD); + pcpp::DoIpRoutingActivationRequest doipLayer(0x00, pcpp::DoIpActivationTypes::WWH_OBD); doipLayer.setSourceAddress(0x0e80); doipLayer.setActivationType(pcpp::DoIpActivationTypes::DEFAULT); @@ -145,7 +145,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0xa0a5)); - auto* doipLayer = RoutingActivationResponse.getLayerOfType(); + auto* doipLayer = RoutingActivationResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -185,7 +185,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x6, 0x0, 0x0, 0x0, 0xd, 0xe, 0x80, 0x40, 0x10, 0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x5 }; - pcpp::RoutingActivationResponse doipLayer(0x0, 0x0, pcpp::DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS); + pcpp::DoIpRoutingActivationResponse doipLayer(0x0, 0x0, pcpp::DoIpRoutingResponseCodes::WRONG_SOURCE_ADDRESS); doipLayer.setLogicalAddressExternalTester(0x0e80); doipLayer.setSourceAddress(0x4010); doipLayer.setResponseCode(pcpp::DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED); @@ -237,7 +237,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = GenericHeaderNack.getLayerOfType(); + auto* doipLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -266,7 +266,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1 }; - pcpp::GenericHeaderNack doipLayer(pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE); + pcpp::DoIpGenericHeaderNack doipLayer(pcpp::DoIpGenericHeaderNackCodes::UNKNOWN_PAYLOAD_TYPE); PTF_ASSERT_TRUE(doIpPacket.addLayer(&doipLayer)); doIpPacket.computeCalculateFields(); @@ -304,7 +304,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); + auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "EID: 4241554e4545\n"); @@ -339,7 +339,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; - pcpp::VehicleIdentificationRequestEID withEID(eid); + pcpp::DoIpVehicleIdentificationRequestEID withEID(eid); withEID.setEID(eid); PTF_ASSERT_TRUE(doIpPacket.addLayer(&withEID)); @@ -378,7 +378,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -416,7 +416,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - pcpp::VehicleIdentificationRequestVIN withVin(vin); + pcpp::DoIpVehicleIdentificationRequestVIN withVin(vin); withVin.setVIN(vin); PTF_ASSERT_TRUE(doIpPacket.addLayer(&withVin)); @@ -461,7 +461,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); // DOIP fields for vehicle identification request - auto* doipLayer = VehicleAnnouncement.getLayerOfType(); + auto* doipLayer = VehicleAnnouncement.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL( @@ -507,13 +507,13 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - pcpp::VehicleAnnouncement ann(vin, 0x4010, eid, gid, pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED); + pcpp::DoIpVehicleAnnouncement ann(vin, 0x4010, eid, gid, pcpp::DoIpActionCodes::NO_FURTHER_ACTION_REQUIRED); ann.setSyncStatus(pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED); PTF_ASSERT_TRUE(doIpPacket.addLayer(&ann)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 83); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -558,7 +558,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -587,7 +587,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0 }; - pcpp::VehicleIdentificationRequest req; + pcpp::DoIpVehicleIdentificationRequest req; PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); @@ -621,7 +621,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = AliveCheckResponse.getLayerOfType(); + auto* doipLayer = AliveCheckResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x0\n"); @@ -650,14 +650,14 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x8, 0x0, 0x0, 0x0, 0x2, 0x10, 0x20 }; - pcpp::AliveCheckResponse aliveCheckResp(0x1020); + pcpp::DoIpAliveCheckResponse aliveCheckResp(0x1020); PTF_ASSERT_TRUE(doIpPacket.addLayer(&aliveCheckResp)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 52); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -689,7 +689,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = PowerModeResponse.getLayerOfType(); + auto* doipLayer = PowerModeResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: not ready (0x0)\n"); @@ -719,14 +719,14 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x4, 0x0, 0x0, 0x0, 0x1, 0x1 }; - pcpp::DiagnosticPowerModeResponse data(pcpp::DoIpDiagnosticPowerModeCodes::READY); + pcpp::DoIpDiagnosticPowerModeResponse data(pcpp::DoIpDiagnosticPowerModeCodes::READY); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -759,7 +759,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = EntityStatusResponse.getLayerOfType(); + auto* doipLayer = EntityStatusResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL( @@ -772,7 +772,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 7); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); - PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponse::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponseCode::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 1); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 0); const std::array& maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; @@ -795,13 +795,13 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x5, 0x2, 0xff, 0xff, 0xff, 0xff }; - pcpp::EntityStatusResponse data(pcpp::DoIpEntityStatusResponse::GATEWAY, 0, 0); + pcpp::DoIpEntityStatusResponse data(pcpp::DoIpEntityStatusResponseCode::GATEWAY, 0, 0); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); - doipLayer->setNodeType(pcpp::DoIpEntityStatusResponse::GATEWAY); + doipLayer->setNodeType(pcpp::DoIpEntityStatusResponseCode::GATEWAY); doipLayer->setMaxConcurrentSockets(5); doipLayer->setCurrentlyOpenSockets(2); const std::array& maxDataSize{ 0xff, 0xff, 0xff, 0xff }; @@ -817,7 +817,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadLength(), 7); PTF_ASSERT_EQUAL(_doipLayer2->toString(), "DoIP Layer, DOIP entity status response (0x4002)"); - PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponse::GATEWAY, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponseCode::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 5); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 2); PTF_ASSERT_TRUE(doipLayer->hasMaxDataSize()); @@ -845,7 +845,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); - auto* doipLayer = DiagnosticMessagePacket.getLayerOfType(); + auto* doipLayer = DiagnosticMessagePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0xe, 0x80, 0x40, 0x10, 0x10, 0x3 }; @@ -887,7 +887,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x1, 0x0, 0x0, 0x0, 0x6, 0x20, 0x30, 0x40, 0x40, 0x10, 0x02 }; const std::vector& diagnosticData{ 0x10, 0x02 }; const std::vector& diagnosticData2{ 0x10, 0x02, 0x40, 0x50 }; - pcpp::DiagnosticMessage data(0x2030, 0x4040, diagnosticData); + pcpp::DoIpDiagnosticMessage data(0x2030, 0x4040, diagnosticData); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); @@ -898,7 +898,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 68); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (68 - 14), bytes, 14); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x2030); PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4040); @@ -937,7 +937,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - auto* doipLayer = DiagnosticAckMessage.getLayerOfType(); + auto* doipLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), @@ -974,14 +974,14 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x80, 0x2, 0x0, 0x0, 0x0, 0x5, 0x40, 0x10, 0xe, 0x80, 0x0 }; - pcpp::DiagnosticAckMessage data(0x4010, 0xe80, pcpp::DoIpDiagnosticAckCodes::ACK); + pcpp::DoIpDiagnosticAckMessage data(0x4010, 0xe80, pcpp::DoIpDiagnosticAckCodes::ACK); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); - auto* doipLayer = doIpPacket.getLayerOfType(); + auto* doipLayer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); @@ -1034,7 +1034,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) PTF_ASSERT_NOT_NULL(tcpLayer); PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); - auto* nackLayer = diagnosticNackPacket.getLayerOfType(); + auto* nackLayer = diagnosticNackPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(nackLayer); PTF_ASSERT_EQUAL(nackLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -1073,7 +1073,8 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) doIpPacket.computeCalculateFields(); // Create NACK message with no previous message - pcpp::DiagnosticNackMessage nackMsg(0x4010, 0x0e80, pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS); + pcpp::DoIpDiagnosticNackMessage nackMsg(0x4010, 0x0e80, + pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS); PTF_ASSERT_TRUE(doIpPacket.addLayer(&nackMsg)); doIpPacket.computeCalculateFields(); @@ -1082,7 +1083,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); - auto* layer = doIpPacket.getLayerOfType(); + auto* layer = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(layer->getSourceAddress(), 0x4010); PTF_ASSERT_EQUAL(layer->getTargetAddress(), 0x0e80); PTF_ASSERT_EQUAL(layer->getNackCode(), pcpp::DoIpDiagnosticMessageNackCodes::INVALID_SOURCE_ADDRESS, enumclass); @@ -1130,7 +1131,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = PowerModeRequest.getLayerOfType(); + auto* doipLayer = PowerModeRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -1157,7 +1158,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x3, 0x0, 0x0, 0x0, 0x0 }; - pcpp::DiagnosticPowerModeRequest req; + pcpp::DoIpDiagnosticPowerModeRequest req; PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); @@ -1194,7 +1195,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4988)); - auto* doipLayer = EntityStatusRequest.getLayerOfType(); + auto* doipLayer = EntityStatusRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -1221,7 +1222,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x1, 0x0, 0x0, 0x0, 0x0 }; - pcpp::EntityStatusRequest req; + pcpp::DoIpEntityStatusRequest req; PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); @@ -1256,7 +1257,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = AliveCheckRequest.getLayerOfType(); + auto* doipLayer = AliveCheckRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -1283,14 +1284,14 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) doIpPacket.computeCalculateFields(); unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0 }; - pcpp::AliveCheckRequest req; + pcpp::DoIpAliveCheckRequest req; PTF_ASSERT_TRUE(doIpPacket.addLayer(&req)); doIpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 50); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); - auto* _doipLayer2 = doIpPacket.getLayerOfType(); + auto* _doipLayer2 = doIpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); @@ -1318,7 +1319,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); + auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::DefaultVersion, enumclass); From d6c116b86b4cfb5506fd8d788049f7b01dd88cec Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 6 May 2025 08:39:26 -0400 Subject: [PATCH 36/43] fix review comments --- Packet++/header/DoIpLayer.h | 371 ++++++++++-------- Packet++/src/DoIpLayer.cpp | 519 +++++++++---------------- Tests/Packet++Test/Tests/DoIpTests.cpp | 40 +- 3 files changed, 413 insertions(+), 517 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 0971134d55..12c3c3dce7 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -31,7 +31,7 @@ namespace pcpp namespace DoIpConstants { - // @brief Length of doip header + /// @brief Length of doip header static constexpr size_t DOIP_HEADER_LEN = sizeof(doiphdr); /// @brief Length of the Equiepement Identifier (EID) field. @@ -70,7 +70,7 @@ namespace pcpp /// Central security routing activation type. /// Used for secure communications involving a central security system. - CENTRAL_SECURITY = 0xE0U + CENTRAL_SECURITY = 0xE0U, }; /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). @@ -509,13 +509,9 @@ namespace pcpp enum class DoIpPorts : uint16_t { - /// UDP Port. - /// The standard port for DoIP communication over UDP. - UDP_PORT = 13400U, - - /// TCP Port. - /// The standard port for DoIP communication over TCP. - TCP_PORT = 13400U, + /// TCP and UDP doip Ports. + /// The standard port for DoIP communication. + TCP_UDP_PORT = 13400U, /// TLS Port. /// The standard port for DoIP communication over a secure TLS connection. @@ -550,8 +546,8 @@ namespace pcpp void setProtocolVersion(DoIpProtocolVersion version); /// Additional setter for raw protocol version (for testing/fuzzing/debugging) - /// @param[in] Rawversion the raw version of DOIP protocol to set - void setProtocolVersion(uint8_t Rawversion); + /// @param[in] rawVersion the raw version of DOIP protocol to set + void setProtocolVersion(uint8_t rawVersion); /// Get the invert version of DOIP protocol /// @return A uint8_t presenting the used protocol invert version (DOIPV) @@ -614,7 +610,7 @@ namespace pcpp static inline bool isPayloadTypeValid(uint16_t type); - static inline bool isProtocolVersionValid(uint8_t version, uint8_t invVersion, DoIpPayloadTypes type); + static inline bool isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type); static inline bool isPayloadLengthValid(uint32_t payloadLength, size_t dataLen); @@ -636,17 +632,13 @@ namespace pcpp inline bool DoIpLayer::isDoIpPort(uint16_t port) { auto portAsEnum = static_cast(port); - return (portAsEnum == DoIpPorts::UDP_PORT || portAsEnum == DoIpPorts::TCP_PORT || - portAsEnum == DoIpPorts::TLS_PORT); + return (portAsEnum == DoIpPorts::TCP_UDP_PORT || portAsEnum == DoIpPorts::TLS_PORT); } inline bool DoIpLayer::isDataValid(uint8_t* data, size_t dataLen) { - if (data == nullptr) - { - PCPP_LOG_DEBUG("Data pointer is null!"); + if (data == nullptr || dataLen < DOIP_HEADER_LEN) return false; - } auto* doipHeader = reinterpret_cast(data); const uint8_t version = doipHeader->protocolVersion; @@ -778,23 +770,6 @@ namespace pcpp /// @param[in] activationType Type of routing activation. DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); -/// @struct routing_activation_request -/// Represents the Routing Activation Request data in DoIP. -/// Routing Activation Response message structure (extends DoIP header). -#pragma pack(push, 1) - struct routing_activation_request : doiphdr - { - /// @brief Source address of the tester. - uint16_t sourceAddress; - - /// @brief Routing activation type. - DoIpActivationTypes activationType; - - /// @brief ISO reserved bytes. - std::array reservedIso; - }; -#pragma pack(pop) - /// @brief Returns the source address. uint16_t getSourceAddress() const; @@ -834,21 +809,31 @@ namespace pcpp return DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST; } - /// @brief Get a pointer to Routing activation request message - /// Notice this points directly to the data, so any change will modify - /// the actual packet data - /// @return A pointer to a routing_activation_request structure containing the data - routing_activation_request* getRoutingRequest() const + /// @brief Checks if the routing activation request data length is valid. + /// @param[in] dataLen The length of the data. + /// @return true if the data is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) { - return reinterpret_cast(m_Data); + return (dataLen == FIXED_LEN || dataLen == OPT_LEN); } private: - bool _hasReservedOem; ///< Whether OEM bytes are set. +#pragma pack(push, 1) + struct routing_activation_request : doiphdr + { + uint16_t sourceAddress; + + uint8_t activationType; + + std::array reservedIso; + }; +#pragma pack(pop) - static constexpr size_t ACTIVATION_TYPE_LEN = 1; - static constexpr size_t FIXED_LEN = - DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + ACTIVATION_TYPE_LEN + DOIP_RESERVED_ISO_LEN; + routing_activation_request* getRoutingRequest() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(routing_activation_request); static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; @@ -878,26 +863,6 @@ namespace pcpp DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode); -/// @struct routing_activation_response -/// Represents the Routing Activation Response data in DoIP. -/// Routing Activation Response message structure (extends DoIP header). -#pragma pack(push, 1) - struct routing_activation_response : doiphdr - { - /// @brief External tester's logical address. - uint16_t logicalAddressExternalTester; - - /// @brief ECU source address. - uint16_t sourceAddress; - - /// @brief Response code. - DoIpRoutingResponseCodes responseCode; - - /// @brief ISO reserved bytes. - std::array reservedIso; - }; -#pragma pack(pop) - /// @brief Gets the logical address of the external tester. uint16_t getLogicalAddressExternalTester() const; @@ -943,22 +908,32 @@ namespace pcpp return DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE; } - /// Get a pointer to Routing activation response message - /// Notice this points directly to the data, so any change will modify - /// the actual packet data - /// @return A pointer to a routing_activation_response structure containing the data - routing_activation_response* getRoutingResponse() const + /// @brief Checks if the routing activation response data length is valid. + /// @param[in] dataLen The length of the data. + /// @return true if the data is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) { - return reinterpret_cast(m_Data); + return (dataLen == FIXED_LEN || dataLen == OPT_LEN); } private: - bool _hasReservedOem; ///< Whether OEM bytes are set. +#pragma pack(push, 1) + struct routing_activation_response : doiphdr + { + uint16_t logicalAddressExternalTester; + + uint16_t sourceAddress; - static constexpr size_t LOGICAL_ADDRESS_LEN = 2; - static constexpr size_t RESPONSE_CODE_LEN = 1; - static constexpr size_t FIXED_LEN = - DOIP_HEADER_LEN + LOGICAL_ADDRESS_LEN + DOIP_SOURCE_ADDRESS_LEN + RESPONSE_CODE_LEN + DOIP_RESERVED_ISO_LEN; + uint8_t responseCode; + + std::array reservedIso; + }; +#pragma pack(pop) + routing_activation_response* getRoutingResponse() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(routing_activation_response); static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; @@ -1002,6 +977,14 @@ namespace pcpp return DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK; } + /// @brief Checks if the NACK data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == FIXED_LEN); + } + private: static constexpr size_t NACK_CODE_OFFSET = DOIP_HEADER_LEN; static constexpr size_t NACK_CODE_LEN = sizeof(uint8_t); @@ -1045,6 +1028,14 @@ namespace pcpp return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID; } + /// @brief Checks if the EID data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == FIXED_LEN); + } + private: static constexpr size_t EID_OFFSET = DOIP_HEADER_LEN; static constexpr size_t FIXED_LEN = EID_OFFSET + DOIP_EID_LEN; @@ -1087,6 +1078,14 @@ namespace pcpp return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN; } + /// @brief Checks if the VIN data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == FIXED_LEN); + } + private: static constexpr size_t VIN_OFFSET = DOIP_HEADER_LEN; static constexpr size_t FIXED_LEN = VIN_OFFSET + DOIP_VIN_LEN; @@ -1121,28 +1120,6 @@ namespace pcpp const std::array& eid, const std::array& gid, DoIpActionCodes actionCode); -/// @struct vehicle_announcement -/// Represents the vehicle announcement data in DoIP. -/// Vehicle announcement message structure (extends DoIP header). -#pragma pack(push, 1) - struct vehicle_announcement : doiphdr - { - /// @brief Vehicle Identification Number. - std::array vin; - - /// @brief Logical address of the vehicle. - uint16_t logicalAddress; - - /// @brief Entity Identifier. - std::array eid; - - /// @brief Group Identifier. - std::array gid; - - /// @brief Further action required code. - DoIpActionCodes actionCode; - }; -#pragma pack(pop) /// @brief Gets the Vehicle Identification Number (VIN). std::array getVIN() const; @@ -1194,28 +1171,38 @@ namespace pcpp return DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE; } - /// Get a pointer to Routing vehicle announcement data - /// Notice this points directly to the data, so any change will modify - /// the actual packet data - /// @return A pointer to a vehicle_announcement structure containing the data - vehicle_announcement* getVehicleAnnouncement() const + /// @brief checks if the vehicle announcement data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) { - return reinterpret_cast(m_Data); + return (dataLen == FIXED_LEN || dataLen == OPT_LEN); } private: - bool _hasSyncStatus; +#pragma pack(push, 1) + struct vehicle_announcement : doiphdr + { + std::array vin; - static constexpr size_t VIN_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t LOGICAL_ADDRESS_LEN = 2; - static constexpr size_t ACTION_CODE_LEN = 1; - static constexpr size_t FIXED_LEN = - VIN_OFFSET + DOIP_VIN_LEN + LOGICAL_ADDRESS_LEN + DOIP_EID_LEN + DOIP_GID_LEN + ACTION_CODE_LEN; + uint16_t logicalAddress; + + std::array eid; + + std::array gid; + uint8_t actionCode; + }; +#pragma pack(pop) + + vehicle_announcement* getVehicleAnnouncement() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(vehicle_announcement); static constexpr size_t SYNC_STATUS_OFFSET = FIXED_LEN; static constexpr size_t SYNC_STATUS_LEN = 1; - - static constexpr size_t OPT_LEN = FIXED_LEN + SYNC_STATUS_LEN; + static constexpr size_t OPT_LEN = SYNC_STATUS_OFFSET + SYNC_STATUS_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~| @@ -1259,6 +1246,13 @@ namespace pcpp { return DoIpPayloadTypes::ALIVE_CHECK_RESPONSE; } + /// @brief Checks if the Alive Check Response data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == FIXED_LEN); + } private: static constexpr size_t SOURCE_ADDRESS_OFFSET = DOIP_HEADER_LEN; @@ -1307,8 +1301,18 @@ namespace pcpp return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE; } + /// @brief Checks if the Diagnostic Power Mode Response data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == FIXED_LEN); + } + private: - DoIpDiagnosticPowerModeCodes _powerModeCode; ///< Diagnostic power mode code. + static constexpr size_t POWER_MODE_CODE_OFFSET = DOIP_HEADER_LEN; + static constexpr size_t POWER_MODE_CODE_LEN = sizeof(uint8_t); + static constexpr size_t FIXED_LEN = POWER_MODE_CODE_OFFSET + POWER_MODE_CODE_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1337,21 +1341,6 @@ namespace pcpp DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets); - /// @struct entity_status_response - /// Represents the Routing Activation Request data in DoIP. - /// Routing Activation Response message structure (extends DoIP header). - struct entity_status_response : doiphdr - { - /// @brief Type of the DoIP node (e.g., gateway, ECU). - DoIpEntityStatusResponseCode nodeType; - - /// @brief Maximum number of concurrent sockets supported. - uint8_t maxConcurrentSockets; - - /// @brief Number of currently open sockets. - uint8_t currentlyOpenSockets; - }; - /// @brief Returns the DoIP payload type. /// @return DoIpPayloadTypes::ENTITY_STATUS_RESPONSE DoIpPayloadTypes getPayloadType() const override @@ -1402,25 +1391,33 @@ namespace pcpp /// @return A string summarizing the Entity Status Response. std::string getSummary() const; - /// Get a pointer to entity status response data - /// Notice this points directly to the data, so any change will modify - /// the actual packet data - /// @return A pointer to a routing_activation_response structure containing the data - entity_status_response* getEntityStatusResponsePtr() const + /// @brief Checks if the Entity Status Response data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) { - return reinterpret_cast(m_Data); + return (dataLen == FIXED_LEN || dataLen == OPT_LEN); } private: - bool _hasMaxDataSize; ///< Indicates if max data size is set. +#pragma pack(push, 1) + struct entity_status_response : doiphdr + { + uint8_t nodeType; + + uint8_t maxConcurrentSockets; - static constexpr size_t NODE_TYPE_LEN = 1; - static constexpr size_t MAX_CONCURRENT_SOCKETS_LEN = 1; - static constexpr size_t CURRENTLY_OPEN_SOCKETS_LEN = 1; - static constexpr size_t FIXED_LEN = - DOIP_HEADER_LEN + NODE_TYPE_LEN + MAX_CONCURRENT_SOCKETS_LEN + CURRENTLY_OPEN_SOCKETS_LEN; + uint8_t currentlyOpenSockets; + }; +#pragma pack(pop) + + entity_status_response* getEntityStatusResponsePtr() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(entity_status_response); static constexpr size_t MAX_DATA_SIZE_OFFSET = FIXED_LEN; - static constexpr size_t MAX_DATA_SIZE_LEN = 4; + static constexpr size_t MAX_DATA_SIZE_LEN = sizeof(uint32_t); static constexpr size_t OPT_LEN = FIXED_LEN + MAX_DATA_SIZE_LEN; }; @@ -1444,10 +1441,11 @@ namespace pcpp /// @brief default c'tor. DoIpDiagnosticBase() {}; - /// @struct common_diagnostic_header - /// Common first diagnostic data in DoIP - /// messages (diagnostic/diagnosticAck/diagnosticNack). - /// common_diagnostic_header message structure (extends DoIP header). +/// @struct common_diagnostic_header +/// Common first diagnostic data in DoIP +/// messages (diagnostic/diagnosticAck/diagnosticNack). +/// common_diagnostic_header message structure (extends DoIP header). +#pragma pack(push, 1) struct common_diagnostic_header : doiphdr { /// @brief Diagnostic source address @@ -1456,6 +1454,7 @@ namespace pcpp /// @brief Diagnostic target address uint16_t targetAddress; }; +#pragma pack(pop) /// @brief Gets the source logical address of the message. /// @return 16-bit address of the source ECU. @@ -1466,28 +1465,22 @@ namespace pcpp uint16_t getTargetAddress() const; /// @brief Sets the source logical address. - /// @param[in] addr New 16-bit source address. - void setSourceAddress(uint16_t addr); + /// @param[in] sourceAddress New 16-bit source address. + void setSourceAddress(uint16_t sourceAddress); /// @brief Sets the target logical address. - /// @param[in] addr New 16-bit target address. - void setTargetAddress(uint16_t addr); + /// @param[in] targetAddress New 16-bit target address. + void setTargetAddress(uint16_t targetAddress); /// @brief Returns a human-readable summary of the message content. /// @return A string summarizing the diagnostic message. virtual std::string getSummary() const = 0; - /// Get a pointer to diagnostic message data - /// Notice this points directly to the data, so any change will modify - /// the actual packet data - /// @return A pointer to a common_diagnostic_header structure containing the data + private: common_diagnostic_header* getCommonDiagnosticHeader() const { return reinterpret_cast(m_Data); } - - private: - static constexpr size_t FIX_LEN = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; }; //~~~~~~~~~~~~~~~~~~~~~~| @@ -1539,11 +1532,16 @@ namespace pcpp return sizeof(doiphdr) + 2 * sizeof(uint16_t); } + /// @brief Checks if the diagnostic data length is valid. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen > MIN_LEN); + } + private: - static constexpr size_t DIAGNOSTIC_DATA_OFFSET = - DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; - static constexpr size_t MIN_LEN = - DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + 1; /*Min diagnostic message Len*/ + static constexpr size_t DIAGNOSTIC_DATA_OFFSET = sizeof(common_diagnostic_header); + static constexpr size_t MIN_LEN = DIAGNOSTIC_DATA_OFFSET + 1; /*Min diagnostic message Len*/ }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1561,9 +1559,6 @@ namespace pcpp /// @param[in] packet Pointer to the parent packet. DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - /// @brief default c'tor - DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); - /// @brief Gets the acknowledgment/nack code (1-byte). uint8_t getResponseCode() const; @@ -1582,12 +1577,21 @@ namespace pcpp /// @brief Clears the previously stored diagnostic message. void clearPreviousMessage(); + /// @brief Checks if data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen >= FIXED_LEN); + } + protected: - bool _hasPreviousMessage; ///< True if a previous message is present. - static constexpr size_t DIAGNOSTIC_ACK_CODE_OFFSET = - DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN; - static constexpr size_t DIAGNOSTIC_ACK_CODE_LEN = 1; - static constexpr size_t FIXED_LEN = DIAGNOSTIC_ACK_CODE_OFFSET + DIAGNOSTIC_ACK_CODE_LEN; + DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); + + private: + static constexpr size_t DIAGNOSTIC_CODE_OFFSET = sizeof(common_diagnostic_header); + static constexpr size_t DIAGNOSTIC_CODE_LEN = sizeof(uint8_t); + static constexpr size_t FIXED_LEN = DIAGNOSTIC_CODE_OFFSET + DIAGNOSTIC_CODE_LEN; static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; @@ -1703,6 +1707,13 @@ namespace pcpp { return DoIpPayloadTypes::ALIVE_CHECK_REQUEST; } + /// @brief Checks if the Alive Check Request data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == DOIP_HEADER_LEN); // No payload + } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1734,6 +1745,14 @@ namespace pcpp { return DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST; } + + /// @brief Checks if the Vehicle Identification Request data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == DOIP_HEADER_LEN); // No payload + } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1765,6 +1784,14 @@ namespace pcpp { return DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST; } + + /// @brief Checks if the Entity Status Request data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == DOIP_HEADER_LEN); // No payload + } }; //~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1797,6 +1824,14 @@ namespace pcpp { return DoIpPayloadTypes::ENTITY_STATUS_REQUEST; } + + /// @brief Checks if the Entity Status Request data length is valid. + /// @param[in] dataLen Length of the data buffer. + /// @return true if the data length is valid, false otherwise. + static inline bool isDataLenValid(size_t dataLen) + { + return (dataLen == DOIP_HEADER_LEN); // No payload + } }; } // namespace pcpp diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index e364a121e5..144c82ec45 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -110,7 +110,7 @@ namespace pcpp // in the context of DoIP (Diagnostic over IP). It maps the `DoIpEntityStatus` enum values // to their corresponding descriptions, distinguishing between a "DoIP node" and a "DoIP gateway." static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ - { DoIpEntityStatusResponseCode::NODE, "DoIp node" }, + { DoIpEntityStatusResponseCode::NODE, "DoIP node" }, { DoIpEntityStatusResponseCode::GATEWAY, "DoIP gateway" }, }; @@ -179,25 +179,6 @@ namespace pcpp { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } }; - DoIpProtocolVersion DoIpLayer::getProtocolVersion() const - { - uint8_t version = getDoIpHeader()->protocolVersion; - - switch (static_cast(version)) - { - case DoIpProtocolVersion::ReservedVersion: - case DoIpProtocolVersion::Version01Iso2010: - case DoIpProtocolVersion::Version02Iso2012: - case DoIpProtocolVersion::Version03Iso2019: - case DoIpProtocolVersion::Version04Iso2019_AMD1: - case DoIpProtocolVersion::DefaultVersion: - return static_cast(version); - - default: - return DoIpProtocolVersion::UnknownVersion; - } - } - DoIpLayer::DoIpLayer() { m_DataLen = DOIP_HEADER_LEN; @@ -218,45 +199,97 @@ namespace pcpp switch (detectedPayloadType) { case DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST: - return new DoIpRoutingActivationRequest(data, dataLen, prevLayer, packet); + return (DoIpRoutingActivationRequest::isDataLenValid(dataLen)) + ? new DoIpRoutingActivationRequest(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE: - return new DoIpRoutingActivationResponse(data, dataLen, prevLayer, packet); + return (DoIpRoutingActivationResponse::isDataLenValid(dataLen)) + ? new DoIpRoutingActivationResponse(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK: - return new DoIpGenericHeaderNack(data, dataLen, prevLayer, packet); + return (DoIpGenericHeaderNack::isDataLenValid(dataLen)) + ? new DoIpGenericHeaderNack(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: - return new DoIpVehicleIdentificationRequestEID(data, dataLen, prevLayer, packet); + return (DoIpVehicleIdentificationRequestEID::isDataLenValid(dataLen)) + ? new DoIpVehicleIdentificationRequestEID(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: - return new DoIpVehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet); + return (DoIpVehicleIdentificationRequestVIN::isDataLenValid(dataLen)) + ? new DoIpVehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: - return new DoIpVehicleAnnouncement(data, dataLen, prevLayer, packet); + return (DoIpVehicleAnnouncement::isDataLenValid(dataLen)) + ? new DoIpVehicleAnnouncement(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ALIVE_CHECK_RESPONSE: - return new DoIpAliveCheckResponse(data, dataLen, prevLayer, packet); + return (DoIpAliveCheckResponse::isDataLenValid(dataLen)) + ? new DoIpAliveCheckResponse(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE: - return new DoIpDiagnosticPowerModeResponse(data, dataLen, prevLayer, packet); + return (DoIpDiagnosticPowerModeResponse::isDataLenValid(dataLen)) + ? new DoIpDiagnosticPowerModeResponse(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ENTITY_STATUS_RESPONSE: - return new DoIpEntityStatusResponse(data, dataLen, prevLayer, packet); + return (DoIpEntityStatusResponse::isDataLenValid(dataLen)) + ? new DoIpEntityStatusResponse(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE: - return new DoIpDiagnosticMessage(data, dataLen, prevLayer, packet); + return (DoIpDiagnosticMessage::isDataLenValid(dataLen)) + ? new DoIpDiagnosticMessage(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK: - return new DoIpDiagnosticAckMessage(data, dataLen, prevLayer, packet); + return (DoIpDiagnosticAckMessage::isDataLenValid(dataLen)) + ? new DoIpDiagnosticAckMessage(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK: - return new DoIpDiagnosticNackMessage(data, dataLen, prevLayer, packet); + return (DoIpDiagnosticNackMessage::isDataLenValid(dataLen)) + ? new DoIpDiagnosticNackMessage(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST: - return new DoIpVehicleIdentificationRequest(data, dataLen, prevLayer, packet); + return (DoIpVehicleIdentificationRequest::isDataLenValid(dataLen)) + ? new DoIpVehicleIdentificationRequest(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ALIVE_CHECK_REQUEST: - return new DoIpAliveCheckRequest(data, dataLen, prevLayer, packet); + return (DoIpAliveCheckRequest::isDataLenValid(dataLen)) + ? new DoIpAliveCheckRequest(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST: - return new DoIpDiagnosticPowerModeRequest(data, dataLen, prevLayer, packet); + return (DoIpDiagnosticPowerModeRequest::isDataLenValid(dataLen)) + ? new DoIpDiagnosticPowerModeRequest(data, dataLen, prevLayer, packet) + : nullptr; case DoIpPayloadTypes::ENTITY_STATUS_REQUEST: - return new DoIpEntityStatusRequest(data, dataLen, prevLayer, packet); + return (DoIpEntityStatusRequest::isDataLenValid(dataLen)) + ? new DoIpEntityStatusRequest(data, dataLen, prevLayer, packet) + : nullptr; default: return nullptr; } } + + DoIpProtocolVersion DoIpLayer::getProtocolVersion() const + { + uint8_t version = getDoIpHeader()->protocolVersion; + + switch (static_cast(version)) + { + case DoIpProtocolVersion::ReservedVersion: + case DoIpProtocolVersion::Version01Iso2010: + case DoIpProtocolVersion::Version02Iso2012: + case DoIpProtocolVersion::Version03Iso2019: + case DoIpProtocolVersion::Version04Iso2019_AMD1: + case DoIpProtocolVersion::DefaultVersion: + return static_cast(version); + + default: + return DoIpProtocolVersion::UnknownVersion; + } + } + std::string DoIpLayer::getProtocolVersionAsStr() const { auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); - return it->second; + return (it != DoIpEnumToStringProtocolVersion.end()) ? it->second : "Unknown Protocol Version"; } void DoIpLayer::setProtocolVersion(DoIpProtocolVersion version) @@ -264,9 +297,9 @@ namespace pcpp getDoIpHeader()->protocolVersion = static_cast(version); } - void DoIpLayer::setProtocolVersion(uint8_t version) + void DoIpLayer::setProtocolVersion(uint8_t rawVersion) { - getDoIpHeader()->protocolVersion = version; + getDoIpHeader()->protocolVersion = rawVersion; } uint8_t DoIpLayer::getInvertProtocolVersion() const @@ -287,7 +320,7 @@ namespace pcpp std::string DoIpLayer::getPayloadTypeAsStr() const { auto it = DoIpEnumToStringPayloadType.find(getPayloadType()); - return it->second; + return (it != DoIpEnumToStringPayloadType.end()) ? it->second : "Unknown Payload Type"; } uint32_t DoIpLayer::getPayloadLength() const @@ -303,11 +336,8 @@ namespace pcpp std::string DoIpLayer::toString() const { std::ostringstream oss; - DoIpPayloadTypes type = getPayloadType(); - oss << "DoIP Layer, " << getPayloadTypeAsStr() << " (0x" << std::hex << std::setw(4) << std::setfill('0') - << static_cast(type) << ")"; - + << static_cast(getPayloadType()) << ")"; return oss.str(); } @@ -343,34 +373,17 @@ namespace pcpp DoIpRoutingActivationRequest::DoIpRoutingActivationRequest(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < FIXED_LEN || dataLen > OPT_LEN) - throw std::runtime_error("DoIpRoutingActivationRequest: Invalid payload length!"); - - if (dataLen > FIXED_LEN && dataLen < OPT_LEN) - throw std::runtime_error("DoIpRoutingActivationRequest: Invalid OEM field length!"); - - if (dataLen == OPT_LEN) - { - _hasReservedOem = true; - } - else - { - _hasReservedOem = false; - PCPP_LOG_DEBUG("Reserved OEM field is empty!"); - } - } + {} DoIpRoutingActivationRequest::DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType) - : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); extendLayer(DOIP_HEADER_LEN, FIXED_LEN - DOIP_HEADER_LEN); auto* payload = getRoutingRequest(); payload->sourceAddress = htobe16(sourceAddress); - payload->activationType = activationType; + payload->activationType = static_cast(activationType); // Reserved ISO is always all zeros payload->reservedIso.fill(0); } @@ -387,12 +400,12 @@ namespace pcpp DoIpActivationTypes DoIpRoutingActivationRequest::getActivationType() const { - return getRoutingRequest()->activationType; + return static_cast(getRoutingRequest()->activationType); } void DoIpRoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) { - getRoutingRequest()->activationType = activationType; + getRoutingRequest()->activationType = static_cast(activationType); } std::array DoIpRoutingActivationRequest::getReservedIso() const @@ -407,58 +420,51 @@ namespace pcpp bool DoIpRoutingActivationRequest::hasReservedOem() const { - return _hasReservedOem; + return (m_DataLen == OPT_LEN); } const uint8_t* DoIpRoutingActivationRequest::getReservedOem() const { - return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; + return hasReservedOem() ? (m_Data + FIXED_LEN) : nullptr; } void DoIpRoutingActivationRequest::setReservedOem(const std::array& reservedOem) { - if (!_hasReservedOem) + if (!hasReservedOem()) { extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); memcpy((m_Data + FIXED_LEN), reservedOem.data(), DOIP_RESERVED_OEM_LEN); - _hasReservedOem = true; } void DoIpRoutingActivationRequest::clearReservedOem() { - if (m_DataLen == OPT_LEN) + if (hasReservedOem()) { shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); - _hasReservedOem = false; PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } - else if (m_DataLen == FIXED_LEN) + else { PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); } } + std::string DoIpRoutingActivationRequest::getSummary() const { std::ostringstream oss; - DoIpActivationTypes type = getActivationType(); - oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; - auto it = DoIpEnumToStringActivationTypes.find(type); - if (it != DoIpEnumToStringActivationTypes.end()) - { - oss << "Activation type: " << it->second << std::hex << " (0x" << unsigned(type) << ")\n"; - } - else - { - oss << "Activation type: Unknown" << std::hex << " (0x" << unsigned(type) << ")\n"; - } + oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; + + auto it = DoIpEnumToStringActivationTypes.find(getActivationType()); + oss << "Activation type: " << ((it != DoIpEnumToStringActivationTypes.end()) ? it->second : "Unknown") << " (0x" + << std::hex << static_cast(getActivationType()) << ")\n"; + oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; - if (_hasReservedOem) - { + if (hasReservedOem()) oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << '\n'; - } + return oss.str(); } @@ -468,33 +474,11 @@ namespace pcpp DoIpRoutingActivationResponse::DoIpRoutingActivationResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < FIXED_LEN || dataLen > OPT_LEN) - { - throw std::runtime_error("DoIpRoutingActivationResponse: Invalid payload length!"); - } - - if (dataLen > FIXED_LEN && dataLen < OPT_LEN) - { - throw std::runtime_error("DoIpRoutingActivationResponse: invalid OEM field length"); - } - - // Optional OEM part - if (dataLen == OPT_LEN) - { - _hasReservedOem = true; - } - else - { - _hasReservedOem = false; - PCPP_LOG_DEBUG("Reserved OEM field is empty!"); - } - } + {} DoIpRoutingActivationResponse::DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode) - : _hasReservedOem(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); @@ -502,7 +486,7 @@ namespace pcpp auto* payload = getRoutingResponse(); payload->logicalAddressExternalTester = htobe16(logicalAddressExternalTester); payload->sourceAddress = htobe16(sourceAddress); - payload->responseCode = responseCode; + payload->responseCode = static_cast(responseCode); payload->reservedIso.fill(0); } @@ -528,12 +512,12 @@ namespace pcpp DoIpRoutingResponseCodes DoIpRoutingActivationResponse::getResponseCode() const { - return getRoutingResponse()->responseCode; + return static_cast(getRoutingResponse()->responseCode); } void DoIpRoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) { - getRoutingResponse()->responseCode = code; + getRoutingResponse()->responseCode = static_cast(code); } std::array DoIpRoutingActivationResponse::getReservedIso() const @@ -548,34 +532,32 @@ namespace pcpp bool DoIpRoutingActivationResponse::hasReservedOem() const { - return _hasReservedOem; + return (m_DataLen == OPT_LEN); } const uint8_t* DoIpRoutingActivationResponse::getReservedOem() const { - return _hasReservedOem ? (m_Data + FIXED_LEN) : nullptr; + return hasReservedOem() ? (m_Data + FIXED_LEN) : nullptr; } void DoIpRoutingActivationResponse::setReservedOem(const std::array& reservedOem) { - if (!_hasReservedOem) + if (!hasReservedOem()) { extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); memcpy((m_Data + FIXED_LEN), &reservedOem, DOIP_RESERVED_OEM_LEN); - _hasReservedOem = true; } void DoIpRoutingActivationResponse::clearReservedOem() { - if (m_DataLen == OPT_LEN) + if (hasReservedOem()) { shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); - _hasReservedOem = false; PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } - if (m_DataLen == FIXED_LEN) + else { PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); } @@ -583,21 +565,21 @@ namespace pcpp std::string DoIpRoutingActivationResponse::getSummary() const { - std::ostringstream ss; - DoIpRoutingResponseCodes code = getResponseCode(); - ss << "Logical Address (Tester): 0x" << std::hex << getLogicalAddressExternalTester() << "\n"; - ss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; - auto it = DoIpEnumToStringRoutingResponseCodes.find(code); - if (it != DoIpEnumToStringRoutingResponseCodes.end()) - ss << "Routing activation response code: " << it->second << " (0x" << std::hex << unsigned(code) << ")\n"; - else - ss << "Response Code: Unknown (0x" << std::hex << unsigned(code) << ")\n"; + std::ostringstream oss; + oss << "Logical Address (Tester): 0x" << std::hex << getLogicalAddressExternalTester() << "\n"; + oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; - ss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; - if (_hasReservedOem) - ss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << "\n"; + auto it = DoIpEnumToStringRoutingResponseCodes.find(getResponseCode()); + oss << "Routing activation response code: " + << ((it != DoIpEnumToStringRoutingResponseCodes.end()) ? it->second : "Unknown") << " (0x" << std::hex + << static_cast(getResponseCode()) << ")\n"; + + oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) + << "\n"; + if (hasReservedOem()) + oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << "\n"; - return ss.str(); + return oss.str(); } //~~~~~~~~~~~~~~~~~~~~~~| @@ -605,10 +587,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~| DoIpGenericHeaderNack::DoIpGenericHeaderNack(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen != FIXED_LEN) - throw std::runtime_error("DoIpGenericHeaderNack: Invalid payload length!"); - } + {} DoIpGenericHeaderNack::DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) { @@ -634,19 +613,19 @@ namespace pcpp std::string DoIpGenericHeaderNack::getSummary() const { - std::ostringstream ss; + std::ostringstream oss; DoIpGenericHeaderNackCodes nackCode = getNackCode(); auto it = DoIpEnumToStringGenericHeaderNackCodes.find(nackCode); if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) { - ss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(nackCode) - << ")\n"; + oss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(nackCode) + << ")\n"; } else { - ss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(nackCode) << ")\n"; + oss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(nackCode) << ")\n"; } - return ss.str(); + return oss.str(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -655,10 +634,7 @@ namespace pcpp DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen != FIXED_LEN) - throw std::runtime_error("VehicleIdentificationRequestEID: Invalid payload length"); - } + {} DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID( const std::array& eid) @@ -691,10 +667,7 @@ namespace pcpp DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen != FIXED_LEN) - throw std::runtime_error("VehicleIdentificationRequestVIN: Invalid payload length!"); - } + {} DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN( const std::array& vin) @@ -726,27 +699,13 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~| DoIpVehicleAnnouncement::DoIpVehicleAnnouncement(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < FIXED_LEN || dataLen > OPT_LEN) - throw std::runtime_error("VehicleAnnouncement: invalid payload length!"); - - if (dataLen == OPT_LEN) - { - _hasSyncStatus = true; - } - else - { - PCPP_LOG_DEBUG("Sync status field is empty!"); - _hasSyncStatus = false; - } - } + {} DoIpVehicleAnnouncement::DoIpVehicleAnnouncement(const std::array& vin, uint16_t logicalAddress, const std::array& eid, const std::array& gid, DoIpActionCodes actionCode) - : _hasSyncStatus(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); @@ -776,11 +735,11 @@ namespace pcpp } DoIpActionCodes DoIpVehicleAnnouncement::getFurtherActionRequired() const { - return getVehicleAnnouncement()->actionCode; + return static_cast(getVehicleAnnouncement()->actionCode); } const DoIpSyncStatus* DoIpVehicleAnnouncement::getSyncStatus() const { - return _hasSyncStatus ? reinterpret_cast(m_Data + SYNC_STATUS_OFFSET) : nullptr; + return hasSyncStatus() ? reinterpret_cast(m_Data + SYNC_STATUS_OFFSET) : nullptr; } void DoIpVehicleAnnouncement::clearSyncStatus() @@ -788,10 +747,9 @@ namespace pcpp if (m_DataLen == OPT_LEN) { shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); - _hasSyncStatus = false; PCPP_LOG_DEBUG("Sync status has been removed successfully!"); } - if (m_DataLen == FIXED_LEN) + else { PCPP_LOG_DEBUG("doip packet has no syncStatus!"); } @@ -818,57 +776,45 @@ namespace pcpp void DoIpVehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) { - getVehicleAnnouncement()->actionCode = action; + getVehicleAnnouncement()->actionCode = static_cast(action); } void DoIpVehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) { - if (!_hasSyncStatus) + if (!hasSyncStatus()) { extendLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); *(m_Data + SYNC_STATUS_OFFSET) = static_cast(syncStatus); - _hasSyncStatus = true; } bool DoIpVehicleAnnouncement::hasSyncStatus() const { - return _hasSyncStatus; + return (m_DataLen == OPT_LEN); } std::string DoIpVehicleAnnouncement::getSummary() const { std::ostringstream oss; - DoIpActionCodes actionCode = getFurtherActionRequired(); oss << "VIN: " << std::string(reinterpret_cast(getVIN().data()), DOIP_VIN_LEN) << "\n"; - oss << "Logical address: " << std::hex << "0x" << getLogicalAddress() << "\n"; + oss << "Logical address: 0x" << std::hex << getLogicalAddress() << "\n"; oss << "EID: " << pcpp::byteArrayToHexString(getEID().data(), DOIP_EID_LEN) << "\n"; oss << "GID: " << pcpp::byteArrayToHexString(getGID().data(), DOIP_GID_LEN) << "\n"; - auto it = DoIpEnumToStringActionCodes.find(actionCode); - if (it != DoIpEnumToStringActionCodes.end()) - { - oss << "Further action required: " << it->second << std::hex << " (0x" << unsigned(actionCode) << ")" - << "\n"; - } - else - { - oss << "Further action required: Unknown" << std::hex << " (0x" << unsigned(actionCode) << ")" - << "\n"; - } - if (_hasSyncStatus) + + auto it = DoIpEnumToStringActionCodes.find(getFurtherActionRequired()); + oss << "Further action required: " << ((it != DoIpEnumToStringActionCodes.end()) ? it->second : "Unknown") + << " (0x" << std::hex << static_cast(getFurtherActionRequired()) << ")\n"; + + if (hasSyncStatus()) { - DoIpSyncStatus syncStatus = *getSyncStatus(); - auto it_ = DoIpEnumToStringSyncStatus.find(syncStatus); - if (it_ != DoIpEnumToStringSyncStatus.end()) - { - oss << "VIN/GID sync status: " << it_->second << "\n"; // Convert enum to byte - } - else - { - oss << "VIN/GID sync status: Unknown" << std::hex << " (0x" << unsigned(syncStatus) << ")" << "\n"; - } + auto syncStatus = *getSyncStatus(); + auto itSync = DoIpEnumToStringSyncStatus.find(syncStatus); + oss << "VIN/GID sync status: " + << ((itSync != DoIpEnumToStringSyncStatus.end()) ? itSync->second : "Unknown") << " (0x" << std::hex + << static_cast(syncStatus) << ")\n"; } + return oss.str(); } @@ -877,10 +823,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~| DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < DOIP_HEADER_LEN + DOIP_SOURCE_ADDRESS_LEN) - throw std::runtime_error("AliveCheckResponse: insufficient payload length"); - } + {} DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint16_t sourceAddress) { @@ -891,15 +834,12 @@ namespace pcpp uint16_t DoIpAliveCheckResponse::getSourceAddress() const { - uint16_t _sourceAddress; - memcpy(&_sourceAddress, (m_Data + SOURCE_ADDRESS_OFFSET), DOIP_SOURCE_ADDRESS_LEN); - return htobe16(_sourceAddress); + return htobe16(*reinterpret_cast(m_Data + SOURCE_ADDRESS_OFFSET)); } void DoIpAliveCheckResponse::setSourceAddress(uint16_t sourceAddress) { - uint16_t _sourceAddress = htobe16(sourceAddress); - memcpy((m_Data + SOURCE_ADDRESS_OFFSET), &_sourceAddress, DOIP_SOURCE_ADDRESS_LEN); + *reinterpret_cast(m_Data + SOURCE_ADDRESS_OFFSET) = htobe16(sourceAddress); } std::string DoIpAliveCheckResponse::getSummary() const @@ -915,48 +855,33 @@ namespace pcpp DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - constexpr size_t payloadLen = DOIP_HEADER_LEN + sizeof(_powerModeCode); - if (dataLen != payloadLen) - throw std::runtime_error("DiagnosticPowerModeResponse: invalid payload length!"); - - const uint8_t* payloadPtr = data + DOIP_HEADER_LEN; - _powerModeCode = static_cast(*payloadPtr); - } + {} DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) - : _powerModeCode(code) { - const size_t payloadLen = sizeof(_powerModeCode); - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(DOIP_HEADER_LEN, payloadLen); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), POWER_MODE_CODE_LEN); + extendLayer(POWER_MODE_CODE_OFFSET, POWER_MODE_CODE_LEN); setPowerModeCode(code); } DoIpDiagnosticPowerModeCodes DoIpDiagnosticPowerModeResponse::getPowerModeCode() const { - return _powerModeCode; + return static_cast(*(m_Data + POWER_MODE_CODE_OFFSET)); } void DoIpDiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) { - _powerModeCode = code; - uint8_t* dataPtr = getDataPtr(DOIP_HEADER_LEN); - *dataPtr = static_cast(code); + *(m_Data + POWER_MODE_CODE_OFFSET) = static_cast(code); } std::string DoIpDiagnosticPowerModeResponse::getSummary() const { std::ostringstream oss; - auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(_powerModeCode); - if (it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) - { - oss << "Diagnostic power mode: " << it->second << std::hex << " (0x" << unsigned(_powerModeCode) << ")\n"; - } - else - { - oss << "Diagnostic power mode: Unknown" << std::hex << " (0x" << unsigned(_powerModeCode) << ")\n"; - } + DoIpDiagnosticPowerModeCodes powerModeCode = getPowerModeCode(); + auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); + oss << "Diagnostic power mode: " + << ((it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) ? it->second : "Unknown") << " (0x" << std::hex + << static_cast(powerModeCode) << ")\n"; return oss.str(); } @@ -965,31 +890,10 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~| DoIpEntityStatusResponse::DoIpEntityStatusResponse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < FIXED_LEN || dataLen > OPT_LEN) - { - throw std::runtime_error("EntityStatusResponse: Invalid payload length!"); - } - - if (dataLen > FIXED_LEN && dataLen < OPT_LEN) - { - throw std::runtime_error("EntityStatusResponse: Invalid MaxDataSize field length!"); - } - - if (dataLen == OPT_LEN) - { - _hasMaxDataSize = true; - } - else - { - PCPP_LOG_DEBUG("MaxDataSize field is empty !"); - _hasMaxDataSize = false; - } - } + {} DoIpEntityStatusResponse::DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) - : _hasMaxDataSize(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); @@ -1000,7 +904,7 @@ namespace pcpp } DoIpEntityStatusResponseCode DoIpEntityStatusResponse::getNodeType() const { - return getEntityStatusResponsePtr()->nodeType; + return static_cast(getEntityStatusResponsePtr()->nodeType); } uint8_t DoIpEntityStatusResponse::getMaxConcurrentSockets() const { @@ -1012,22 +916,21 @@ namespace pcpp } const uint8_t* DoIpEntityStatusResponse::getMaxDataSize() const { - return _hasMaxDataSize ? (m_Data + MAX_DATA_SIZE_OFFSET) : nullptr; + return hasMaxDataSize() ? (m_Data + MAX_DATA_SIZE_OFFSET) : nullptr; } void DoIpEntityStatusResponse::setNodeType(DoIpEntityStatusResponseCode nodeType) { - getEntityStatusResponsePtr()->nodeType = nodeType; + getEntityStatusResponsePtr()->nodeType = static_cast(nodeType); } bool DoIpEntityStatusResponse::hasMaxDataSize() const { - return _hasMaxDataSize; + return (m_DataLen == OPT_LEN); } void DoIpEntityStatusResponse::clearMaxDataSize() { - if (m_DataLen == OPT_LEN && _hasMaxDataSize) + if (hasMaxDataSize()) { shortenLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); - _hasMaxDataSize = false; PCPP_LOG_DEBUG("MaxDataSize has been removed successfully!"); } else @@ -1047,47 +950,37 @@ namespace pcpp void DoIpEntityStatusResponse::setMaxDataSize(const std::array& data) { - if (!_hasMaxDataSize) + if (!hasMaxDataSize()) { extendLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); } memcpy(m_Data + MAX_DATA_SIZE_OFFSET, &data, MAX_DATA_SIZE_LEN); setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); - _hasMaxDataSize = true; } std::string DoIpEntityStatusResponse::getSummary() const { - std::ostringstream oos; + std::ostringstream oss; DoIpEntityStatusResponseCode nodeType = getNodeType(); auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); - if (it != DoIpEnumToStringEntityStatusNodeTypes.end()) + oss << "Entity status: " << ((it != DoIpEnumToStringEntityStatusNodeTypes.end()) ? it->second : "Unknown") + << " (0x" << std::hex << static_cast(nodeType) << ")" << "\n"; + oss << "Max Concurrent Socket: " << static_cast(getMaxConcurrentSockets()) << "\n"; + oss << "Currently Opened Socket: " << static_cast(getCurrentlyOpenSockets()) << "\n"; + if (hasMaxDataSize()) { - oos << "Entity status: " << it->second << std::hex << " (0x" << unsigned(nodeType) << ")" << "\n"; - } - else - { - oos << "Node Type: Unknown" << std::hex << " (0x" << unsigned(nodeType) << ")\n"; - } - oos << "Max Concurrent Socket: " << unsigned(getMaxConcurrentSockets()) << "\n"; - oos << "Currently Opened Socket: " << unsigned(getCurrentlyOpenSockets()) << "\n"; - if (_hasMaxDataSize) - { - oos << "Max Data Size: " + oss << "Max Data Size: " << "0x" << pcpp::byteArrayToHexString((m_Data + MAX_DATA_SIZE_OFFSET), MAX_DATA_SIZE_LEN) << "\n"; } - return oos.str(); + return oss.str(); } - //~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~| // DoIpDiagnosticBase| - //~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~| DoIpDiagnosticBase::DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) - { - if (dataLen < FIX_LEN) - throw std::runtime_error("DiagnosticBase: insufficient payload length!"); - } + {} uint16_t DoIpDiagnosticBase::getSourceAddress() const { @@ -1109,15 +1002,12 @@ namespace pcpp getCommonDiagnosticHeader()->targetAddress = htobe16(targetAddress); } - //~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~| // DoIpDiagnosticMessage| - //~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~| DoIpDiagnosticMessage::DoIpDiagnosticMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : DoIpDiagnosticBase(data, dataLen, prevLayer, packet) - { - if (dataLen < MIN_LEN) - throw std::runtime_error("DiagnosticBase: insufficient payload length!"); - } + {} DoIpDiagnosticMessage::DoIpDiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData) @@ -1165,26 +1055,11 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| DoIpDiagnosticResponseMessageBase::DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DoIpDiagnosticBase(data, dataLen, prevLayer, packet), _hasPreviousMessage(false) - { - if (dataLen < PREVIOUS_MSG_OFFSET) - throw std::runtime_error("DiagnosticAckMessage: Invalid payload length"); - - const size_t remainingData = dataLen - PREVIOUS_MSG_OFFSET; - if (remainingData > 0) - { - _hasPreviousMessage = true; - } - else - { - PCPP_LOG_DEBUG("PreviousMessage field is empty!"); - _hasPreviousMessage = false; - } - } + : DoIpDiagnosticBase(data, dataLen, prevLayer, packet) + {} DoIpDiagnosticResponseMessageBase::DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type) - : _hasPreviousMessage(false) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); @@ -1194,12 +1069,12 @@ namespace pcpp uint8_t DoIpDiagnosticResponseMessageBase::getResponseCode() const { - return static_cast(*(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET)); + return static_cast(*(m_Data + DIAGNOSTIC_CODE_OFFSET)); } const std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const { - if (_hasPreviousMessage) + if (hasPreviousMessage()) { uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); @@ -1212,12 +1087,12 @@ namespace pcpp void DoIpDiagnosticResponseMessageBase::setResponseCode(uint8_t code) { - *(m_Data + DIAGNOSTIC_ACK_CODE_OFFSET) = static_cast(code); + *(m_Data + DIAGNOSTIC_CODE_OFFSET) = static_cast(code); } bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const { - return _hasPreviousMessage; + return (m_DataLen > PREVIOUS_MSG_OFFSET); } void DoIpDiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) @@ -1226,22 +1101,20 @@ namespace pcpp size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; setPayloadLength(newPayloadLen); // clear memory for old previous message - if (_hasPreviousMessage) + if (hasPreviousMessage()) { shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); } extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); memcpy(ptr, msg.data(), msg.size()); - _hasPreviousMessage = true; } void DoIpDiagnosticResponseMessageBase::clearPreviousMessage() { - if (_hasPreviousMessage) + if (hasPreviousMessage()) { shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); - _hasPreviousMessage = false; PCPP_LOG_DEBUG("PreviousMessage has been removed successfully!"); } else @@ -1281,15 +1154,9 @@ namespace pcpp oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; oss << "Target Address: " << std::hex << "0x" << getTargetAddress() << "\n"; auto it = DoIpEnumToStringAckCode.find(ackCode); - if (it != DoIpEnumToStringAckCode.end()) - { - oss << "ACK code: " << it->second << " (0x" << unsigned(ackCode) << ")\n"; - } - else - { - oss << "ACK code: Unknown" << std::hex << " (0x" << unsigned(ackCode) << ")\n"; - } - if (_hasPreviousMessage) + oss << "ACK code: " << ((it != DoIpEnumToStringAckCode.end()) ? it->second : "Unknown") << " (0x" + << static_cast(ackCode) << ")\n"; + if (hasPreviousMessage()) { oss << "Previous message: " << pcpp::byteArrayToHexString(getPreviousMessage().data(), getPreviousMessage().size()) << "\n"; @@ -1330,16 +1197,10 @@ namespace pcpp oss << "Target Address: 0x" << std::hex << getTargetAddress() << "\n"; auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); - if (it != DoIpEnumToStringDiagnosticNackCodes.end()) - { - oss << "NACK code: " << it->second << " (0x" << unsigned(nackCode) << ")\n"; - } - else - { - oss << "NACK code: Unknown (0x" << unsigned(nackCode) << ")\n"; - } + oss << "NACK code: " << ((it != DoIpEnumToStringDiagnosticNackCodes.end()) ? it->second : "Unknown") << " (0x" + << static_cast(nackCode) << ")\n"; - if (_hasPreviousMessage) + if (hasPreviousMessage()) { oss << "Previous message: " << pcpp::byteArrayToHexString(getPreviousMessage().data(), getPreviousMessage().size()) << "\n"; diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 8dda74f51f..d68b8bd7d6 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -32,7 +32,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) pcpp::TcpLayer* tcpLayer = RoutingActivationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = RoutingActivationRequest.getLayerOfType(); @@ -142,7 +142,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) PTF_ASSERT_NOT_NULL(tcpLayer); PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), 53850); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); PTF_ASSERT_EQUAL(tcpLayer->getTcpHeader()->headerChecksum, be16toh(0xa0a5)); auto* doipLayer = RoutingActivationResponse.getLayerOfType(); @@ -235,7 +235,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) pcpp::UdpLayer* udpLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -301,7 +301,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestEID.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); @@ -376,7 +376,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) pcpp::UdpLayer* udpLayer = VehicleIdentificationRequestVIN.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -457,8 +457,8 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) pcpp::UdpLayer* udpLayer = VehicleAnnouncement.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); // DOIP fields for vehicle identification request auto* doipLayer = VehicleAnnouncement.getLayerOfType(); @@ -531,7 +531,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_EQUAL(*doipLayer->getSyncStatus(), pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, enumclass); PTF_ASSERT_EQUAL( doipLayer->getSummary(), - "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\nVIN/GID sync status: VIN and/or GID are synchronized\n"); + "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\nVIN/GID sync status: VIN and/or GID are synchronized (0x0)\n"); doipLayer->clearSyncStatus(); PTF_ASSERT_FALSE(doipLayer->hasSyncStatus()); PTF_ASSERT_TRUE(doipLayer->getSyncStatus() == nullptr); @@ -556,7 +556,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) pcpp::UdpLayer* udpLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -619,7 +619,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) auto* udpLayer = AliveCheckResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = AliveCheckResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -687,7 +687,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_NOT_NULL(udpLayer); PTF_ASSERT_EQUAL(udpLayer->getDstPort(), 65300); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = PowerModeResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -757,7 +757,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) pcpp::UdpLayer* udpLayer = EntityStatusResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = EntityStatusResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -843,7 +843,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) pcpp::TcpLayer* tcpLayer = DiagnosticMessagePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = DiagnosticMessagePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -935,7 +935,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) pcpp::TcpLayer* tcpLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = DiagnosticAckMessage.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1032,7 +1032,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) pcpp::TcpLayer* tcpLayer = diagnosticNackPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(tcpLayer); - PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_PORT); + PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* nackLayer = diagnosticNackPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(nackLayer); @@ -1129,7 +1129,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) pcpp::UdpLayer* udpLayer = PowerModeRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = PowerModeRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1191,7 +1191,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) pcpp::UdpLayer* udpLayer = EntityStatusRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, be16toh(0x4988)); @@ -1255,7 +1255,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) pcpp::UdpLayer* udpLayer = AliveCheckRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = AliveCheckRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1317,7 +1317,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) auto* udpLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(udpLayer); - PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::UDP_PORT); + PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); @@ -1328,7 +1328,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle identification request (0x0001)"); PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 0x0); -} // DoIpInvalidPayloadTypePacketPacketParsing +} // DoIpVehicleIdentificationRequestWithDEfaultVersPacketParsing // DoIpInvalidPayloadTypePacketParsing PTF_TEST_CASE(DoIpInvalidPayloadTypePacketParsing) From cc6d70cedd82c0007ab60c3401fec3e3a11ea830 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 11 May 2025 16:32:34 -0400 Subject: [PATCH 37/43] Apply code review suggestions and resolve feedback comments --- Packet++/header/DoIpLayer.h | 282 +++++++++++++++++-------- Packet++/src/DoIpLayer.cpp | 272 ++++++++++++++++-------- Tests/Packet++Test/Tests/DoIpTests.cpp | 57 +++-- 3 files changed, 419 insertions(+), 192 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 12c3c3dce7..c7be58e77e 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -4,7 +4,6 @@ #include #include "Layer.h" #include "Logger.h" -#include "EndianPortable.h" /// @file @@ -71,6 +70,10 @@ namespace pcpp /// Central security routing activation type. /// Used for secure communications involving a central security system. CENTRAL_SECURITY = 0xE0U, + + /// Unknown routing activation type. + /// This value is used when the routing activation type is not specified or recognized. + UNKNOWN }; /// @brief Enum representing DoIP Generic Header NACK codes (ISO 13400). @@ -96,6 +99,10 @@ namespace pcpp /// Invalid payload length. /// The payload length specified in the header is invalid. INVALID_PAYLOAD_LENGTH = 0x04U, + + /// UNKNOWN. + /// Indicates that the NACK code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP action codes for DoIP announcement messages (ISO 13400). @@ -170,6 +177,10 @@ namespace pcpp /// Routing activation required. /// Indicates that routing activation is needed after the announcement message. ROUTING_ACTIVATION_REQUIRED = 0x10U, + + /// UNKNOWN. + /// Indicates that the action code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP routing activation response codes (ISO 13400). @@ -249,6 +260,10 @@ namespace pcpp /// Confirmation required. /// Additional confirmation is required to complete the routing activation. CONFIRMATION_REQUIRED = 0x11U, + + /// UNKNOWN. + /// Indicates that the routing response code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP diagnostic message NACK codes (ISO 13400). @@ -291,6 +306,10 @@ namespace pcpp /// Transport protocol error. /// An error occurred at the transport protocol level, preventing the message from being processed. TRANSPORT_PROTOCOL_ERROR = 0x08U, + + /// UNKNOWN. + /// Indicates that the NACK code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP diagnostic power mode codes (ISO 13400). @@ -308,7 +327,11 @@ namespace pcpp /// Not supported. /// The DoIP entity does not support diagnostic power mode reporting. - NOT_SUPPORTED = 0x02U + NOT_SUPPORTED = 0x02U, + + /// UNKNOWN. + /// Indicates that the power mode code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP diagnostic acknowledgment codes (ISO 13400). @@ -318,7 +341,11 @@ namespace pcpp { /// Acknowledgment. /// Indicates successful receipt or acknowledgment of a diagnostic message. - ACK = 0x00U + ACK = 0x00U, + + /// UNKNOWN. + /// Indicates that the acknowledgment code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP entity status response codes (ISO 13400). @@ -332,7 +359,11 @@ namespace pcpp /// Node. /// The entity functions as an individual node within the DoIP network. - NODE = 0x01U + NODE = 0x01U, + + /// UNKNOWN. + /// Indicates that the entity status response code is not recognized or supported. + UNKNOWN }; /// @brief Enum representing DoIP sync status (ISO 13400). @@ -404,6 +435,10 @@ namespace pcpp /// VIN and or GID are not synchronized. VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED = 0x10U, + + /// UNKNOWN. + /// Indicates that the sync status is not recognized or supported. + UNKNOWN }; /// @brief Represents the DoIP (Diagnostics over IP) protocol versions. @@ -508,7 +543,6 @@ namespace pcpp /// These ports are used for communication in the DoIP protocol over different transport layers. enum class DoIpPorts : uint16_t { - /// TCP and UDP doip Ports. /// The standard port for DoIP communication. TCP_UDP_PORT = 13400U, @@ -582,7 +616,7 @@ namespace pcpp /// @param[in] data The pointer to the beginning of a byte stream of an DOIP layer /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an DOIP layer - static inline bool isDataValid(uint8_t* data, size_t dataLen); + static bool isDataValid(uint8_t* data, size_t dataLen); // implement abstract methods @@ -616,7 +650,7 @@ namespace pcpp protected: // protected c'tors, this class cannot be instantiated by users - DoIpLayer(); + DoIpLayer(size_t length); DoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); @@ -635,32 +669,6 @@ namespace pcpp return (portAsEnum == DoIpPorts::TCP_UDP_PORT || portAsEnum == DoIpPorts::TLS_PORT); } - inline bool DoIpLayer::isDataValid(uint8_t* data, size_t dataLen) - { - if (data == nullptr || dataLen < DOIP_HEADER_LEN) - return false; - - auto* doipHeader = reinterpret_cast(data); - const uint8_t version = doipHeader->protocolVersion; - const uint8_t inVersion = doipHeader->invertProtocolVersion; - const uint16_t payloadRaw = doipHeader->payloadType; - const uint32_t lengthRaw = doipHeader->payloadLength; - - const uint32_t payloadLen = htobe32(lengthRaw); - - if (!isPayloadTypeValid(payloadRaw)) - return false; - // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() - const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); - if (!isProtocolVersionValid(version, inVersion, payloadType)) - return false; - - if (!isPayloadLengthValid(payloadLen, dataLen)) - return false; - - return true; - } - inline bool DoIpLayer::isProtocolVersionValid(uint8_t version, uint8_t inVersion, DoIpPayloadTypes type) { const DoIpProtocolVersion parsedVersion = static_cast(version); @@ -771,30 +779,41 @@ namespace pcpp DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType); /// @brief Returns the source address. + /// @return The 2-byte source address. uint16_t getSourceAddress() const; /// @brief Sets the source address. + /// @param[in] value The source address to set. void setSourceAddress(uint16_t value); /// @brief Returns the activation type. + /// @return The activation type as a DoIpActivationTypes enum value. DoIpActivationTypes getActivationType() const; /// @brief Sets the activation type. + /// @param[in] activationType The activation type to set. void setActivationType(DoIpActivationTypes activationType); /// @brief Gets the reserved ISO bytes. + /// @return 4-byte array representing the reserved ISO bytes. std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. + /// @param[in] reservedIso The reserved ISO bytes to set. void setReservedIso(const std::array& reservedIso); - /// @brief Gets pointer to reserved OEM bytes if present. - const uint8_t* getReservedOem() const; + /// @brief Gets the to reserved OEM bytes if present. + /// @throw std::runtime_error if the reserved OEM bytes are not present. + /// @note To use this method safely, check beforehand if the reserved OEM bytes are present using + /// hasReservedOem(). + const std::array getReservedOem() const; /// @brief Sets the reserved OEM bytes. + /// @param[in] reservedOem The reserved OEM bytes to set. void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. + /// @return true if OEM reserved bytes are present, false otherwise. bool hasReservedOem() const; /// @brief Clears the OEM reserved bytes. @@ -864,36 +883,49 @@ namespace pcpp DoIpRoutingResponseCodes responseCode); /// @brief Gets the logical address of the external tester. + /// @return The 2-byte logical address of the external tester. uint16_t getLogicalAddressExternalTester() const; /// @brief Sets the logical address of the external tester. + /// @param[in] addr The logical address of the external tester to set. void setLogicalAddressExternalTester(uint16_t addr); /// @brief Gets the source address. + /// @return The 2-byte source address. uint16_t getSourceAddress() const; /// @brief Sets the source address. - void setSourceAddress(uint16_t addr); + /// @param[in] sourceAddress The source address to set. + void setSourceAddress(uint16_t sourceAddress); /// @brief Gets the routing response code. + /// @return enum DoIpRoutingResponseCodes representing the routing response code. DoIpRoutingResponseCodes getResponseCode() const; /// @brief Sets the routing response code. + /// @param[in] code The routing response code to set. void setResponseCode(DoIpRoutingResponseCodes code); /// @brief Gets the reserved ISO bytes. + /// @return 4-byte array representing the reserved ISO bytes. std::array getReservedIso() const; /// @brief Sets the reserved ISO bytes. + /// @param[in] reservedIso The reserved ISO bytes to set. void setReservedIso(const std::array& reservedIso); /// @brief Gets pointer to reserved OEM bytes if present. - const uint8_t* getReservedOem() const; + /// @throw std::runtime_error if the reserved OEM bytes are not present. + /// @note before using this method, check beforehand if the reserved OEM bytes are present using + /// hasReservedOem(). + const std::array getReservedOem() const; /// @brief Sets the reserved OEM bytes. + /// @param[in] reservedOem The reserved OEM bytes to set. void setReservedOem(const std::array& reservedOem); /// @brief Checks if OEM reserved bytes are present. + /// @return true if OEM reserved bytes are present, false otherwise. bool hasReservedOem() const; /// @brief Clears the OEM reserved bytes. @@ -960,14 +992,13 @@ namespace pcpp explicit DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode); /// @brief Gets the NACK code. + /// @return enum DoIpGenericHeaderNackCodes representing the NACK code. DoIpGenericHeaderNackCodes getNackCode() const; /// @brief Sets the NACK code. + /// @param[in] code enum DoIpGenericHeaderNackCodes representing the NACK code to set. void setNackCode(DoIpGenericHeaderNackCodes code); - /// @brief Sets the Raw NACK code for debugging/testing. - void setNackCode(uint8_t code); - /// @brief Returns a human-readable summary of the message. std::string getSummary() const; @@ -986,9 +1017,17 @@ namespace pcpp } private: - static constexpr size_t NACK_CODE_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t NACK_CODE_LEN = sizeof(uint8_t); - static constexpr size_t FIXED_LEN = NACK_CODE_OFFSET + NACK_CODE_LEN; +#pragma pack(push, 1) + struct generic_header_nack : doiphdr + { + uint8_t nackCode; + }; +#pragma pack(pop) + generic_header_nack* getGenericHeaderNack() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(generic_header_nack); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1014,9 +1053,11 @@ namespace pcpp explicit DoIpVehicleIdentificationRequestEID(const std::array& eid = {}); /// @brief Gets the Entity ID (EID). + /// @return A 6-byte Entity ID (EID). std::array getEID() const; /// @brief Sets the Entity ID (EID). + /// @param[in] eid A 6-byte Entity ID (EID). void setEID(const std::array& eid); /// @brief Returns a human-readable summary of the message. @@ -1037,8 +1078,17 @@ namespace pcpp } private: - static constexpr size_t EID_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t FIXED_LEN = EID_OFFSET + DOIP_EID_LEN; +#pragma pack(push, 1) + struct vehicle_identification_request_eid : doiphdr + { + std::array eid; + }; +#pragma pack(pop) + vehicle_identification_request_eid* getVehicleIdentificationRequestEID() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_eid); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1064,9 +1114,11 @@ namespace pcpp explicit DoIpVehicleIdentificationRequestVIN(const std::array& vin = {}); /// @brief Gets the Vehicle Identification Number (VIN). + /// @return A 17-byte Vehicle Identification Number (VIN). std::array getVIN() const; /// @brief Sets the Vehicle Identification Number (VIN). + /// @param[in] vin A 17-byte Vehicle Identification Number (VIN). void setVIN(const std::array& vin); /// @brief Returns a human-readable summary of the message. @@ -1087,8 +1139,17 @@ namespace pcpp } private: - static constexpr size_t VIN_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t FIXED_LEN = VIN_OFFSET + DOIP_VIN_LEN; +#pragma pack(push, 1) + struct vehicle_identification_request_vin : doiphdr + { + std::array vin; + }; +#pragma pack(pop) + vehicle_identification_request_vin* getVehicleIdentificationRequestVIN() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_vin); }; //~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1121,42 +1182,57 @@ namespace pcpp const std::array& gid, DoIpActionCodes actionCode); /// @brief Gets the Vehicle Identification Number (VIN). + /// @return A 17-byte Vehicle Identification Number (VIN). std::array getVIN() const; /// @brief Gets the logical address of the vehicle. + /// @return A 2-byte logical address of the vehicle. uint16_t getLogicalAddress() const; /// @brief Gets the Entity Identifier (EID). + /// @return A 6-byte Entity Identifier (EID). std::array getEID() const; /// @brief Gets the Group Identifier (GID). + /// @return A 6-byte Group Identifier (GID). std::array getGID() const; /// @brief Gets the further action required code. + /// @return enum DoIpActionCodes representing the further action required code. DoIpActionCodes getFurtherActionRequired() const; /// @brief Gets the optional synchronization status if available. - const DoIpSyncStatus* getSyncStatus() const; + /// @throw std::runtime_error if the sync status is not present. + /// @note To use this method safely, check beforehand if the sync status is present using hasSyncStatus(). + /// @return A 1-byte synchronization status. + DoIpSyncStatus getSyncStatus() const; /// @brief Sets the Vehicle Identification Number (VIN). + /// @param[in] vin A 17-byte Vehicle Identification Number (VIN). void setVIN(const std::array& vin); /// @brief Sets the logical address. + /// @param[in] address A 2-byte logical address of the vehicle. void setLogicalAddress(uint16_t address); /// @brief Sets the Entity Identifier (EID). + /// @param[in] eid A 6-byte Entity Identifier (EID). void setEID(const std::array& eid); /// @brief Sets the Group Identifier (GID). + /// @param[in] gid A 6-byte Group Identifier (GID). void setGID(const std::array& gid); /// @brief Sets the further action required code. + /// @param[in] action enum DoIpActionCodes representing the further action required code to set. void setFurtherActionRequired(DoIpActionCodes action); /// @brief Sets the synchronization status. + /// @param[in] sync enum DoIpSyncStatus representing the synchronization status to set. void setSyncStatus(DoIpSyncStatus sync); /// @brief Checks whether the sync status is present. + /// @return true if the sync status is present, false otherwise. bool hasSyncStatus() const; /// @brief Clears the optional sync status field. @@ -1201,7 +1277,7 @@ namespace pcpp } static constexpr size_t FIXED_LEN = sizeof(vehicle_announcement); static constexpr size_t SYNC_STATUS_OFFSET = FIXED_LEN; - static constexpr size_t SYNC_STATUS_LEN = 1; + static constexpr size_t SYNC_STATUS_LEN = sizeof(uint8_t); static constexpr size_t OPT_LEN = SYNC_STATUS_OFFSET + SYNC_STATUS_LEN; }; @@ -1237,7 +1313,6 @@ namespace pcpp void setSourceAddress(uint16_t address); /// @brief Returns a human-readable summary of the message. - /// @return A string summarizing the Alive Check Response. std::string getSummary() const; /// @brief Returns the DoIP payload type. @@ -1255,8 +1330,17 @@ namespace pcpp } private: - static constexpr size_t SOURCE_ADDRESS_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t FIXED_LEN = SOURCE_ADDRESS_OFFSET + DOIP_SOURCE_ADDRESS_LEN; +#pragma pack(push, 1) + struct alive_check_response : doiphdr + { + uint16_t sourceAddress; + }; +#pragma pack(pop) + alive_check_response* getAliveCheckResponse() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(alive_check_response); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1287,11 +1371,10 @@ namespace pcpp DoIpDiagnosticPowerModeCodes getPowerModeCode() const; /// @brief Sets the power mode code. - /// @param[in] code The new diagnostic power mode code. + /// @param[in] code enum DoIpDiagnosticPowerModeCodes representing the power mode code to set. void setPowerModeCode(DoIpDiagnosticPowerModeCodes code); /// @brief Returns a human-readable summary of the message. - /// @return A string summarizing the Diagnostic Power Mode Response. std::string getSummary() const; /// @brief Returns the DoIP payload type. @@ -1310,9 +1393,17 @@ namespace pcpp } private: - static constexpr size_t POWER_MODE_CODE_OFFSET = DOIP_HEADER_LEN; - static constexpr size_t POWER_MODE_CODE_LEN = sizeof(uint8_t); - static constexpr size_t FIXED_LEN = POWER_MODE_CODE_OFFSET + POWER_MODE_CODE_LEN; +#pragma pack(push, 1) + struct diagnostic_power_mode_response : doiphdr + { + uint8_t powerModeCode; + }; +#pragma pack(pop) + diagnostic_power_mode_response* getDiagnosticPowerModeResponse() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(diagnostic_power_mode_response); }; //~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1349,7 +1440,7 @@ namespace pcpp } /// @brief Gets the type of the DoIP node. - /// @return The DoIP entity status value. + /// @return enum DoIpEntityStatusResponseCode representing the node type. DoIpEntityStatusResponseCode getNodeType() const; /// @brief Gets the maximum number of concurrent sockets supported. @@ -1361,11 +1452,13 @@ namespace pcpp uint8_t getCurrentlyOpenSockets() const; /// @brief Gets the optional maximum data size field. - /// @return Pointer to a 4-byte array representing max data size, or nullptr if not set. - const uint8_t* getMaxDataSize() const; + /// @throws std::runtime_error if the max data size is not present. + /// @note To use this method safely, check beforehand if the max data size is present using hasMaxDataSize(). + /// @return The maximum data size in bytes. + uint32_t getMaxDataSize() const; /// @brief Sets the DoIP node type. - /// @param[in] status New DoIP entity status. + /// @param[in] status enum DoIpEntityStatusResponseCode representing the node type to set. void setNodeType(DoIpEntityStatusResponseCode status); /// @brief Sets the maximum number of concurrent sockets. @@ -1377,8 +1470,8 @@ namespace pcpp void setCurrentlyOpenSockets(uint8_t sockets); /// @brief Sets the maximum data size field. - /// @param[in] data 4-byte array representing the max data size. - void setMaxDataSize(const std::array& data); + /// @param[in] data uint32_t representing the max data size. + void setMaxDataSize(uint32_t data); /// @brief Checks if the optional max data size is present. /// @return True if max data size is available, false otherwise. @@ -1439,22 +1532,7 @@ namespace pcpp DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief default c'tor. - DoIpDiagnosticBase() {}; - -/// @struct common_diagnostic_header -/// Common first diagnostic data in DoIP -/// messages (diagnostic/diagnosticAck/diagnosticNack). -/// common_diagnostic_header message structure (extends DoIP header). -#pragma pack(push, 1) - struct common_diagnostic_header : doiphdr - { - /// @brief Diagnostic source address - uint16_t sourceAddress; - - /// @brief Diagnostic target address - uint16_t targetAddress; - }; -#pragma pack(pop) + DoIpDiagnosticBase(size_t length) : DoIpLayer(length) {}; /// @brief Gets the source logical address of the message. /// @return 16-bit address of the source ECU. @@ -1465,18 +1543,32 @@ namespace pcpp uint16_t getTargetAddress() const; /// @brief Sets the source logical address. - /// @param[in] sourceAddress New 16-bit source address. + /// @param[in] sourceAddress 16-bit source address. void setSourceAddress(uint16_t sourceAddress); /// @brief Sets the target logical address. - /// @param[in] targetAddress New 16-bit target address. + /// @param[in] targetAddress 16-bit target address. void setTargetAddress(uint16_t targetAddress); /// @brief Returns a human-readable summary of the message content. /// @return A string summarizing the diagnostic message. virtual std::string getSummary() const = 0; - private: + protected: +/// @struct common_diagnostic_header +/// Common first diagnostic data in DoIP +/// messages (diagnostic/diagnosticAck/diagnosticNack). +/// common_diagnostic_header message structure (extends DoIP header). +#pragma pack(push, 1) + struct common_diagnostic_header : doiphdr + { + /// @brief Diagnostic source address + uint16_t sourceAddress; + + /// @brief Diagnostic target address + uint16_t targetAddress; + }; +#pragma pack(pop) common_diagnostic_header* getCommonDiagnosticHeader() const { return reinterpret_cast(m_Data); @@ -1541,7 +1633,7 @@ namespace pcpp private: static constexpr size_t DIAGNOSTIC_DATA_OFFSET = sizeof(common_diagnostic_header); - static constexpr size_t MIN_LEN = DIAGNOSTIC_DATA_OFFSET + 1; /*Min diagnostic message Len*/ + static constexpr size_t MIN_LEN = DIAGNOSTIC_DATA_OFFSET + 1; /*Min diagnostic request Len*/ }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1560,18 +1652,23 @@ namespace pcpp DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Gets the acknowledgment/nack code (1-byte). + /// @return The acknowledgment/nack code. uint8_t getResponseCode() const; /// @brief Sets the acknowledgment/nack code (1-byte). + /// @param[in] code The acknowledgment/nack code to set. void setResponseCode(uint8_t code); /// @brief Gets the optional previously echoed diagnostic message. + /// @return A vector containing the previously echoed diagnostic message. const std::vector getPreviousMessage() const; /// @brief Checks if a previous message is attached. + /// @return true if a previous message is present, false otherwise. bool hasPreviousMessage() const; /// @brief Sets the previous echoed diagnostic message. + /// @param[in] msg A vector containing the previously echoed diagnostic message. void setPreviousMessage(const std::vector& msg); /// @brief Clears the previously stored diagnostic message. @@ -1589,9 +1686,17 @@ namespace pcpp DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type); private: - static constexpr size_t DIAGNOSTIC_CODE_OFFSET = sizeof(common_diagnostic_header); - static constexpr size_t DIAGNOSTIC_CODE_LEN = sizeof(uint8_t); - static constexpr size_t FIXED_LEN = DIAGNOSTIC_CODE_OFFSET + DIAGNOSTIC_CODE_LEN; +#pragma pack(push, 1) + struct diagnostic_response_message_base : common_diagnostic_header + { + uint8_t diagnosticCode; + }; +#pragma pack(pop) + diagnostic_response_message_base* getDiagnosticResponseMessageBase() const + { + return reinterpret_cast(m_Data); + } + static constexpr size_t FIXED_LEN = sizeof(diagnostic_response_message_base); static constexpr size_t PREVIOUS_MSG_OFFSET = FIXED_LEN; }; @@ -1621,9 +1726,11 @@ namespace pcpp DoIpDiagnosticAckMessage(uint16_t sourceAddress, uint16_t targetAddress, DoIpDiagnosticAckCodes ackCode); /// @brief Gets the diagnostic acknowledgment code. + /// @return enum DoIpDiagnosticAckCodes describing the acknowledgment code. DoIpDiagnosticAckCodes getAckCode() const; /// @brief Sets the acknowledgment code. + /// @param[in] code enum DoIpDiagnosticAckCodes describing the acknowledgment code. void setAckCode(DoIpDiagnosticAckCodes code); /// @brief Returns a human-readable summary of the message. @@ -1663,9 +1770,11 @@ namespace pcpp DoIpDiagnosticMessageNackCodes nackCode); /// @brief Gets the negative acknowledgment code. + /// @return enum DoIpDiagnosticMessageNackCodes describing the negative acknowledgment code. DoIpDiagnosticMessageNackCodes getNackCode() const; /// @brief Sets the negative acknowledgment code. + /// @param[in] code enum DoIpDiagnosticMessageNackCodes describing the negative acknowledgment code. void setNackCode(DoIpDiagnosticMessageNackCodes code); /// @brief Returns a human-readable summary of the message. @@ -1707,6 +1816,7 @@ namespace pcpp { return DoIpPayloadTypes::ALIVE_CHECK_REQUEST; } + /// @brief Checks if the Alive Check Request data length is valid. /// @param[in] dataLen Length of the data buffer. /// @return true if the data length is valid, false otherwise. diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 144c82ec45..e79d3857f6 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -6,6 +6,7 @@ #include "DoIpLayer.h" #include "GeneralUtils.h" #include "PayloadLayer.h" +#include "EndianPortable.h" namespace pcpp { @@ -17,6 +18,7 @@ namespace pcpp { DoIpActivationTypes::DEFAULT, "Default" }, { DoIpActivationTypes::WWH_OBD, "WWH-OBD" }, { DoIpActivationTypes::CENTRAL_SECURITY, "Central security" }, + { DoIpActivationTypes::UNKNOWN, "Unknown" }, }; // This unordered map provides human-readable descriptions for each Nack code related to @@ -28,6 +30,7 @@ namespace pcpp { DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH, "Invalid payload length" }, { DoIpGenericHeaderNackCodes::MESSAGE_TOO_LARGE, "Message too large" }, { DoIpGenericHeaderNackCodes::OUT_OF_MEMORY, "Out of memory" }, + { DoIpGenericHeaderNackCodes::UNKNOWN, "Unknown" } }; // This unordered map provides human-readable descriptions for each action code related to @@ -50,7 +53,8 @@ namespace pcpp { DoIpActionCodes::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, { DoIpActionCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, { DoIpActionCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" } + { DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED, "Routing activation required to initiate central security" }, + { DoIpActionCodes::UNKNOWN, "Unknown" } }; // This unordered map provides human-readable descriptions for each routing response code @@ -79,7 +83,8 @@ namespace pcpp { DoIpRoutingResponseCodes::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, - { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" } + { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" }, + { DoIpRoutingResponseCodes::UNKNOWN, "Unknown routing activation response code" } }; // This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code @@ -95,6 +100,7 @@ namespace pcpp { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, + { DoIpDiagnosticMessageNackCodes::UNKNOWN, "Unknown NACK code" } }; // This unordered map provides human-readable descriptions for each power mode code @@ -104,6 +110,7 @@ namespace pcpp { DoIpDiagnosticPowerModeCodes::NOT_READY, "not ready" }, { DoIpDiagnosticPowerModeCodes::READY, "ready" }, { DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED, "not supported" }, + { DoIpDiagnosticPowerModeCodes::UNKNOWN, "unknown" } }; // This unordered map provides human-readable descriptions for the entity status codes @@ -112,12 +119,14 @@ namespace pcpp static const std::unordered_map DoIpEnumToStringEntityStatusNodeTypes{ { DoIpEntityStatusResponseCode::NODE, "DoIP node" }, { DoIpEntityStatusResponseCode::GATEWAY, "DoIP gateway" }, + { DoIpEntityStatusResponseCode::UNKNOWN, "Unknown" } }; // This unordered map provides a human-readable description for the DoIP acknowledgement // code `ACK`, which is used to confirm the successful reception or processing of a message. static const std::unordered_map DoIpEnumToStringAckCode{ - { DoIpDiagnosticAckCodes::ACK, "ACK" }, + { DoIpDiagnosticAckCodes::ACK, "ACK" }, + { DoIpDiagnosticAckCodes::UNKNOWN, "Unknown" } }; // This unordered map provides a human-readable string for each synchronization status @@ -140,7 +149,8 @@ namespace pcpp { DoIpSyncStatus::RESERVED_ISO_0x0D, "Reserved by ISO 13400" }, { DoIpSyncStatus::RESERVED_ISO_0x0E, "Reserved by ISO 13400" }, { DoIpSyncStatus::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, - { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" } + { DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED, "VIN and/or GID are not synchronized" }, + { DoIpSyncStatus::UNKNOWN, "Unknown" } }; // This unordered map provides human-readable descriptions for each version of the @@ -153,7 +163,7 @@ namespace pcpp { DoIpProtocolVersion::Version03Iso2019, "DoIP ISO 13400-2:2019" }, { DoIpProtocolVersion::Version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, { DoIpProtocolVersion::ReservedVersion, "Reserved" }, - { DoIpProtocolVersion::UnknownVersion, "Unknown Protocol Version" } + { DoIpProtocolVersion::UnknownVersion, "Unknown Protocol Version" }, }; // This unordered map provides human-readable descriptions for each payload type @@ -179,9 +189,9 @@ namespace pcpp { DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, "Diagnostic message Nack" } }; - DoIpLayer::DoIpLayer() + DoIpLayer::DoIpLayer(size_t length) { - m_DataLen = DOIP_HEADER_LEN; + m_DataLen = length; m_Protocol = DOIP; m_Data = new uint8_t[m_DataLen]{}; } @@ -190,6 +200,32 @@ namespace pcpp : Layer(data, dataLen, prevLayer, packet, DOIP) {} + bool DoIpLayer::isDataValid(uint8_t* data, size_t dataLen) + { + if (data == nullptr || dataLen < DOIP_HEADER_LEN) + return false; + + auto* doipHeader = reinterpret_cast(data); + const uint8_t version = doipHeader->protocolVersion; + const uint8_t inVersion = doipHeader->invertProtocolVersion; + const uint16_t payloadRaw = doipHeader->payloadType; + const uint32_t lengthRaw = doipHeader->payloadLength; + + const uint32_t payloadLen = htobe32(lengthRaw); + + if (!isPayloadTypeValid(payloadRaw)) + return false; + // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() + const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); + if (!isProtocolVersionValid(version, inVersion, payloadType)) + return false; + + if (!isPayloadLengthValid(payloadLen, dataLen)) + return false; + + return true; + } + DoIpLayer* DoIpLayer::parseDoIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) { doiphdr* doipHeader = reinterpret_cast(data); @@ -377,9 +413,9 @@ namespace pcpp DoIpRoutingActivationRequest::DoIpRoutingActivationRequest(uint16_t sourceAddress, DoIpActivationTypes activationType) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); - extendLayer(DOIP_HEADER_LEN, FIXED_LEN - DOIP_HEADER_LEN); auto* payload = getRoutingRequest(); payload->sourceAddress = htobe16(sourceAddress); @@ -400,7 +436,16 @@ namespace pcpp DoIpActivationTypes DoIpRoutingActivationRequest::getActivationType() const { - return static_cast(getRoutingRequest()->activationType); + auto activationType = static_cast(getRoutingRequest()->activationType); + switch (activationType) + { + case DoIpActivationTypes::DEFAULT: + case DoIpActivationTypes::WWH_OBD: + case DoIpActivationTypes::CENTRAL_SECURITY: + return activationType; + default: + return DoIpActivationTypes::UNKNOWN; + } } void DoIpRoutingActivationRequest::setActivationType(DoIpActivationTypes activationType) @@ -423,9 +468,18 @@ namespace pcpp return (m_DataLen == OPT_LEN); } - const uint8_t* DoIpRoutingActivationRequest::getReservedOem() const + const std::array DoIpRoutingActivationRequest::getReservedOem() const { - return hasReservedOem() ? (m_Data + FIXED_LEN) : nullptr; + std::array reservedOem; + if (hasReservedOem()) + { + memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); + return reservedOem; + } + else + { + throw std::runtime_error("Reserved OEM field not present!"); + } } void DoIpRoutingActivationRequest::setReservedOem(const std::array& reservedOem) @@ -463,7 +517,8 @@ namespace pcpp oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (hasReservedOem()) - oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << '\n'; + oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem().data(), DOIP_RESERVED_OEM_LEN) + << '\n'; return oss.str(); } @@ -479,9 +534,9 @@ namespace pcpp DoIpRoutingActivationResponse::DoIpRoutingActivationResponse(uint16_t logicalAddressExternalTester, uint16_t sourceAddress, DoIpRoutingResponseCodes responseCode) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); - extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); auto* payload = getRoutingResponse(); payload->logicalAddressExternalTester = htobe16(logicalAddressExternalTester); @@ -512,7 +567,11 @@ namespace pcpp DoIpRoutingResponseCodes DoIpRoutingActivationResponse::getResponseCode() const { - return static_cast(getRoutingResponse()->responseCode); + uint8_t code = getRoutingResponse()->responseCode; + if (code <= static_cast(DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED)) + return static_cast(code); + else + return DoIpRoutingResponseCodes::UNKNOWN; } void DoIpRoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) @@ -535,9 +594,18 @@ namespace pcpp return (m_DataLen == OPT_LEN); } - const uint8_t* DoIpRoutingActivationResponse::getReservedOem() const + const std::array DoIpRoutingActivationResponse::getReservedOem() const { - return hasReservedOem() ? (m_Data + FIXED_LEN) : nullptr; + std::array reservedOem; + if (hasReservedOem()) + { + memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); + return reservedOem; + } + else + { + throw std::runtime_error("Reserved OEM field not present!"); + } } void DoIpRoutingActivationResponse::setReservedOem(const std::array& reservedOem) @@ -547,7 +615,7 @@ namespace pcpp extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); - memcpy((m_Data + FIXED_LEN), &reservedOem, DOIP_RESERVED_OEM_LEN); + memcpy((m_Data + FIXED_LEN), reservedOem.data(), DOIP_RESERVED_OEM_LEN); } void DoIpRoutingActivationResponse::clearReservedOem() @@ -577,7 +645,8 @@ namespace pcpp oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; if (hasReservedOem()) - oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem(), DOIP_RESERVED_OEM_LEN) << "\n"; + oss << "Reserved by OEM: " << pcpp::byteArrayToHexString(getReservedOem().data(), DOIP_RESERVED_OEM_LEN) + << "\n"; return oss.str(); } @@ -589,26 +658,24 @@ namespace pcpp : DoIpLayer(data, dataLen, prevLayer, packet) {} - DoIpGenericHeaderNack::DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) + DoIpGenericHeaderNack::DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), NACK_CODE_LEN); - extendLayer(NACK_CODE_OFFSET, NACK_CODE_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setNackCode(nackCode); } DoIpGenericHeaderNackCodes DoIpGenericHeaderNack::getNackCode() const { - return static_cast(*(m_Data + NACK_CODE_OFFSET)); + uint8_t nackCode = getGenericHeaderNack()->nackCode; + if (nackCode <= static_cast(DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH)) + return static_cast(nackCode); + else + return DoIpGenericHeaderNackCodes::UNKNOWN; } void DoIpGenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) { - *(m_Data + NACK_CODE_OFFSET) = static_cast(nackCode); - } - - void DoIpGenericHeaderNack::setNackCode(uint8_t nackCode) - { - *(m_Data + NACK_CODE_OFFSET) = nackCode; + getGenericHeaderNack()->nackCode = static_cast(nackCode); } std::string DoIpGenericHeaderNack::getSummary() const @@ -616,15 +683,8 @@ namespace pcpp std::ostringstream oss; DoIpGenericHeaderNackCodes nackCode = getNackCode(); auto it = DoIpEnumToStringGenericHeaderNackCodes.find(nackCode); - if (it != DoIpEnumToStringGenericHeaderNackCodes.end()) - { - oss << "Generic header nack code: " << it->second << " (0x" << std::hex << static_cast(nackCode) - << ")\n"; - } - else - { - oss << "Generic header nack code: Unknown (0x" << std::hex << static_cast(nackCode) << ")\n"; - } + oss << "Generic header nack code: " << it->second << " (0x" << std::hex + << static_cast(getGenericHeaderNack()->nackCode) << ")\n"; return oss.str(); } @@ -638,20 +698,20 @@ namespace pcpp DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID( const std::array& eid) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); - extendLayer(EID_OFFSET, DOIP_EID_LEN); setEID(eid); } std::array DoIpVehicleIdentificationRequestEID::getEID() const { - return *reinterpret_cast*>(m_Data + EID_OFFSET); + return getVehicleIdentificationRequestEID()->eid; } void DoIpVehicleIdentificationRequestEID::setEID(const std::array& eid) { - memcpy(m_Data + EID_OFFSET, &eid, DOIP_EID_LEN); + getVehicleIdentificationRequestEID()->eid = eid; } std::string DoIpVehicleIdentificationRequestEID::getSummary() const @@ -671,20 +731,20 @@ namespace pcpp DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN( const std::array& vin) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); - extendLayer(VIN_OFFSET, DOIP_VIN_LEN); setVIN(vin); } std::array DoIpVehicleIdentificationRequestVIN::getVIN() const { - return *reinterpret_cast*>(m_Data + VIN_OFFSET); + return getVehicleIdentificationRequestVIN()->vin; } void DoIpVehicleIdentificationRequestVIN::setVIN(const std::array& vin) { - memcpy(m_Data + VIN_OFFSET, &vin, DOIP_VIN_LEN); + getVehicleIdentificationRequestVIN()->vin = vin; } std::string DoIpVehicleIdentificationRequestVIN::getSummary() const @@ -706,9 +766,9 @@ namespace pcpp const std::array& eid, const std::array& gid, DoIpActionCodes actionCode) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); - extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setVIN(vin); setLogicalAddress(logicalAddress); @@ -735,11 +795,27 @@ namespace pcpp } DoIpActionCodes DoIpVehicleAnnouncement::getFurtherActionRequired() const { - return static_cast(getVehicleAnnouncement()->actionCode); + uint8_t actionCode = getVehicleAnnouncement()->actionCode; + if (actionCode <= static_cast(DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED)) + return static_cast(actionCode); + else + return DoIpActionCodes::UNKNOWN; } - const DoIpSyncStatus* DoIpVehicleAnnouncement::getSyncStatus() const + + DoIpSyncStatus DoIpVehicleAnnouncement::getSyncStatus() const { - return hasSyncStatus() ? reinterpret_cast(m_Data + SYNC_STATUS_OFFSET) : nullptr; + if (hasSyncStatus()) + { + uint8_t syncStatus = *(m_Data + SYNC_STATUS_OFFSET); + if (syncStatus <= static_cast(DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED)) + return static_cast(syncStatus); + else + return DoIpSyncStatus::UNKNOWN; + } + else + { + throw std::runtime_error("Sync status field not present!"); + } } void DoIpVehicleAnnouncement::clearSyncStatus() @@ -803,16 +879,15 @@ namespace pcpp oss << "GID: " << pcpp::byteArrayToHexString(getGID().data(), DOIP_GID_LEN) << "\n"; auto it = DoIpEnumToStringActionCodes.find(getFurtherActionRequired()); - oss << "Further action required: " << ((it != DoIpEnumToStringActionCodes.end()) ? it->second : "Unknown") - << " (0x" << std::hex << static_cast(getFurtherActionRequired()) << ")\n"; + oss << "Further action required: " << it->second << " (0x" << std::hex + << static_cast(getVehicleAnnouncement()->actionCode) << ")\n"; if (hasSyncStatus()) { - auto syncStatus = *getSyncStatus(); + auto syncStatus = getSyncStatus(); auto itSync = DoIpEnumToStringSyncStatus.find(syncStatus); - oss << "VIN/GID sync status: " - << ((itSync != DoIpEnumToStringSyncStatus.end()) ? itSync->second : "Unknown") << " (0x" << std::hex - << static_cast(syncStatus) << ")\n"; + oss << "VIN/GID sync status: " << itSync->second << " (0x" << std::hex + << static_cast(*(m_Data + SYNC_STATUS_OFFSET)) << ")\n"; } return oss.str(); @@ -825,21 +900,20 @@ namespace pcpp : DoIpLayer(data, dataLen, prevLayer, packet) {} - DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint16_t sourceAddress) + DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint16_t sourceAddress) : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_SOURCE_ADDRESS_LEN); - extendLayer(DOIP_HEADER_LEN, DOIP_SOURCE_ADDRESS_LEN); setSourceAddress(sourceAddress); } uint16_t DoIpAliveCheckResponse::getSourceAddress() const { - return htobe16(*reinterpret_cast(m_Data + SOURCE_ADDRESS_OFFSET)); + return htobe16(getAliveCheckResponse()->sourceAddress); } void DoIpAliveCheckResponse::setSourceAddress(uint16_t sourceAddress) { - *reinterpret_cast(m_Data + SOURCE_ADDRESS_OFFSET) = htobe16(sourceAddress); + getAliveCheckResponse()->sourceAddress = htobe16(sourceAddress); } std::string DoIpAliveCheckResponse::getSummary() const @@ -858,20 +932,24 @@ namespace pcpp {} DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) + : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), POWER_MODE_CODE_LEN); - extendLayer(POWER_MODE_CODE_OFFSET, POWER_MODE_CODE_LEN); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setPowerModeCode(code); } DoIpDiagnosticPowerModeCodes DoIpDiagnosticPowerModeResponse::getPowerModeCode() const { - return static_cast(*(m_Data + POWER_MODE_CODE_OFFSET)); + uint8_t powerModeCode = getDiagnosticPowerModeResponse()->powerModeCode; + if (powerModeCode <= static_cast(DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED)) + return static_cast(powerModeCode); + else + return DoIpDiagnosticPowerModeCodes::UNKNOWN; } void DoIpDiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) { - *(m_Data + POWER_MODE_CODE_OFFSET) = static_cast(code); + getDiagnosticPowerModeResponse()->powerModeCode = static_cast(code); } std::string DoIpDiagnosticPowerModeResponse::getSummary() const @@ -879,9 +957,8 @@ namespace pcpp std::ostringstream oss; DoIpDiagnosticPowerModeCodes powerModeCode = getPowerModeCode(); auto it = DoIpEnumToStringDiagnosticPowerModeCodes.find(powerModeCode); - oss << "Diagnostic power mode: " - << ((it != DoIpEnumToStringDiagnosticPowerModeCodes.end()) ? it->second : "Unknown") << " (0x" << std::hex - << static_cast(powerModeCode) << ")\n"; + oss << "Diagnostic power mode: " << it->second << " (0x" << std::hex + << static_cast(getDiagnosticPowerModeResponse()->powerModeCode) << ")\n"; return oss.str(); } @@ -894,9 +971,9 @@ namespace pcpp DoIpEntityStatusResponse::DoIpEntityStatusResponse(DoIpEntityStatusResponseCode nodeType, uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) + : DoIpLayer(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); - extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setNodeType(nodeType); setMaxConcurrentSockets(maxConcurrentSockets); @@ -904,8 +981,13 @@ namespace pcpp } DoIpEntityStatusResponseCode DoIpEntityStatusResponse::getNodeType() const { - return static_cast(getEntityStatusResponsePtr()->nodeType); + uint8_t nodeType = getEntityStatusResponsePtr()->nodeType; + if (nodeType <= static_cast(DoIpEntityStatusResponseCode::NODE)) + return static_cast(nodeType); + else + return DoIpEntityStatusResponseCode::UNKNOWN; } + uint8_t DoIpEntityStatusResponse::getMaxConcurrentSockets() const { return getEntityStatusResponsePtr()->maxConcurrentSockets; @@ -914,9 +996,14 @@ namespace pcpp { return getEntityStatusResponsePtr()->currentlyOpenSockets; } - const uint8_t* DoIpEntityStatusResponse::getMaxDataSize() const + uint32_t DoIpEntityStatusResponse::getMaxDataSize() const { - return hasMaxDataSize() ? (m_Data + MAX_DATA_SIZE_OFFSET) : nullptr; + if (!hasMaxDataSize()) + throw std::runtime_error("Max data size field not present!"); + + uint32_t value; + std::memcpy(&value, m_Data + MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); + return htobe32(value); } void DoIpEntityStatusResponse::setNodeType(DoIpEntityStatusResponseCode nodeType) { @@ -948,13 +1035,14 @@ namespace pcpp getEntityStatusResponsePtr()->currentlyOpenSockets = sockets; } - void DoIpEntityStatusResponse::setMaxDataSize(const std::array& data) + void DoIpEntityStatusResponse::setMaxDataSize(uint32_t data) { if (!hasMaxDataSize()) { extendLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); } - memcpy(m_Data + MAX_DATA_SIZE_OFFSET, &data, MAX_DATA_SIZE_LEN); + uint32_t value = htobe32(data); + memcpy(m_Data + MAX_DATA_SIZE_OFFSET, &value, MAX_DATA_SIZE_LEN); setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); } @@ -1011,10 +1099,9 @@ namespace pcpp DoIpDiagnosticMessage::DoIpDiagnosticMessage(uint16_t sourceAddress, uint16_t targetAddress, const std::vector& diagData) + : DoIpDiagnosticBase(MIN_LEN + diagData.size()) { - size_t payloadLen = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + diagData.size(); - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), payloadLen); - extendLayer(DOIP_HEADER_LEN, payloadLen); + setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), MIN_LEN + diagData.size()); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); setDiagnosticData(diagData); @@ -1060,16 +1147,21 @@ namespace pcpp DoIpDiagnosticResponseMessageBase::DoIpDiagnosticResponseMessageBase(uint16_t sourceAddress, uint16_t targetAddress, DoIpPayloadTypes type) + : DoIpDiagnosticBase(FIXED_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); - extendLayer(DOIP_HEADER_LEN, (FIXED_LEN - DOIP_HEADER_LEN)); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); } + void DoIpDiagnosticResponseMessageBase::setResponseCode(uint8_t code) + { + getDiagnosticResponseMessageBase()->diagnosticCode = code; + } + uint8_t DoIpDiagnosticResponseMessageBase::getResponseCode() const { - return static_cast(*(m_Data + DIAGNOSTIC_CODE_OFFSET)); + return static_cast(getDiagnosticResponseMessageBase()->diagnosticCode); } const std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const @@ -1085,11 +1177,6 @@ namespace pcpp } } - void DoIpDiagnosticResponseMessageBase::setResponseCode(uint8_t code) - { - *(m_Data + DIAGNOSTIC_CODE_OFFSET) = static_cast(code); - } - bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const { return (m_DataLen > PREVIOUS_MSG_OFFSET); @@ -1139,7 +1226,10 @@ namespace pcpp DoIpDiagnosticAckCodes DoIpDiagnosticAckMessage::getAckCode() const { - return static_cast(getResponseCode()); + if (getResponseCode() == static_cast(DoIpDiagnosticAckCodes::ACK)) + return DoIpDiagnosticAckCodes::ACK; + else + return DoIpDiagnosticAckCodes::UNKNOWN; } void DoIpDiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) @@ -1154,8 +1244,7 @@ namespace pcpp oss << "Source Address: " << std::hex << "0x" << getSourceAddress() << "\n"; oss << "Target Address: " << std::hex << "0x" << getTargetAddress() << "\n"; auto it = DoIpEnumToStringAckCode.find(ackCode); - oss << "ACK code: " << ((it != DoIpEnumToStringAckCode.end()) ? it->second : "Unknown") << " (0x" - << static_cast(ackCode) << ")\n"; + oss << "ACK code: " << it->second << " (0x" << static_cast(getResponseCode()) << ")\n"; if (hasPreviousMessage()) { oss << "Previous message: " @@ -1181,7 +1270,11 @@ namespace pcpp DoIpDiagnosticMessageNackCodes DoIpDiagnosticNackMessage::getNackCode() const { - return static_cast(getResponseCode()); + uint8_t nackCode = getResponseCode(); + if (nackCode <= static_cast(DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR)) + return static_cast(nackCode); + else + return DoIpDiagnosticMessageNackCodes::UNKNOWN; } void DoIpDiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) @@ -1197,8 +1290,7 @@ namespace pcpp oss << "Target Address: 0x" << std::hex << getTargetAddress() << "\n"; auto it = DoIpEnumToStringDiagnosticNackCodes.find(nackCode); - oss << "NACK code: " << ((it != DoIpEnumToStringDiagnosticNackCodes.end()) ? it->second : "Unknown") << " (0x" - << static_cast(nackCode) << ")\n"; + oss << "NACK code: " << it->second << " (0x" << static_cast(getResponseCode()) << ")\n"; if (hasPreviousMessage()) { @@ -1211,7 +1303,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~| // DoIpAliveCheckRequest| //~~~~~~~~~~~~~~~~~~~~~~| - DoIpAliveCheckRequest::DoIpAliveCheckRequest() + DoIpAliveCheckRequest::DoIpAliveCheckRequest() : DoIpLayer(DOIP_HEADER_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } @@ -1219,7 +1311,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| // DoIpVehicleIdentificationRequest| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DoIpVehicleIdentificationRequest::DoIpVehicleIdentificationRequest() + DoIpVehicleIdentificationRequest::DoIpVehicleIdentificationRequest() : DoIpLayer(DOIP_HEADER_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } @@ -1227,7 +1319,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| // DoIpDiagnosticPowerModeRequest| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DoIpDiagnosticPowerModeRequest::DoIpDiagnosticPowerModeRequest() + DoIpDiagnosticPowerModeRequest::DoIpDiagnosticPowerModeRequest() : DoIpLayer(DOIP_HEADER_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } @@ -1235,7 +1327,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~| // DoIpEntityStatusRequest| //~~~~~~~~~~~~~~~~~~~~~~~~| - DoIpEntityStatusRequest::DoIpEntityStatusRequest() + DoIpEntityStatusRequest::DoIpEntityStatusRequest() : DoIpLayer(DOIP_HEADER_LEN) { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); } diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index d68b8bd7d6..403bbf5154 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -48,11 +48,9 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getActivationType(), pcpp::DoIpActivationTypes::DEFAULT, enumclass); std::array isoField = { 0x0, 0x0, 0x0, 0x0 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), isoField); - PTF_ASSERT_TRUE(doipLayer->hasReservedOem()); - PTF_ASSERT_NOT_NULL(doipLayer->getReservedOem()); std::array oemField = { 0x0, 0x0, 0x0, 0x0 }; - PTF_ASSERT_BUF_COMPARE(doipLayer->getReservedOem(), oemField.data(), 4); + PTF_ASSERT_BUF_COMPARE(doipLayer->getReservedOem().data(), oemField.data(), 4); PTF_ASSERT_EQUAL( doipLayer->getSummary(), @@ -107,7 +105,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(doipLayer.getActivationType(), pcpp::DoIpActivationTypes::DEFAULT, enumclass); PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); - PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem(), oemField.data(), 4); + PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem().data(), oemField.data(), 4); doipLayer.clearReservedOem(); @@ -115,7 +113,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - 4); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 4) - 15, bytes, 15); PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), isoReserved); - PTF_ASSERT_TRUE(doipLayer.getReservedOem() == nullptr); + PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); PTF_ASSERT_EQUAL(doipLayer.getSummary(), "Source Address: 0xe80\nActivation type: Default (0x0)\nReserved by ISO: 01020304\n"); doipLayer.setReservedOem(oemField); @@ -161,7 +159,14 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) std::array resISO{}; PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), resISO); PTF_ASSERT_FALSE(doipLayer->hasReservedOem()); - PTF_ASSERT_TRUE(doipLayer->getReservedOem() == nullptr); + try + { + doipLayer->getReservedOem(); + } + catch (const std::runtime_error& e) + { + PTF_ASSERT_EQUAL(std::string(e.what()), "Reserved OEM field not present!"); + } PTF_ASSERT_EQUAL( doipLayer->getSummary(), "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 00000000\n"); @@ -208,7 +213,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) std::array resOEM{ 0x5, 0x5, 0x5, 0x5 }; PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), resISO); PTF_ASSERT_TRUE(doipLayer.hasReservedOem()); - PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem(), resOEM.data(), 4); + PTF_ASSERT_BUF_COMPARE(doipLayer.getReservedOem().data(), resOEM.data(), 4); PTF_ASSERT_EQUAL( doipLayer.getSummary(), "Logical Address (Tester): 0xe80\nSource Address: 0x4010\nRouting activation response code: Routing successfully activated (0x10)\nReserved by ISO: 01020304\nReserved by OEM: 05050505\n"); @@ -481,7 +486,14 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); PTF_ASSERT_VECTORS_EQUAL(doipLayer->getGID(), gid); PTF_ASSERT_FALSE(doipLayer->hasSyncStatus()); - PTF_ASSERT_NULL(doipLayer->getSyncStatus()); + try + { + doipLayer->getSyncStatus(); + } + catch (const std::runtime_error& e) + { + PTF_ASSERT_EQUAL(std::string(e.what()), "Sync status field not present!"); + } } // DoIpVehicleAnnouncementPacketParsing // DoIpVehicleAnnouncementPacketCreation @@ -528,13 +540,12 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); PTF_ASSERT_VECTORS_EQUAL(doipLayer->getGID(), gid); PTF_ASSERT_TRUE(doipLayer->hasSyncStatus()); - PTF_ASSERT_EQUAL(*doipLayer->getSyncStatus(), pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getSyncStatus(), pcpp::DoIpSyncStatus::VIN_AND_OR_GID_ARE_SINCHRONIZED, enumclass); PTF_ASSERT_EQUAL( doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\nVIN/GID sync status: VIN and/or GID are synchronized (0x0)\n"); doipLayer->clearSyncStatus(); PTF_ASSERT_FALSE(doipLayer->hasSyncStatus()); - PTF_ASSERT_TRUE(doipLayer->getSyncStatus() == nullptr); PTF_ASSERT_EQUAL( doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\n"); @@ -775,8 +786,9 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getNodeType(), pcpp::DoIpEntityStatusResponseCode::GATEWAY, enumclass); PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 1); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 0); - const std::array& maxDataSize{ 0x0, 0x0, 0x0f, 0xff }; - PTF_ASSERT_BUF_COMPARE(doipLayer->getMaxDataSize(), maxDataSize.data(), 4); + PTF_ASSERT_TRUE(doipLayer->hasMaxDataSize()); + const uint32_t maxDataSize = 0x000000fff; + PTF_ASSERT_EQUAL(doipLayer->getMaxDataSize(), maxDataSize); } // DoIpEntityStatusResponsePacketParsing // DoIpEntityStatusResponsePacketCreation @@ -794,7 +806,8 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_TRUE(doIpPacket.addLayer(&udpLayer)); doIpPacket.computeCalculateFields(); - unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x5, 0x2, 0xff, 0xff, 0xff, 0xff }; + unsigned char bytesWithoutMaxDataSize[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x5, 0x2 }; + unsigned char bytes[] = { 0x2, 0xfd, 0x40, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x5, 0x2, 0x11, 0x22, 0x33, 0x44 }; pcpp::DoIpEntityStatusResponse data(pcpp::DoIpEntityStatusResponseCode::GATEWAY, 0, 0); PTF_ASSERT_TRUE(doIpPacket.addLayer(&data)); @@ -804,7 +817,20 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) doipLayer->setNodeType(pcpp::DoIpEntityStatusResponseCode::GATEWAY); doipLayer->setMaxConcurrentSockets(5); doipLayer->setCurrentlyOpenSockets(2); - const std::array& maxDataSize{ 0xff, 0xff, 0xff, 0xff }; + PTF_ASSERT_FALSE(doipLayer->hasMaxDataSize()); + try + { + doipLayer->getMaxDataSize(); + } + catch (const std::runtime_error& e) + { + PTF_ASSERT_EQUAL(std::string(e.what()), "Max data size field not present!"); + } + PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 53); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytesWithoutMaxDataSize, 11); + + // add max data size + const uint32_t maxDataSize = 0x11223344; doipLayer->setMaxDataSize(maxDataSize); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 57); @@ -821,10 +847,9 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_EQUAL(doipLayer->getMaxConcurrentSockets(), 5); PTF_ASSERT_EQUAL(doipLayer->getCurrentlyOpenSockets(), 2); PTF_ASSERT_TRUE(doipLayer->hasMaxDataSize()); - PTF_ASSERT_BUF_COMPARE(doipLayer->getMaxDataSize(), maxDataSize.data(), 4); + PTF_ASSERT_EQUAL(doipLayer->getMaxDataSize(), maxDataSize); doipLayer->clearMaxDataSize(); PTF_ASSERT_FALSE(doipLayer->hasMaxDataSize()); - PTF_ASSERT_TRUE(doipLayer->getMaxDataSize() == nullptr); } // DoIpEntityStatusResponsePacketCreation // DoIpDiagnosticMessagePacketParsing From c7fd6644d24843e107c9e0456b1ab7a0797223ff Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Mon, 12 May 2025 20:35:30 -0400 Subject: [PATCH 38/43] fix endian import --- Packet++/header/DoIpLayer.h | 2 +- Packet++/src/DoIpLayer.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index c7be58e77e..80c75229af 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -712,7 +712,7 @@ namespace pcpp inline bool DoIpLayer::isPayloadTypeValid(uint16_t type) { - const DoIpPayloadTypes payloadType = static_cast(htobe16(type)); + const DoIpPayloadTypes payloadType = static_cast(type); switch (payloadType) { diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index e79d3857f6..1261542fce 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -208,19 +208,17 @@ namespace pcpp auto* doipHeader = reinterpret_cast(data); const uint8_t version = doipHeader->protocolVersion; const uint8_t inVersion = doipHeader->invertProtocolVersion; - const uint16_t payloadRaw = doipHeader->payloadType; + const uint16_t payloadTypeRaw = doipHeader->payloadType; const uint32_t lengthRaw = doipHeader->payloadLength; - const uint32_t payloadLen = htobe32(lengthRaw); - - if (!isPayloadTypeValid(payloadRaw)) + if (!isPayloadTypeValid(htobe16(payloadTypeRaw))) return false; // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() - const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadRaw)); + const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadTypeRaw)); if (!isProtocolVersionValid(version, inVersion, payloadType)) return false; - if (!isPayloadLengthValid(payloadLen, dataLen)) + if (!isPayloadLengthValid(htobe32(lengthRaw), dataLen)) return false; return true; From e1beca17d372f5f88774b0378d7bb11db2f5d81e Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 13 May 2025 00:13:25 -0400 Subject: [PATCH 39/43] Reduce reservedIso variable scope --- Packet++/src/DoIpLayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 1261542fce..b38ffa3bdb 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -468,9 +468,9 @@ namespace pcpp const std::array DoIpRoutingActivationRequest::getReservedOem() const { - std::array reservedOem; if (hasReservedOem()) { + std::array reservedOem; memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); return reservedOem; } @@ -594,9 +594,9 @@ namespace pcpp const std::array DoIpRoutingActivationResponse::getReservedOem() const { - std::array reservedOem; if (hasReservedOem()) { + std::array reservedOem; memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); return reservedOem; } From ae6e41ce424a9a9ff6c9b9ed69c59479d9211f76 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Mon, 19 May 2025 10:03:27 -0400 Subject: [PATCH 40/43] fix review comments --- Packet++/header/DoIpLayer.h | 52 ++--- Packet++/src/DoIpLayer.cpp | 212 ++++++++++-------- Packet++/src/TcpLayer.cpp | 18 +- Packet++/src/UdpLayer.cpp | 7 +- ...ehicleIdentificationRequestWEIDPacket.dat} | 0 ...ehicleIdentificationRequestWVINPacket.dat} | 0 Tests/Packet++Test/TestDefinition.h | 8 +- Tests/Packet++Test/Tests/DoIpTests.cpp | 30 +-- Tests/Packet++Test/main.cpp | 8 +- 9 files changed, 173 insertions(+), 162 deletions(-) rename Tests/Packet++Test/PacketExamples/{DoIpVehicleIdentificationRequestEIDPacket.dat => DoIpVehicleIdentificationRequestWEIDPacket.dat} (100%) rename Tests/Packet++Test/PacketExamples/{DoIpVehicleIdentificationRequestVINPacket.dat => DoIpVehicleIdentificationRequestWVINPacket.dat} (100%) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 80c75229af..c78d53c3cd 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -806,7 +806,7 @@ namespace pcpp /// @throw std::runtime_error if the reserved OEM bytes are not present. /// @note To use this method safely, check beforehand if the reserved OEM bytes are present using /// hasReservedOem(). - const std::array getReservedOem() const; + std::array getReservedOem() const; /// @brief Sets the reserved OEM bytes. /// @param[in] reservedOem The reserved OEM bytes to set. @@ -918,7 +918,7 @@ namespace pcpp /// @throw std::runtime_error if the reserved OEM bytes are not present. /// @note before using this method, check beforehand if the reserved OEM bytes are present using /// hasReservedOem(). - const std::array getReservedOem() const; + std::array getReservedOem() const; /// @brief Sets the reserved OEM bytes. /// @param[in] reservedOem The reserved OEM bytes to set. @@ -1030,15 +1030,15 @@ namespace pcpp static constexpr size_t FIXED_LEN = sizeof(generic_header_nack); }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DoIpVehicleIdentificationRequestEID| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequestWEID| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DoIpVehicleIdentificationRequestEID + /// @class DoIpVehicleIdentificationRequestWEID /// @brief Represents a DoIP Vehicle Identification Request with EID. /// /// This message is used to identify a vehicle based on its Entity ID (EID). - class DoIpVehicleIdentificationRequestEID : public DoIpLayer + class DoIpVehicleIdentificationRequestWEID : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1046,11 +1046,11 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - DoIpVehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpVehicleIdentificationRequestWEID(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified EID. /// @param[in] eid A 6-byte Entity ID used for vehicle identification. - explicit DoIpVehicleIdentificationRequestEID(const std::array& eid = {}); + explicit DoIpVehicleIdentificationRequestWEID(const std::array& eid = {}); /// @brief Gets the Entity ID (EID). /// @return A 6-byte Entity ID (EID). @@ -1091,15 +1091,15 @@ namespace pcpp static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_eid); }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // DoIpVehicleIdentificationRequestVIN| - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequestWVIN| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - /// @class DoIpVehicleIdentificationRequestVIN + /// @class DoIpVehicleIdentificationRequestWVIN /// @brief Represents a DoIP Vehicle Identification Request with VIN. /// /// This message is used to identify a vehicle based on its Vehicle Identification Number (VIN). - class DoIpVehicleIdentificationRequestVIN : public DoIpLayer + class DoIpVehicleIdentificationRequestWVIN : public DoIpLayer { public: /// @brief Constructs the layer from raw DoIP packet data. @@ -1107,11 +1107,11 @@ namespace pcpp /// @param[in] dataLen Length of the raw data. /// @param[in] prevLayer Pointer to the previous layer. /// @param[in] packet Pointer to the parent packet instance. - DoIpVehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + DoIpVehicleIdentificationRequestWVIN(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /// @brief Constructs the message using the specified VIN. /// @param[in] vin A 17-byte Vehicle Identification Number. - explicit DoIpVehicleIdentificationRequestVIN(const std::array& vin = {}); + explicit DoIpVehicleIdentificationRequestWVIN(const std::array& vin = {}); /// @brief Gets the Vehicle Identification Number (VIN). /// @return A 17-byte Vehicle Identification Number (VIN). @@ -1140,16 +1140,16 @@ namespace pcpp private: #pragma pack(push, 1) - struct vehicle_identification_request_vin : doiphdr + struct vehicle_identification_request_with_vin : doiphdr { std::array vin; }; #pragma pack(pop) - vehicle_identification_request_vin* getVehicleIdentificationRequestVIN() const + vehicle_identification_request_with_vin* getVehicleIdentificationRequestWVIN() const { - return reinterpret_cast(m_Data); + return reinterpret_cast(m_Data); } - static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_vin); + static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_with_vin); }; //~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1504,7 +1504,7 @@ namespace pcpp }; #pragma pack(pop) - entity_status_response* getEntityStatusResponsePtr() const + entity_status_response* getEntityStatusResponse() const { return reinterpret_cast(m_Data); } @@ -1555,17 +1555,11 @@ namespace pcpp virtual std::string getSummary() const = 0; protected: -/// @struct common_diagnostic_header -/// Common first diagnostic data in DoIP -/// messages (diagnostic/diagnosticAck/diagnosticNack). -/// common_diagnostic_header message structure (extends DoIP header). #pragma pack(push, 1) struct common_diagnostic_header : doiphdr { - /// @brief Diagnostic source address uint16_t sourceAddress; - /// @brief Diagnostic target address uint16_t targetAddress; }; #pragma pack(pop) @@ -1605,7 +1599,7 @@ namespace pcpp /// @brief Get the diagnostic data payload. /// @return A vector containing the diagnostic data bytes. - const std::vector getDiagnosticData() const; + std::vector getDiagnosticData() const; /// @brief Returns a human-readable summary of the message content. /// @return A string summarizing the diagnostic message. @@ -1628,7 +1622,7 @@ namespace pcpp /// @return true if the data length is valid, false otherwise. static inline bool isDataLenValid(size_t dataLen) { - return (dataLen > MIN_LEN); + return (dataLen >= MIN_LEN); } private: diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index b38ffa3bdb..40480b3b4c 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -211,14 +211,14 @@ namespace pcpp const uint16_t payloadTypeRaw = doipHeader->payloadType; const uint32_t lengthRaw = doipHeader->payloadLength; - if (!isPayloadTypeValid(htobe16(payloadTypeRaw))) + if (!isPayloadTypeValid(be16toh(payloadTypeRaw))) return false; // if payload type is validated, we ensure passing a valid type to isProtocolVersionValid() - const DoIpPayloadTypes payloadType = static_cast(htobe16(payloadTypeRaw)); + const DoIpPayloadTypes payloadType = static_cast(be16toh(payloadTypeRaw)); if (!isProtocolVersionValid(version, inVersion, payloadType)) return false; - if (!isPayloadLengthValid(htobe32(lengthRaw), dataLen)) + if (!isPayloadLengthValid(be32toh(lengthRaw), dataLen)) return false; return true; @@ -228,7 +228,7 @@ namespace pcpp { doiphdr* doipHeader = reinterpret_cast(data); uint16_t payloadType = doipHeader->payloadType; - DoIpPayloadTypes detectedPayloadType = static_cast(htobe16(payloadType)); + DoIpPayloadTypes detectedPayloadType = static_cast(be16toh(payloadType)); switch (detectedPayloadType) { @@ -245,12 +245,12 @@ namespace pcpp ? new DoIpGenericHeaderNack(data, dataLen, prevLayer, packet) : nullptr; case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID: - return (DoIpVehicleIdentificationRequestEID::isDataLenValid(dataLen)) - ? new DoIpVehicleIdentificationRequestEID(data, dataLen, prevLayer, packet) + return (DoIpVehicleIdentificationRequestWEID::isDataLenValid(dataLen)) + ? new DoIpVehicleIdentificationRequestWEID(data, dataLen, prevLayer, packet) : nullptr; case DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN: - return (DoIpVehicleIdentificationRequestVIN::isDataLenValid(dataLen)) - ? new DoIpVehicleIdentificationRequestVIN(data, dataLen, prevLayer, packet) + return (DoIpVehicleIdentificationRequestWVIN::isDataLenValid(dataLen)) + ? new DoIpVehicleIdentificationRequestWVIN(data, dataLen, prevLayer, packet) : nullptr; case DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE: return (DoIpVehicleAnnouncement::isDataLenValid(dataLen)) @@ -322,8 +322,7 @@ namespace pcpp std::string DoIpLayer::getProtocolVersionAsStr() const { - auto it = DoIpEnumToStringProtocolVersion.find(getProtocolVersion()); - return (it != DoIpEnumToStringProtocolVersion.end()) ? it->second : "Unknown Protocol Version"; + return DoIpEnumToStringProtocolVersion.find(getProtocolVersion())->second; } void DoIpLayer::setProtocolVersion(DoIpProtocolVersion version) @@ -415,11 +414,10 @@ namespace pcpp { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); - auto* payload = getRoutingRequest(); - payload->sourceAddress = htobe16(sourceAddress); - payload->activationType = static_cast(activationType); + setSourceAddress(sourceAddress); + setActivationType(activationType); // Reserved ISO is always all zeros - payload->reservedIso.fill(0); + setReservedIso({}); } uint16_t DoIpRoutingActivationRequest::getSourceAddress() const @@ -466,7 +464,7 @@ namespace pcpp return (m_DataLen == OPT_LEN); } - const std::array DoIpRoutingActivationRequest::getReservedOem() const + std::array DoIpRoutingActivationRequest::getReservedOem() const { if (hasReservedOem()) { @@ -509,8 +507,8 @@ namespace pcpp oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; auto it = DoIpEnumToStringActivationTypes.find(getActivationType()); - oss << "Activation type: " << ((it != DoIpEnumToStringActivationTypes.end()) ? it->second : "Unknown") << " (0x" - << std::hex << static_cast(getActivationType()) << ")\n"; + oss << "Activation type: " << it->second << " (0x" << std::hex + << static_cast(getRoutingRequest()->activationType) << ")\n"; oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; @@ -536,16 +534,15 @@ namespace pcpp { setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); - auto* payload = getRoutingResponse(); - payload->logicalAddressExternalTester = htobe16(logicalAddressExternalTester); - payload->sourceAddress = htobe16(sourceAddress); - payload->responseCode = static_cast(responseCode); - payload->reservedIso.fill(0); + setLogicalAddressExternalTester(logicalAddressExternalTester); + setSourceAddress(sourceAddress); + setResponseCode(responseCode); + setReservedIso({}); } uint16_t DoIpRoutingActivationResponse::getLogicalAddressExternalTester() const { - return htobe16(getRoutingResponse()->logicalAddressExternalTester); + return be16toh(getRoutingResponse()->logicalAddressExternalTester); } void DoIpRoutingActivationResponse::setLogicalAddressExternalTester(uint16_t addr) @@ -555,7 +552,7 @@ namespace pcpp uint16_t DoIpRoutingActivationResponse::getSourceAddress() const { - return htobe16(getRoutingResponse()->sourceAddress); + return be16toh(getRoutingResponse()->sourceAddress); } void DoIpRoutingActivationResponse::setSourceAddress(uint16_t sourceAddress) @@ -567,9 +564,10 @@ namespace pcpp { uint8_t code = getRoutingResponse()->responseCode; if (code <= static_cast(DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED)) + { return static_cast(code); - else - return DoIpRoutingResponseCodes::UNKNOWN; + } + return DoIpRoutingResponseCodes::UNKNOWN; } void DoIpRoutingActivationResponse::setResponseCode(DoIpRoutingResponseCodes code) @@ -592,7 +590,7 @@ namespace pcpp return (m_DataLen == OPT_LEN); } - const std::array DoIpRoutingActivationResponse::getReservedOem() const + std::array DoIpRoutingActivationResponse::getReservedOem() const { if (hasReservedOem()) { @@ -636,9 +634,8 @@ namespace pcpp oss << "Source Address: 0x" << std::hex << getSourceAddress() << "\n"; auto it = DoIpEnumToStringRoutingResponseCodes.find(getResponseCode()); - oss << "Routing activation response code: " - << ((it != DoIpEnumToStringRoutingResponseCodes.end()) ? it->second : "Unknown") << " (0x" << std::hex - << static_cast(getResponseCode()) << ")\n"; + oss << "Routing activation response code: " << it->second << " (0x" << std::hex + << static_cast(getRoutingResponse()->responseCode) << ")\n"; oss << "Reserved by ISO: " << pcpp::byteArrayToHexString(getReservedIso().data(), DOIP_RESERVED_ISO_LEN) << "\n"; @@ -666,9 +663,10 @@ namespace pcpp { uint8_t nackCode = getGenericHeaderNack()->nackCode; if (nackCode <= static_cast(DoIpGenericHeaderNackCodes::INVALID_PAYLOAD_LENGTH)) + { return static_cast(nackCode); - else - return DoIpGenericHeaderNackCodes::UNKNOWN; + } + return DoIpGenericHeaderNackCodes::UNKNOWN; } void DoIpGenericHeaderNack::setNackCode(DoIpGenericHeaderNackCodes nackCode) @@ -686,15 +684,15 @@ namespace pcpp return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequestEID | - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID(uint8_t* data, size_t dataLen, - Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // DoIpVehicleIdentificationRequestWEID| + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpVehicleIdentificationRequestWEID::DoIpVehicleIdentificationRequestWEID(uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} - DoIpVehicleIdentificationRequestEID::DoIpVehicleIdentificationRequestEID( + DoIpVehicleIdentificationRequestWEID::DoIpVehicleIdentificationRequestWEID( const std::array& eid) : DoIpLayer(FIXED_LEN) { @@ -702,32 +700,32 @@ namespace pcpp setEID(eid); } - std::array DoIpVehicleIdentificationRequestEID::getEID() const + std::array DoIpVehicleIdentificationRequestWEID::getEID() const { return getVehicleIdentificationRequestEID()->eid; } - void DoIpVehicleIdentificationRequestEID::setEID(const std::array& eid) + void DoIpVehicleIdentificationRequestWEID::setEID(const std::array& eid) { getVehicleIdentificationRequestEID()->eid = eid; } - std::string DoIpVehicleIdentificationRequestEID::getSummary() const + std::string DoIpVehicleIdentificationRequestWEID::getSummary() const { std::ostringstream oss; oss << "EID: " << pcpp::byteArrayToHexString(getEID().data(), DOIP_EID_LEN) << "\n"; return oss.str(); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - // VehicleIdentificationRequestVIN | - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| - DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN(uint8_t* data, size_t dataLen, - Layer* prevLayer, Packet* packet) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + // VehicleIdentificationRequestWVIN | + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| + DoIpVehicleIdentificationRequestWVIN::DoIpVehicleIdentificationRequestWVIN(uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) : DoIpLayer(data, dataLen, prevLayer, packet) {} - DoIpVehicleIdentificationRequestVIN::DoIpVehicleIdentificationRequestVIN( + DoIpVehicleIdentificationRequestWVIN::DoIpVehicleIdentificationRequestWVIN( const std::array& vin) : DoIpLayer(FIXED_LEN) { @@ -735,17 +733,17 @@ namespace pcpp setVIN(vin); } - std::array DoIpVehicleIdentificationRequestVIN::getVIN() const + std::array DoIpVehicleIdentificationRequestWVIN::getVIN() const { - return getVehicleIdentificationRequestVIN()->vin; + return getVehicleIdentificationRequestWVIN()->vin; } - void DoIpVehicleIdentificationRequestVIN::setVIN(const std::array& vin) + void DoIpVehicleIdentificationRequestWVIN::setVIN(const std::array& vin) { - getVehicleIdentificationRequestVIN()->vin = vin; + getVehicleIdentificationRequestWVIN()->vin = vin; } - std::string DoIpVehicleIdentificationRequestVIN::getSummary() const + std::string DoIpVehicleIdentificationRequestWVIN::getSummary() const { std::ostringstream oss; oss << "VIN: " << std::string(reinterpret_cast(getVIN().data()), DOIP_VIN_LEN) << "\n"; @@ -778,26 +776,30 @@ namespace pcpp { return getVehicleAnnouncement()->vin; } + uint16_t DoIpVehicleAnnouncement::getLogicalAddress() const { - return htobe16(getVehicleAnnouncement()->logicalAddress); + return be16toh(getVehicleAnnouncement()->logicalAddress); } std::array DoIpVehicleAnnouncement::getEID() const { return getVehicleAnnouncement()->eid; } + std::array DoIpVehicleAnnouncement::getGID() const { return getVehicleAnnouncement()->gid; } + DoIpActionCodes DoIpVehicleAnnouncement::getFurtherActionRequired() const { uint8_t actionCode = getVehicleAnnouncement()->actionCode; if (actionCode <= static_cast(DoIpActionCodes::ROUTING_ACTIVATION_REQUIRED)) + { return static_cast(actionCode); - else - return DoIpActionCodes::UNKNOWN; + } + return DoIpActionCodes::UNKNOWN; } DoIpSyncStatus DoIpVehicleAnnouncement::getSyncStatus() const @@ -806,9 +808,10 @@ namespace pcpp { uint8_t syncStatus = *(m_Data + SYNC_STATUS_OFFSET); if (syncStatus <= static_cast(DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED)) + { return static_cast(syncStatus); - else - return DoIpSyncStatus::UNKNOWN; + } + return DoIpSyncStatus::UNKNOWN; } else { @@ -828,6 +831,7 @@ namespace pcpp PCPP_LOG_DEBUG("doip packet has no syncStatus!"); } } + void DoIpVehicleAnnouncement::setVIN(const std::array& vin) { getVehicleAnnouncement()->vin = vin; @@ -835,7 +839,7 @@ namespace pcpp void DoIpVehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) { - getVehicleAnnouncement()->logicalAddress = be16toh(logicalAddress); + getVehicleAnnouncement()->logicalAddress = htobe16(logicalAddress); } void DoIpVehicleAnnouncement::setEID(const std::array& eid) @@ -906,7 +910,7 @@ namespace pcpp uint16_t DoIpAliveCheckResponse::getSourceAddress() const { - return htobe16(getAliveCheckResponse()->sourceAddress); + return be16toh(getAliveCheckResponse()->sourceAddress); } void DoIpAliveCheckResponse::setSourceAddress(uint16_t sourceAddress) @@ -940,9 +944,10 @@ namespace pcpp { uint8_t powerModeCode = getDiagnosticPowerModeResponse()->powerModeCode; if (powerModeCode <= static_cast(DoIpDiagnosticPowerModeCodes::NOT_SUPPORTED)) + { return static_cast(powerModeCode); - else - return DoIpDiagnosticPowerModeCodes::UNKNOWN; + } + return DoIpDiagnosticPowerModeCodes::UNKNOWN; } void DoIpDiagnosticPowerModeResponse::setPowerModeCode(DoIpDiagnosticPowerModeCodes code) @@ -979,21 +984,24 @@ namespace pcpp } DoIpEntityStatusResponseCode DoIpEntityStatusResponse::getNodeType() const { - uint8_t nodeType = getEntityStatusResponsePtr()->nodeType; + uint8_t nodeType = getEntityStatusResponse()->nodeType; if (nodeType <= static_cast(DoIpEntityStatusResponseCode::NODE)) + { return static_cast(nodeType); - else - return DoIpEntityStatusResponseCode::UNKNOWN; + } + return DoIpEntityStatusResponseCode::UNKNOWN; } uint8_t DoIpEntityStatusResponse::getMaxConcurrentSockets() const { - return getEntityStatusResponsePtr()->maxConcurrentSockets; + return getEntityStatusResponse()->maxConcurrentSockets; } + uint8_t DoIpEntityStatusResponse::getCurrentlyOpenSockets() const { - return getEntityStatusResponsePtr()->currentlyOpenSockets; + return getEntityStatusResponse()->currentlyOpenSockets; } + uint32_t DoIpEntityStatusResponse::getMaxDataSize() const { if (!hasMaxDataSize()) @@ -1001,16 +1009,19 @@ namespace pcpp uint32_t value; std::memcpy(&value, m_Data + MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); - return htobe32(value); + return be32toh(value); } + void DoIpEntityStatusResponse::setNodeType(DoIpEntityStatusResponseCode nodeType) { - getEntityStatusResponsePtr()->nodeType = static_cast(nodeType); + getEntityStatusResponse()->nodeType = static_cast(nodeType); } + bool DoIpEntityStatusResponse::hasMaxDataSize() const { return (m_DataLen == OPT_LEN); } + void DoIpEntityStatusResponse::clearMaxDataSize() { if (hasMaxDataSize()) @@ -1023,14 +1034,15 @@ namespace pcpp PCPP_LOG_DEBUG("doip packet has no MaxDataSize field!"); } } + void DoIpEntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) { - getEntityStatusResponsePtr()->maxConcurrentSockets = sockets; + getEntityStatusResponse()->maxConcurrentSockets = sockets; } void DoIpEntityStatusResponse::setCurrentlyOpenSockets(uint8_t sockets) { - getEntityStatusResponsePtr()->currentlyOpenSockets = sockets; + getEntityStatusResponse()->currentlyOpenSockets = sockets; } void DoIpEntityStatusResponse::setMaxDataSize(uint32_t data) @@ -1047,10 +1059,10 @@ namespace pcpp std::string DoIpEntityStatusResponse::getSummary() const { std::ostringstream oss; - DoIpEntityStatusResponseCode nodeType = getNodeType(); - auto it = DoIpEnumToStringEntityStatusNodeTypes.find(nodeType); - oss << "Entity status: " << ((it != DoIpEnumToStringEntityStatusNodeTypes.end()) ? it->second : "Unknown") - << " (0x" << std::hex << static_cast(nodeType) << ")" << "\n"; + auto it = DoIpEnumToStringEntityStatusNodeTypes.find(getNodeType()); + + oss << "Entity status: " << it->second << " (0x" << std::hex + << static_cast(getEntityStatusResponse()->nodeType) << ")" << "\n"; oss << "Max Concurrent Socket: " << static_cast(getMaxConcurrentSockets()) << "\n"; oss << "Currently Opened Socket: " << static_cast(getCurrentlyOpenSockets()) << "\n"; if (hasMaxDataSize()) @@ -1070,12 +1082,12 @@ namespace pcpp uint16_t DoIpDiagnosticBase::getSourceAddress() const { - return htobe16(getCommonDiagnosticHeader()->sourceAddress); + return be16toh(getCommonDiagnosticHeader()->sourceAddress); } uint16_t DoIpDiagnosticBase::getTargetAddress() const { - return htobe16(getCommonDiagnosticHeader()->targetAddress); + return be16toh(getCommonDiagnosticHeader()->targetAddress); } void DoIpDiagnosticBase::setSourceAddress(uint16_t sourceAddress) @@ -1105,7 +1117,7 @@ namespace pcpp setDiagnosticData(diagData); } - const std::vector DoIpDiagnosticMessage::getDiagnosticData() const + std::vector DoIpDiagnosticMessage::getDiagnosticData() const { const uint8_t* diagDataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; return std::vector(diagDataPtr, diagDataPtr + (m_DataLen - DIAGNOSTIC_DATA_OFFSET)); @@ -1113,16 +1125,19 @@ namespace pcpp void DoIpDiagnosticMessage::setDiagnosticData(const std::vector& data) { - const size_t newPayloadlLength = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + data.size(); + const size_t newPayloadLength = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + data.size(); const size_t currentDiagnosticDataLen = m_DataLen - DIAGNOSTIC_DATA_OFFSET; + setPayloadLength(newPayloadLength); - setPayloadLength(newPayloadlLength); - // always clear the current diagnostic data and extendLayer with the new provided data - if (currentDiagnosticDataLen > 0) + auto layerExtensionLen = data.size() - currentDiagnosticDataLen; + if (layerExtensionLen > 0) { - shortenLayer(DIAGNOSTIC_DATA_OFFSET, currentDiagnosticDataLen); + extendLayer(DIAGNOSTIC_DATA_OFFSET + currentDiagnosticDataLen, layerExtensionLen); + } + else if (layerExtensionLen < 0) + { + shortenLayer(DIAGNOSTIC_DATA_OFFSET, layerExtensionLen); } - extendLayer(DIAGNOSTIC_DATA_OFFSET, data.size()); uint8_t* dataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; memcpy(dataPtr, data.data(), data.size()); } @@ -1159,7 +1174,7 @@ namespace pcpp uint8_t DoIpDiagnosticResponseMessageBase::getResponseCode() const { - return static_cast(getDiagnosticResponseMessageBase()->diagnosticCode); + return getDiagnosticResponseMessageBase()->diagnosticCode; } const std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const @@ -1169,10 +1184,7 @@ namespace pcpp uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); } - else - { - return {}; - } + return {}; } bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const @@ -1182,15 +1194,19 @@ namespace pcpp void DoIpDiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) { - size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); - size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; + const size_t newPayloadLen = FIXED_LEN - DOIP_HEADER_LEN + msg.size(); + const size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; setPayloadLength(newPayloadLen); - // clear memory for old previous message - if (hasPreviousMessage()) + + auto layerExtensionLen = msg.size() - currentPayloadLen; + if (layerExtensionLen > 0) + { + extendLayer(PREVIOUS_MSG_OFFSET + currentPayloadLen, layerExtensionLen); + } + else if (layerExtensionLen < 0) { shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); } - extendLayer(PREVIOUS_MSG_OFFSET, msg.size()); uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); memcpy(ptr, msg.data(), msg.size()); } @@ -1225,9 +1241,10 @@ namespace pcpp DoIpDiagnosticAckCodes DoIpDiagnosticAckMessage::getAckCode() const { if (getResponseCode() == static_cast(DoIpDiagnosticAckCodes::ACK)) + { return DoIpDiagnosticAckCodes::ACK; - else - return DoIpDiagnosticAckCodes::UNKNOWN; + } + return DoIpDiagnosticAckCodes::UNKNOWN; } void DoIpDiagnosticAckMessage::setAckCode(DoIpDiagnosticAckCodes code) @@ -1270,9 +1287,10 @@ namespace pcpp { uint8_t nackCode = getResponseCode(); if (nackCode <= static_cast(DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR)) + { return static_cast(nackCode); - else - return DoIpDiagnosticMessageNackCodes::UNKNOWN; + } + return DoIpDiagnosticMessageNackCodes::UNKNOWN; } void DoIpDiagnosticNackMessage::setNackCode(DoIpDiagnosticMessageNackCodes code) diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 23228c9afd..f34ec8603e 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -367,15 +367,8 @@ namespace pcpp const uint16_t portSrc = getSrcPort(); const char* payloadChar = reinterpret_cast(payload); - if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && - (DoIpLayer::isDataValid(payload, payloadLen))) - { - m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); - if (!m_NextLayer) - constructNextLayer(payload, payloadLen, m_Packet); - } - else if (HttpMessage::isHttpPort(portDst) && - HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) + if (HttpMessage::isHttpPort(portDst) && + HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) { constructNextLayer(payload, payloadLen, m_Packet); } @@ -437,6 +430,13 @@ namespace pcpp { constructNextLayer(payload, payloadLen, m_Packet); } + else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && + (DoIpLayer::isDataValid(payload, payloadLen))) + { + m_NextLayer = DoIpLayer::parseDoIpLayer(payload, payloadLen, this, m_Packet); + if (!m_NextLayer) + constructNextLayer(payload, payloadLen, m_Packet); + } else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) { setNextLayer(SomeIpLayer::parseSomeIpLayer(payload, payloadLen, this, m_Packet)); diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 5a2a12ab7c..b45efc9022 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -131,6 +131,9 @@ namespace pcpp else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && (DhcpV6Layer::isDataValid(udpData, udpDataLen))) m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); + else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && + NtpLayer::isDataValid(udpData, udpDataLen)) + m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && (DoIpLayer::isDataValid(udpData, udpDataLen))) { @@ -138,10 +141,6 @@ namespace pcpp if (!m_NextLayer) constructNextLayer(udpData, udpDataLen, m_Packet); } - - else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && - NtpLayer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) m_NextLayer = SomeIpLayer::parseSomeIpLayer(udpData, udpDataLen, this, m_Packet); else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWEIDPacket.dat similarity index 100% rename from Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat rename to Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWEIDPacket.dat diff --git a/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat b/Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWVINPacket.dat similarity index 100% rename from Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat rename to Tests/Packet++Test/PacketExamples/DoIpVehicleIdentificationRequestWVINPacket.dat diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index 5435ddce22..0c0aba9062 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -95,10 +95,10 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing); PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation); PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing); PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing); -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketCreation); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketParsing); +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketCreation); PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing); PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation); PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing); diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index 403bbf5154..b700b6f87e 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -290,13 +290,13 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) } // VehicleIdentificationWithEID -PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketParsing) { // Dissect Vehicle identification Request with EID timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestEIDPacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestWEIDPacket.dat"); pcpp::Packet VehicleIdentificationRequestEID(&rawPacket1); PTF_ASSERT_TRUE(VehicleIdentificationRequestEID.isPacketOfType(pcpp::IPv4)); @@ -309,7 +309,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); PTF_ASSERT_EQUAL(udpLayer->getSrcPort(), 65300); - auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); + auto* doipLayer = VehicleIdentificationRequestEID.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "EID: 4241554e4545\n"); @@ -326,8 +326,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketParsing) } // VehicleIdentificationWithEIDacketParsing -// DoIpVehicleIdentificationRequestEIDPacketCreation -PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) +// DoIpVehicleIdentificationRequestWEIDPacketCreation +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); @@ -344,7 +344,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; std::array eid{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45 }; - pcpp::DoIpVehicleIdentificationRequestEID withEID(eid); + pcpp::DoIpVehicleIdentificationRequestWEID withEID(eid); withEID.setEID(eid); PTF_ASSERT_TRUE(doIpPacket.addLayer(&withEID)); @@ -362,16 +362,16 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestEIDPacketCreation) PTF_ASSERT_EQUAL(withEID.toString(), "DoIP Layer, Vehicle identification request with EID (0x0002)"); PTF_ASSERT_VECTORS_EQUAL(withEID.getEID(), eid); PTF_ASSERT_EQUAL(withEID.getSummary(), "EID: 4241554e4545\n"); -} // DoIpVehicleIdentificationRequestEIDPacketCreation +} // DoIpVehicleIdentificationRequestWEIDPacketCreation -// DoIpVehicleIdentificationRequestVINPacketParsing -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) +// DoIpVehicleIdentificationRequestWVINPacketParsing +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketParsing) { // Dissect Vehicle identification Request with VIN timeval time; gettimeofday(&time, nullptr); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestVINPacket.dat"); + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DoIpVehicleIdentificationRequestWVINPacket.dat"); pcpp::Packet VehicleIdentificationRequestVIN(&rawPacket1); PTF_ASSERT_TRUE(VehicleIdentificationRequestVIN.isPacketOfType(pcpp::IPv4)); @@ -383,7 +383,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) PTF_ASSERT_EQUAL(udpLayer->getDstPort(), pcpp::DoIpPorts::TCP_UDP_PORT); - auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); + auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); @@ -401,8 +401,8 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketParsing) } // DoIpVehicleIdentificationRequestVINPacketParsing -// DoIpVehicleIdentificationRequestVINPacketCreation -PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) +// DoIpVehicleIdentificationRequestWVINPacketCreation +PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketCreation) { pcpp::Packet doIpPacket(100); pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02")); @@ -421,7 +421,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestVINPacketCreation) std::array vin{ 0x42, 0x41, 0x55, 0x4e, 0x45, 0x45, 0x34, 0x4d, 0x5a, 0x31, 0x37, 0x30, 0x34, 0x32, 0x34, 0x30, 0x33 }; - pcpp::DoIpVehicleIdentificationRequestVIN withVin(vin); + pcpp::DoIpVehicleIdentificationRequestWVIN withVin(vin); withVin.setVIN(vin); PTF_ASSERT_TRUE(doIpPacket.addLayer(&withVin)); @@ -535,7 +535,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_EQUAL(doipLayer->getPayloadLength(), 33); PTF_ASSERT_EQUAL(doipLayer->toString(), "DoIP Layer, Vehicle announcement message / vehicle identification response message (0x0004)"); - PTF_ASSERT_VECTORS_EQUAL(doipLayer->getVIN(), vin); + PTF_ASSERT_EQUAL(doipLayer->getLogicalAddress(), 0x4010); PTF_ASSERT_VECTORS_EQUAL(doipLayer->getEID(), eid); PTF_ASSERT_VECTORS_EQUAL(doipLayer->getGID(), gid); diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 2a6b60ce53..3a33a5d495 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -193,10 +193,10 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(DoIpRoutingActivationResponsePacketCreation, "doip"); PTF_RUN_TEST(DoIpGenericHeaderNackPacketParsing, "doip"); PTF_RUN_TEST(DoIpGenericHeaderNackPacketCreation, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketParsing, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestEIDPacketCreation, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketParsing, "doip"); - PTF_RUN_TEST(DoIpVehicleIdentificationRequestVINPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWEIDPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWEIDPacketCreation, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWVINPacketParsing, "doip"); + PTF_RUN_TEST(DoIpVehicleIdentificationRequestWVINPacketCreation, "doip"); PTF_RUN_TEST(DoIpVehicleAnnouncementPacketParsing, "doip"); PTF_RUN_TEST(DoIpVehicleAnnouncementPacketCreation, "doip"); PTF_RUN_TEST(DoIpAliveCheckResponsePacketParsing, "doip"); From ecac27e040d4f5af30a384529f580cad935aa75d Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Tue, 20 May 2025 00:58:49 -0400 Subject: [PATCH 41/43] serval improvements --- Packet++/header/DoIpLayer.h | 61 ++++++----- Packet++/src/DoIpLayer.cpp | 140 ++++++++++++------------- Tests/Packet++Test/Tests/DoIpTests.cpp | 2 +- 3 files changed, 102 insertions(+), 101 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index c78d53c3cd..3a2dcd3059 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -853,6 +853,7 @@ namespace pcpp return reinterpret_cast(m_Data); } static constexpr size_t FIXED_LEN = sizeof(routing_activation_request); + static constexpr size_t RESERVED_OEM_OFFSET = FIXED_LEN; static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; @@ -966,6 +967,7 @@ namespace pcpp return reinterpret_cast(m_Data); } static constexpr size_t FIXED_LEN = sizeof(routing_activation_response); + static constexpr size_t RESERVED_OEM_OFFSET = FIXED_LEN; static constexpr size_t OPT_LEN = FIXED_LEN + DOIP_RESERVED_OEM_LEN; }; @@ -1079,16 +1081,16 @@ namespace pcpp private: #pragma pack(push, 1) - struct vehicle_identification_request_eid : doiphdr + struct vehicle_identification_request_with_eid : doiphdr { std::array eid; }; #pragma pack(pop) - vehicle_identification_request_eid* getVehicleIdentificationRequestEID() const + vehicle_identification_request_with_eid* getVehicleIdentificationRequestWEID() const { - return reinterpret_cast(m_Data); + return reinterpret_cast(m_Data); } - static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_eid); + static constexpr size_t FIXED_LEN = sizeof(vehicle_identification_request_with_eid); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1185,48 +1187,48 @@ namespace pcpp /// @return A 17-byte Vehicle Identification Number (VIN). std::array getVIN() const; + /// @brief Sets the Vehicle Identification Number (VIN). + /// @param[in] vin A 17-byte Vehicle Identification Number (VIN). + void setVIN(const std::array& vin); + /// @brief Gets the logical address of the vehicle. /// @return A 2-byte logical address of the vehicle. uint16_t getLogicalAddress() const; + /// @brief Sets the logical address. + /// @param[in] address A 2-byte logical address of the vehicle. + void setLogicalAddress(uint16_t address); + /// @brief Gets the Entity Identifier (EID). /// @return A 6-byte Entity Identifier (EID). std::array getEID() const; + /// @brief Sets the Entity Identifier (EID). + /// @param[in] eid A 6-byte Entity Identifier (EID). + void setEID(const std::array& eid); + /// @brief Gets the Group Identifier (GID). /// @return A 6-byte Group Identifier (GID). std::array getGID() const; + /// @brief Sets the Group Identifier (GID). + /// @param[in] gid A 6-byte Group Identifier (GID). + void setGID(const std::array& gid); + /// @brief Gets the further action required code. /// @return enum DoIpActionCodes representing the further action required code. DoIpActionCodes getFurtherActionRequired() const; + /// @brief Sets the further action required code. + /// @param[in] action enum DoIpActionCodes representing the further action required code to set. + void setFurtherActionRequired(DoIpActionCodes action); + /// @brief Gets the optional synchronization status if available. /// @throw std::runtime_error if the sync status is not present. /// @note To use this method safely, check beforehand if the sync status is present using hasSyncStatus(). /// @return A 1-byte synchronization status. DoIpSyncStatus getSyncStatus() const; - /// @brief Sets the Vehicle Identification Number (VIN). - /// @param[in] vin A 17-byte Vehicle Identification Number (VIN). - void setVIN(const std::array& vin); - - /// @brief Sets the logical address. - /// @param[in] address A 2-byte logical address of the vehicle. - void setLogicalAddress(uint16_t address); - - /// @brief Sets the Entity Identifier (EID). - /// @param[in] eid A 6-byte Entity Identifier (EID). - void setEID(const std::array& eid); - - /// @brief Sets the Group Identifier (GID). - /// @param[in] gid A 6-byte Group Identifier (GID). - void setGID(const std::array& gid); - - /// @brief Sets the further action required code. - /// @param[in] action enum DoIpActionCodes representing the further action required code to set. - void setFurtherActionRequired(DoIpActionCodes action); - /// @brief Sets the synchronization status. /// @param[in] sync enum DoIpSyncStatus representing the synchronization status to set. void setSyncStatus(DoIpSyncStatus sync); @@ -1538,14 +1540,14 @@ namespace pcpp /// @return 16-bit address of the source ECU. uint16_t getSourceAddress() const; - /// @brief Gets the target logical address of the message. - /// @return 16-bit address of the destination ECU. - uint16_t getTargetAddress() const; - /// @brief Sets the source logical address. /// @param[in] sourceAddress 16-bit source address. void setSourceAddress(uint16_t sourceAddress); + /// @brief Gets the target logical address of the message. + /// @return 16-bit address of the destination ECU. + uint16_t getTargetAddress() const; + /// @brief Sets the target logical address. /// @param[in] targetAddress 16-bit target address. void setTargetAddress(uint16_t targetAddress); @@ -1556,6 +1558,7 @@ namespace pcpp protected: #pragma pack(push, 1) + /// An internal structure representing the common diagnostic header. struct common_diagnostic_header : doiphdr { uint16_t sourceAddress; @@ -1655,7 +1658,7 @@ namespace pcpp /// @brief Gets the optional previously echoed diagnostic message. /// @return A vector containing the previously echoed diagnostic message. - const std::vector getPreviousMessage() const; + std::vector getPreviousMessage() const; /// @brief Checks if a previous message is attached. /// @return true if a previous message is present, false otherwise. diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 40480b3b4c..5cef2268ec 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -459,17 +459,12 @@ namespace pcpp getRoutingRequest()->reservedIso = reservedIso; } - bool DoIpRoutingActivationRequest::hasReservedOem() const - { - return (m_DataLen == OPT_LEN); - } - std::array DoIpRoutingActivationRequest::getReservedOem() const { if (hasReservedOem()) { std::array reservedOem; - memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); + memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); return reservedOem; } else @@ -482,10 +477,15 @@ namespace pcpp { if (!hasReservedOem()) { - extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); + extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); - memcpy((m_Data + FIXED_LEN), reservedOem.data(), DOIP_RESERVED_OEM_LEN); + memcpy((m_Data + RESERVED_OEM_OFFSET), reservedOem.data(), DOIP_RESERVED_OEM_LEN); + } + + bool DoIpRoutingActivationRequest::hasReservedOem() const + { + return (m_DataLen == OPT_LEN); } void DoIpRoutingActivationRequest::clearReservedOem() @@ -585,17 +585,12 @@ namespace pcpp getRoutingResponse()->reservedIso = reservedIso; } - bool DoIpRoutingActivationResponse::hasReservedOem() const - { - return (m_DataLen == OPT_LEN); - } - std::array DoIpRoutingActivationResponse::getReservedOem() const { if (hasReservedOem()) { std::array reservedOem; - memcpy(reservedOem.data(), m_Data + FIXED_LEN, DOIP_RESERVED_OEM_LEN); + memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); return reservedOem; } else @@ -608,10 +603,15 @@ namespace pcpp { if (!hasReservedOem()) { - extendLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); + extendLayer(RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); } setPayloadLength(OPT_LEN - DOIP_HEADER_LEN); - memcpy((m_Data + FIXED_LEN), reservedOem.data(), DOIP_RESERVED_OEM_LEN); + memcpy((m_Data + RESERVED_OEM_OFFSET), reservedOem.data(), DOIP_RESERVED_OEM_LEN); + } + + bool DoIpRoutingActivationResponse::hasReservedOem() const + { + return (m_DataLen == OPT_LEN); } void DoIpRoutingActivationResponse::clearReservedOem() @@ -623,7 +623,7 @@ namespace pcpp } else { - PCPP_LOG_DEBUG("doip packet has no reserved OEM field!"); + PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); } } @@ -702,12 +702,12 @@ namespace pcpp std::array DoIpVehicleIdentificationRequestWEID::getEID() const { - return getVehicleIdentificationRequestEID()->eid; + return getVehicleIdentificationRequestWEID()->eid; } void DoIpVehicleIdentificationRequestWEID::setEID(const std::array& eid) { - getVehicleIdentificationRequestEID()->eid = eid; + getVehicleIdentificationRequestWEID()->eid = eid; } std::string DoIpVehicleIdentificationRequestWEID::getSummary() const @@ -777,21 +777,41 @@ namespace pcpp return getVehicleAnnouncement()->vin; } + void DoIpVehicleAnnouncement::setVIN(const std::array& vin) + { + getVehicleAnnouncement()->vin = vin; + } + uint16_t DoIpVehicleAnnouncement::getLogicalAddress() const { return be16toh(getVehicleAnnouncement()->logicalAddress); } + void DoIpVehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) + { + getVehicleAnnouncement()->logicalAddress = htobe16(logicalAddress); + } + std::array DoIpVehicleAnnouncement::getEID() const { return getVehicleAnnouncement()->eid; } + void DoIpVehicleAnnouncement::setEID(const std::array& eid) + { + getVehicleAnnouncement()->eid = eid; + } + std::array DoIpVehicleAnnouncement::getGID() const { return getVehicleAnnouncement()->gid; } + void DoIpVehicleAnnouncement::setGID(const std::array& gid) + { + getVehicleAnnouncement()->gid = gid; + } + DoIpActionCodes DoIpVehicleAnnouncement::getFurtherActionRequired() const { uint8_t actionCode = getVehicleAnnouncement()->actionCode; @@ -802,6 +822,11 @@ namespace pcpp return DoIpActionCodes::UNKNOWN; } + void DoIpVehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) + { + getVehicleAnnouncement()->actionCode = static_cast(action); + } + DoIpSyncStatus DoIpVehicleAnnouncement::getSyncStatus() const { if (hasSyncStatus()) @@ -819,44 +844,6 @@ namespace pcpp } } - void DoIpVehicleAnnouncement::clearSyncStatus() - { - if (m_DataLen == OPT_LEN) - { - shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); - PCPP_LOG_DEBUG("Sync status has been removed successfully!"); - } - else - { - PCPP_LOG_DEBUG("doip packet has no syncStatus!"); - } - } - - void DoIpVehicleAnnouncement::setVIN(const std::array& vin) - { - getVehicleAnnouncement()->vin = vin; - } - - void DoIpVehicleAnnouncement::setLogicalAddress(uint16_t logicalAddress) - { - getVehicleAnnouncement()->logicalAddress = htobe16(logicalAddress); - } - - void DoIpVehicleAnnouncement::setEID(const std::array& eid) - { - getVehicleAnnouncement()->eid = eid; - } - - void DoIpVehicleAnnouncement::setGID(const std::array& gid) - { - getVehicleAnnouncement()->gid = gid; - } - - void DoIpVehicleAnnouncement::setFurtherActionRequired(DoIpActionCodes action) - { - getVehicleAnnouncement()->actionCode = static_cast(action); - } - void DoIpVehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) { if (!hasSyncStatus()) @@ -872,6 +859,19 @@ namespace pcpp return (m_DataLen == OPT_LEN); } + void DoIpVehicleAnnouncement::clearSyncStatus() + { + if (hasSyncStatus()) + { + shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); + PCPP_LOG_DEBUG("Sync status has been removed successfully!"); + } + else + { + PCPP_LOG_DEBUG("DoIP packet has no syncStatus!"); + } + } + std::string DoIpVehicleAnnouncement::getSummary() const { std::ostringstream oss; @@ -1005,7 +1005,7 @@ namespace pcpp uint32_t DoIpEntityStatusResponse::getMaxDataSize() const { if (!hasMaxDataSize()) - throw std::runtime_error("Max data size field not present!"); + throw std::runtime_error("MaxDataSize field not present!"); uint32_t value; std::memcpy(&value, m_Data + MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); @@ -1031,7 +1031,7 @@ namespace pcpp } else { - PCPP_LOG_DEBUG("doip packet has no MaxDataSize field!"); + PCPP_LOG_DEBUG("DoIP packet has no MaxDataSize field!"); } } @@ -1085,14 +1085,14 @@ namespace pcpp return be16toh(getCommonDiagnosticHeader()->sourceAddress); } - uint16_t DoIpDiagnosticBase::getTargetAddress() const + void DoIpDiagnosticBase::setSourceAddress(uint16_t sourceAddress) { - return be16toh(getCommonDiagnosticHeader()->targetAddress); + getCommonDiagnosticHeader()->sourceAddress = htobe16(sourceAddress); } - void DoIpDiagnosticBase::setSourceAddress(uint16_t sourceAddress) + uint16_t DoIpDiagnosticBase::getTargetAddress() const { - getCommonDiagnosticHeader()->sourceAddress = htobe16(sourceAddress); + return be16toh(getCommonDiagnosticHeader()->targetAddress); } void DoIpDiagnosticBase::setTargetAddress(uint16_t targetAddress) @@ -1138,8 +1138,7 @@ namespace pcpp { shortenLayer(DIAGNOSTIC_DATA_OFFSET, layerExtensionLen); } - uint8_t* dataPtr = m_Data + DIAGNOSTIC_DATA_OFFSET; - memcpy(dataPtr, data.data(), data.size()); + memcpy((m_Data + DIAGNOSTIC_DATA_OFFSET), data.data(), data.size()); } std::string DoIpDiagnosticMessage::getSummary() const @@ -1177,11 +1176,11 @@ namespace pcpp return getDiagnosticResponseMessageBase()->diagnosticCode; } - const std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const + std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const { if (hasPreviousMessage()) { - uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; + const uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); } return {}; @@ -1189,7 +1188,7 @@ namespace pcpp bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const { - return (m_DataLen > PREVIOUS_MSG_OFFSET); + return (m_DataLen > FIXED_LEN); } void DoIpDiagnosticResponseMessageBase::setPreviousMessage(const std::vector& msg) @@ -1207,8 +1206,7 @@ namespace pcpp { shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); } - uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET); - memcpy(ptr, msg.data(), msg.size()); + memcpy((m_Data + PREVIOUS_MSG_OFFSET), msg.data(), msg.size()); } void DoIpDiagnosticResponseMessageBase::clearPreviousMessage() @@ -1220,7 +1218,7 @@ namespace pcpp } else { - PCPP_LOG_DEBUG("doip packet has no PreviousMessage field!"); + PCPP_LOG_DEBUG("DoIP packet has no PreviousMessage field!"); } } diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index b700b6f87e..fd386f992c 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -824,7 +824,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) } catch (const std::runtime_error& e) { - PTF_ASSERT_EQUAL(std::string(e.what()), "Max data size field not present!"); + PTF_ASSERT_EQUAL(std::string(e.what()), "MaxDataSize field not present!"); } PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 53); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytesWithoutMaxDataSize, 11); From 7bd7276dd82b9df1c1fcf1ced61074ab4127cc02 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Wed, 21 May 2025 02:24:29 -0400 Subject: [PATCH 42/43] try fix shorten/extend logic --- Packet++/src/DoIpLayer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 5cef2268ec..4b6f58b2b3 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -358,12 +358,12 @@ namespace pcpp uint32_t DoIpLayer::getPayloadLength() const { - return htobe32(getDoIpHeader()->payloadLength); + return be32toh(getDoIpHeader()->payloadLength); } void DoIpLayer::setPayloadLength(uint32_t payloadLength) { - getDoIpHeader()->payloadLength = be32toh(payloadLength); + getDoIpHeader()->payloadLength = htobe32(payloadLength); } std::string DoIpLayer::toString() const @@ -1129,14 +1129,15 @@ namespace pcpp const size_t currentDiagnosticDataLen = m_DataLen - DIAGNOSTIC_DATA_OFFSET; setPayloadLength(newPayloadLength); - auto layerExtensionLen = data.size() - currentDiagnosticDataLen; + ptrdiff_t layerExtensionLen = + static_cast(data.size()) - static_cast(currentDiagnosticDataLen); if (layerExtensionLen > 0) { extendLayer(DIAGNOSTIC_DATA_OFFSET + currentDiagnosticDataLen, layerExtensionLen); } else if (layerExtensionLen < 0) { - shortenLayer(DIAGNOSTIC_DATA_OFFSET, layerExtensionLen); + shortenLayer(DIAGNOSTIC_DATA_OFFSET + data.size(), (-1 * layerExtensionLen)); } memcpy((m_Data + DIAGNOSTIC_DATA_OFFSET), data.data(), data.size()); } @@ -1197,14 +1198,14 @@ namespace pcpp const size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; setPayloadLength(newPayloadLen); - auto layerExtensionLen = msg.size() - currentPayloadLen; + ptrdiff_t layerExtensionLen = static_cast(msg.size()) - static_cast(currentPayloadLen); if (layerExtensionLen > 0) { extendLayer(PREVIOUS_MSG_OFFSET + currentPayloadLen, layerExtensionLen); } else if (layerExtensionLen < 0) { - shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen); + shortenLayer(PREVIOUS_MSG_OFFSET + msg.size(), (-1 * layerExtensionLen)); } memcpy((m_Data + PREVIOUS_MSG_OFFSET), msg.data(), msg.size()); } From 885809a1bc958bb6cde5c79c8f2b75176819e6a2 Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Thu, 22 May 2025 23:45:23 -0400 Subject: [PATCH 43/43] fix lenght adjustement --- Packet++/header/DoIpLayer.h | 26 ++-- Packet++/src/DoIpLayer.cpp | 179 +++++++++++-------------- Tests/Packet++Test/Tests/DoIpTests.cpp | 73 +++++----- 3 files changed, 131 insertions(+), 147 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 3a2dcd3059..4aa52e6d82 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -446,27 +446,27 @@ namespace pcpp { /// @brief Reserved protocol version. /// This value is used when the version is not specified. - ReservedVersion = 0x00U, + RESERVED_VER = 0x00U, /// @brief Protocol version 1, based on ISO 2010 specification. - Version01Iso2010 = 0x01U, + ISO13400_2010 = 0x01U, /// @brief Protocol version 2, based on ISO 2012 specification. - Version02Iso2012 = 0x02U, + ISO13400_2012 = 0x02U, /// @brief Protocol version 3, based on ISO 2019 specification. - Version03Iso2019 = 0x03U, + ISO13400_2019 = 0x03U, /// @brief Protocol version 4, based on ISO 2019 AMD1 (Amendment 1) specification. - Version04Iso2019_AMD1 = 0x04U, + ISO13400_2019_AMD1 = 0x04U, /// @brief Default protocol version. /// Used for broadcast Vehicle Identification Request Messages. - DefaultVersion = 0xFFU, + DEFAULT_VALUE = 0xFFU, /// Represents an unknown or unsupported protocol version (not specified by ISO). /// Used to indicate an unsupported or unknown protocol version for internal usage. - UnknownVersion = 0xEF + UNKNOWN = 0xEF }; /// @brief Enum representing DoIP payload types. @@ -675,13 +675,13 @@ namespace pcpp switch (parsedVersion) { - case DoIpProtocolVersion::ReservedVersion: + case DoIpProtocolVersion::RESERVED_VER: { PCPP_LOG_DEBUG("[Malformed doip packet]: Reserved ISO DoIP protocol version detected: 0x" << std::hex << static_cast(version)); return false; } - case DoIpProtocolVersion::DefaultVersion: + case DoIpProtocolVersion::DEFAULT_VALUE: if (type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN && type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID && type != DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST) @@ -689,10 +689,10 @@ namespace pcpp PCPP_LOG_DEBUG("[Malformed doip packet]: Invalid/unsupported DoIP version!"); return false; } - case DoIpProtocolVersion::Version01Iso2010: - case DoIpProtocolVersion::Version02Iso2012: - case DoIpProtocolVersion::Version03Iso2019: - case DoIpProtocolVersion::Version04Iso2019_AMD1: + case DoIpProtocolVersion::ISO13400_2010: + case DoIpProtocolVersion::ISO13400_2012: + case DoIpProtocolVersion::ISO13400_2019: + case DoIpProtocolVersion::ISO13400_2019_AMD1: { if (version != static_cast(~inVersion)) { diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 4b6f58b2b3..2d5aae4d02 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -84,7 +84,7 @@ namespace pcpp { DoIpRoutingResponseCodes::RESERVED_ISO_0x0F, "Reserved by ISO 13400" }, { DoIpRoutingResponseCodes::ROUTING_SUCCESSFULLY_ACTIVATED, "Routing successfully activated" }, { DoIpRoutingResponseCodes::CONFIRMATION_REQUIRED, "Routing will be activated; confirmation required" }, - { DoIpRoutingResponseCodes::UNKNOWN, "Unknown routing activation response code" } + { DoIpRoutingResponseCodes::UNKNOWN, "Unknown" } }; // This unordered map provides human-readable descriptions for each NACK (negative acknowledgment) code @@ -100,7 +100,7 @@ namespace pcpp { DoIpDiagnosticMessageNackCodes::TARGET_UNREACHABLE, "Target unreachable" }, { DoIpDiagnosticMessageNackCodes::UNKNOWN_NETWORK, "Unknown network" }, { DoIpDiagnosticMessageNackCodes::TRANSPORT_PROTOCOL_ERROR, "Transport protocol error" }, - { DoIpDiagnosticMessageNackCodes::UNKNOWN, "Unknown NACK code" } + { DoIpDiagnosticMessageNackCodes::UNKNOWN, "Unknown" } }; // This unordered map provides human-readable descriptions for each power mode code @@ -157,13 +157,13 @@ namespace pcpp // DoIP protocol as defined in ISO 13400. It maps the `DoIpProtocolVersion` enum values // to their corresponding descriptions. static const std::unordered_map DoIpEnumToStringProtocolVersion{ - { DoIpProtocolVersion::DefaultVersion, "Default value for vehicle identification request messages" }, - { DoIpProtocolVersion::Version01Iso2010, "DoIP ISO/DIS 13400-2:2010" }, - { DoIpProtocolVersion::Version02Iso2012, "DoIP ISO 13400-2:2012" }, - { DoIpProtocolVersion::Version03Iso2019, "DoIP ISO 13400-2:2019" }, - { DoIpProtocolVersion::Version04Iso2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, - { DoIpProtocolVersion::ReservedVersion, "Reserved" }, - { DoIpProtocolVersion::UnknownVersion, "Unknown Protocol Version" }, + { DoIpProtocolVersion::DEFAULT_VALUE, "Default value for vehicle identification request messages" }, + { DoIpProtocolVersion::ISO13400_2010, "DoIP ISO/DIS 13400-2:2010" }, + { DoIpProtocolVersion::ISO13400_2012, "DoIP ISO 13400-2:2012" }, + { DoIpProtocolVersion::ISO13400_2019, "DoIP ISO 13400-2:2019" }, + { DoIpProtocolVersion::ISO13400_2019_AMD1, "DoIP ISO 13400-2:2012 AMD1" }, + { DoIpProtocolVersion::RESERVED_VER, "Reserved" }, + { DoIpProtocolVersion::UNKNOWN, "Unknown Protocol Version" }, }; // This unordered map provides human-readable descriptions for each payload type @@ -307,16 +307,16 @@ namespace pcpp switch (static_cast(version)) { - case DoIpProtocolVersion::ReservedVersion: - case DoIpProtocolVersion::Version01Iso2010: - case DoIpProtocolVersion::Version02Iso2012: - case DoIpProtocolVersion::Version03Iso2019: - case DoIpProtocolVersion::Version04Iso2019_AMD1: - case DoIpProtocolVersion::DefaultVersion: + case DoIpProtocolVersion::RESERVED_VER: + case DoIpProtocolVersion::ISO13400_2010: + case DoIpProtocolVersion::ISO13400_2012: + case DoIpProtocolVersion::ISO13400_2019: + case DoIpProtocolVersion::ISO13400_2019_AMD1: + case DoIpProtocolVersion::DEFAULT_VALUE: return static_cast(version); default: - return DoIpProtocolVersion::UnknownVersion; + return DoIpProtocolVersion::UNKNOWN; } } @@ -412,7 +412,7 @@ namespace pcpp DoIpActivationTypes activationType) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setSourceAddress(sourceAddress); setActivationType(activationType); @@ -461,16 +461,12 @@ namespace pcpp std::array DoIpRoutingActivationRequest::getReservedOem() const { - if (hasReservedOem()) - { - std::array reservedOem; - memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); - return reservedOem; - } - else - { + if (!hasReservedOem()) throw std::runtime_error("Reserved OEM field not present!"); - } + + std::array reservedOem; + memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + return reservedOem; } void DoIpRoutingActivationRequest::setReservedOem(const std::array& reservedOem) @@ -490,15 +486,15 @@ namespace pcpp void DoIpRoutingActivationRequest::clearReservedOem() { - if (hasReservedOem()) - { - shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); - PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); - } - else + if (!hasReservedOem()) { PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); + return; } + + shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); + setPayloadLength(FIXED_LEN - DOIP_HEADER_LEN); + PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } std::string DoIpRoutingActivationRequest::getSummary() const @@ -532,7 +528,7 @@ namespace pcpp DoIpRoutingResponseCodes responseCode) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), (FIXED_LEN - DOIP_HEADER_LEN)); setLogicalAddressExternalTester(logicalAddressExternalTester); setSourceAddress(sourceAddress); @@ -587,16 +583,12 @@ namespace pcpp std::array DoIpRoutingActivationResponse::getReservedOem() const { - if (hasReservedOem()) - { - std::array reservedOem; - memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); - return reservedOem; - } - else - { + if (!hasReservedOem()) throw std::runtime_error("Reserved OEM field not present!"); - } + + std::array reservedOem; + memcpy(reservedOem.data(), m_Data + RESERVED_OEM_OFFSET, DOIP_RESERVED_OEM_LEN); + return reservedOem; } void DoIpRoutingActivationResponse::setReservedOem(const std::array& reservedOem) @@ -616,15 +608,15 @@ namespace pcpp void DoIpRoutingActivationResponse::clearReservedOem() { - if (hasReservedOem()) - { - shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); - PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); - } - else + if (!hasReservedOem()) { PCPP_LOG_DEBUG("DoIP packet has no reserved OEM field!"); + return; } + + shortenLayer(FIXED_LEN, DOIP_RESERVED_OEM_LEN); + setPayloadLength(FIXED_LEN - DOIP_HEADER_LEN); + PCPP_LOG_DEBUG("Reserved OEM field has been removed successfully!"); } std::string DoIpRoutingActivationResponse::getSummary() const @@ -655,7 +647,7 @@ namespace pcpp DoIpGenericHeaderNack::DoIpGenericHeaderNack(DoIpGenericHeaderNackCodes nackCode) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setNackCode(nackCode); } @@ -696,7 +688,7 @@ namespace pcpp const std::array& eid) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_EID_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), DOIP_EID_LEN); setEID(eid); } @@ -729,7 +721,7 @@ namespace pcpp const std::array& vin) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_VIN_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), DOIP_VIN_LEN); setVIN(vin); } @@ -764,7 +756,7 @@ namespace pcpp DoIpActionCodes actionCode) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setVIN(vin); setLogicalAddress(logicalAddress); @@ -772,6 +764,7 @@ namespace pcpp setGID(gid); setFurtherActionRequired(actionCode); } + std::array DoIpVehicleAnnouncement::getVIN() const { return getVehicleAnnouncement()->vin; @@ -829,19 +822,14 @@ namespace pcpp DoIpSyncStatus DoIpVehicleAnnouncement::getSyncStatus() const { - if (hasSyncStatus()) - { - uint8_t syncStatus = *(m_Data + SYNC_STATUS_OFFSET); - if (syncStatus <= static_cast(DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED)) - { - return static_cast(syncStatus); - } - return DoIpSyncStatus::UNKNOWN; - } - else - { + if (!hasSyncStatus()) throw std::runtime_error("Sync status field not present!"); - } + + uint8_t syncStatus = *(m_Data + SYNC_STATUS_OFFSET); + if (syncStatus <= static_cast(DoIpSyncStatus::VIN_AND_OR_GID_ARE_NOT_SINCHRONIZED)) + return static_cast(syncStatus); + + return DoIpSyncStatus::UNKNOWN; } void DoIpVehicleAnnouncement::setSyncStatus(DoIpSyncStatus syncStatus) @@ -861,15 +849,13 @@ namespace pcpp void DoIpVehicleAnnouncement::clearSyncStatus() { - if (hasSyncStatus()) - { - shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); - PCPP_LOG_DEBUG("Sync status has been removed successfully!"); - } - else + if (!hasSyncStatus()) { PCPP_LOG_DEBUG("DoIP packet has no syncStatus!"); + return; } + shortenLayer(SYNC_STATUS_OFFSET, SYNC_STATUS_LEN); + setPayloadLength(FIXED_LEN - DOIP_HEADER_LEN); } std::string DoIpVehicleAnnouncement::getSummary() const @@ -904,7 +890,7 @@ namespace pcpp DoIpAliveCheckResponse::DoIpAliveCheckResponse(uint16_t sourceAddress) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), DOIP_SOURCE_ADDRESS_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), DOIP_SOURCE_ADDRESS_LEN); setSourceAddress(sourceAddress); } @@ -936,7 +922,7 @@ namespace pcpp DoIpDiagnosticPowerModeResponse::DoIpDiagnosticPowerModeResponse(DoIpDiagnosticPowerModeCodes code) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setPowerModeCode(code); } @@ -976,7 +962,7 @@ namespace pcpp uint8_t maxConcurrentSockets, uint8_t currentlyOpenSockets) : DoIpLayer(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), FIXED_LEN - DOIP_HEADER_LEN); setNodeType(nodeType); setMaxConcurrentSockets(maxConcurrentSockets); @@ -1024,15 +1010,14 @@ namespace pcpp void DoIpEntityStatusResponse::clearMaxDataSize() { - if (hasMaxDataSize()) - { - shortenLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); - PCPP_LOG_DEBUG("MaxDataSize has been removed successfully!"); - } - else + if (!hasMaxDataSize()) { PCPP_LOG_DEBUG("DoIP packet has no MaxDataSize field!"); + return; } + shortenLayer(MAX_DATA_SIZE_OFFSET, MAX_DATA_SIZE_LEN); + setPayloadLength(FIXED_LEN - DOIP_HEADER_LEN); + PCPP_LOG_DEBUG("MaxDataSize has been removed successfully!"); } void DoIpEntityStatusResponse::setMaxConcurrentSockets(uint8_t sockets) @@ -1111,7 +1096,7 @@ namespace pcpp const std::vector& diagData) : DoIpDiagnosticBase(MIN_LEN + diagData.size()) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), MIN_LEN + diagData.size()); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), MIN_LEN + diagData.size()); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); setDiagnosticData(diagData); @@ -1162,7 +1147,7 @@ namespace pcpp DoIpPayloadTypes type) : DoIpDiagnosticBase(FIXED_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, type, (FIXED_LEN - DOIP_HEADER_LEN)); setSourceAddress(sourceAddress); setTargetAddress(targetAddress); } @@ -1179,12 +1164,11 @@ namespace pcpp std::vector DoIpDiagnosticResponseMessageBase::getPreviousMessage() const { - if (hasPreviousMessage()) - { - const uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; - return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); - } - return {}; + if (!hasPreviousMessage()) + return {}; + + const uint8_t* dataPtr = m_Data + PREVIOUS_MSG_OFFSET; + return std::vector(dataPtr, dataPtr + (m_DataLen - PREVIOUS_MSG_OFFSET)); } bool DoIpDiagnosticResponseMessageBase::hasPreviousMessage() const @@ -1198,7 +1182,7 @@ namespace pcpp const size_t currentPayloadLen = m_DataLen - PREVIOUS_MSG_OFFSET; setPayloadLength(newPayloadLen); - ptrdiff_t layerExtensionLen = static_cast(msg.size()) - static_cast(currentPayloadLen); + int layerExtensionLen = static_cast(msg.size()) - static_cast(currentPayloadLen); if (layerExtensionLen > 0) { extendLayer(PREVIOUS_MSG_OFFSET + currentPayloadLen, layerExtensionLen); @@ -1212,15 +1196,14 @@ namespace pcpp void DoIpDiagnosticResponseMessageBase::clearPreviousMessage() { - if (hasPreviousMessage()) - { - shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); - PCPP_LOG_DEBUG("PreviousMessage has been removed successfully!"); - } - else + if (!hasPreviousMessage()) { PCPP_LOG_DEBUG("DoIP packet has no PreviousMessage field!"); + return; } + shortenLayer(FIXED_LEN, (m_DataLen - FIXED_LEN)); + setPayloadLength(FIXED_LEN - DOIP_HEADER_LEN); + PCPP_LOG_DEBUG("PreviousMessage field has been removed successfully!"); } //~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1320,7 +1303,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~| DoIpAliveCheckRequest::DoIpAliveCheckRequest() : DoIpLayer(DOIP_HEADER_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), 0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1328,7 +1311,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| DoIpVehicleIdentificationRequest::DoIpVehicleIdentificationRequest() : DoIpLayer(DOIP_HEADER_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), 0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1336,7 +1319,7 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| DoIpDiagnosticPowerModeRequest::DoIpDiagnosticPowerModeRequest() : DoIpLayer(DOIP_HEADER_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), 0); } //~~~~~~~~~~~~~~~~~~~~~~~~| @@ -1344,6 +1327,6 @@ namespace pcpp //~~~~~~~~~~~~~~~~~~~~~~~~| DoIpEntityStatusRequest::DoIpEntityStatusRequest() : DoIpLayer(DOIP_HEADER_LEN) { - setHeaderFields(DoIpProtocolVersion::Version02Iso2012, getPayloadType(), 0); + setHeaderFields(DoIpProtocolVersion::ISO13400_2012, getPayloadType(), 0); } } // namespace pcpp diff --git a/Tests/Packet++Test/Tests/DoIpTests.cpp b/Tests/Packet++Test/Tests/DoIpTests.cpp index fd386f992c..dce6fd0eda 100644 --- a/Tests/Packet++Test/Tests/DoIpTests.cpp +++ b/Tests/Packet++Test/Tests/DoIpTests.cpp @@ -38,7 +38,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation request"); @@ -74,6 +74,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) unsigned char bytes[] = { 0x2, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, 0xb, 0xe, 0x80, 0x0, 0x1, 0x2, 0x3, 0x4, 0x05, 0x05, 0x05, 0x05 }; + unsigned char bytesWithoutOem[] = { 0x2, 0xfd, 0x0, 0x5, 0x0, 0x0, 0x0, 0x7, 0xe, 0x80, 0x0, 0x1, 0x2, 0x3, 0x4 }; std::array isoReserved{ 0x1, 0x2, 0x3, 0x4 }; std::array oemField{ 0x5, 0x5, 0x5, 0x5 }; @@ -89,12 +90,12 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 19), bytes, 19); // check for setting invalid protocol version, will be applicable for all derived classes - PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); doipLayer.setProtocolVersion(0x55); - PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::UnknownVersion, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::UNKNOWN, enumclass); PTF_ASSERT_EQUAL(doipLayer.getProtocolVersionAsStr(), "Unknown Protocol Version"); - doipLayer.setProtocolVersion(pcpp::DoIpProtocolVersion::Version02Iso2012); - PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + doipLayer.setProtocolVersion(pcpp::DoIpProtocolVersion::ISO13400_2012); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Routing activation request"); @@ -111,7 +112,7 @@ PTF_TEST_CASE(DoIpRoutingActivationRequestPacketCreation) PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 73 - 4); - PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 4) - 15, bytes, 15); + PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (73 - 4) - 15, bytesWithoutOem, 15); PTF_ASSERT_VECTORS_EQUAL(doipLayer.getReservedIso(), isoReserved); PTF_ASSERT_FALSE(doipLayer.hasReservedOem()); PTF_ASSERT_EQUAL(doipLayer.getSummary(), @@ -146,7 +147,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketParsing) auto* doipLayer = RoutingActivationResponse.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Routing activation response"); @@ -203,7 +204,7 @@ PTF_TEST_CASE(DoIpRoutingActivationResponsePacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 75); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (75 - 21), bytes, 21); - PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Routing activation response"); @@ -245,7 +246,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketParsing) auto* doipLayer = GenericHeaderNack.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Generic DOIP header Nack"); @@ -279,7 +280,7 @@ PTF_TEST_CASE(DoIpGenericHeaderNackPacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 51); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); - PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::GENERIC_HEADER_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Generic DOIP header Nack"); @@ -314,7 +315,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSummary(), "EID: 4241554e4545\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, enumclass); @@ -353,7 +354,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWEIDPacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 56); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (56 - 14), bytes, 14); - PTF_ASSERT_EQUAL(withEID.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(withEID.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(withEID.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(withEID.getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_EID, enumclass); @@ -386,7 +387,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketParsing) auto* doipLayer = VehicleIdentificationRequestVIN.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, enumclass); @@ -430,7 +431,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWVINPacketCreation) PTF_ASSERT_EQUAL(doIpPacket.getRawPacket()->getRawDataLen(), 67); PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 25), bytes, 25); - PTF_ASSERT_EQUAL(withVin.getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(withVin.getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(withVin.getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(withVin.getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST_WITH_VIN, enumclass); @@ -473,7 +474,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketParsing) doipLayer->getSummary(), "VIN: BAUNEE4MZ17042403\nLogical address: 0x4010\nEID: 001a37bfee74\nGID: 001a37bfee74\nFurther action required: No further action required (0x0)\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), @@ -527,7 +528,7 @@ PTF_TEST_CASE(DoIpVehicleAnnouncementPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (83 - 41), bytes, 41); auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ANNOUNCEMENT_MESSAGE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), @@ -572,7 +573,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketParsing) auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request"); @@ -606,7 +607,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Vehicle identification request"); @@ -636,7 +637,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketParsing) PTF_ASSERT_NOT_NULL(doipLayer); PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x0\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); @@ -670,7 +671,7 @@ PTF_TEST_CASE(DoIpAliveCheckResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (52 - 10), bytes, 10); auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check response"); @@ -705,7 +706,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Diagnostic power mode: not ready (0x0)\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); @@ -739,7 +740,7 @@ PTF_TEST_CASE(DoIpPowerModeResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (51 - 9), bytes, 9); auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode response information"); @@ -777,7 +778,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketParsing) doipLayer->getSummary(), "Entity status: DoIP gateway (0x0)\nMax Concurrent Socket: 1\nCurrently Opened Socket: 0\nMax Data Size: 0x00000fff\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status response"); @@ -837,7 +838,7 @@ PTF_TEST_CASE(DoIpEntityStatusResponsePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (57 - 15), bytes, 15); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_RESPONSE, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status response"); @@ -880,7 +881,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0xe80\nTarget Address: 0x4010\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); @@ -927,7 +928,7 @@ PTF_TEST_CASE(DoIpDiagnosticMessagePacketCreation) PTF_ASSERT_EQUAL(doipLayer->getSourceAddress(), 0x2030); PTF_ASSERT_EQUAL(doipLayer->getTargetAddress(), 0x4040); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message"); @@ -968,7 +969,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketParsing) PTF_ASSERT_EQUAL(doipLayer->getSummary(), "Source Address: 0x4010\nTarget Address: 0xe80\nACK code: ACK (0x0)\nPrevious message: 22f101\n"); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); @@ -1008,7 +1009,7 @@ PTF_TEST_CASE(DoIpDiagnosticAckMessagePacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (67 - 13), bytes, 13); auto* doipLayer = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_POS_ACK, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic message Ack"); @@ -1062,7 +1063,7 @@ PTF_TEST_CASE(DoIpDiagnosticNackMessagePacketParsing) auto* nackLayer = diagnosticNackPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(nackLayer); - PTF_ASSERT_EQUAL(nackLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(nackLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(nackLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(nackLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_NEG_ACK, enumclass); PTF_ASSERT_EQUAL(nackLayer->getPayloadTypeAsStr(), "Diagnostic message Nack"); @@ -1159,7 +1160,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketParsing) auto* doipLayer = PowerModeRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Diagnostic power mode request information"); @@ -1192,7 +1193,7 @@ PTF_TEST_CASE(DoIpPowerModeRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::DIAGNOSTIC_POWER_MODE_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Diagnostic power mode request information"); @@ -1223,7 +1224,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketParsing) auto* doipLayer = EntityStatusRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "DOIP entity status request"); @@ -1256,7 +1257,7 @@ PTF_TEST_CASE(DoIpEntityStatusRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); pcpp::DoIpLayer* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ENTITY_STATUS_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "DOIP entity status request"); @@ -1285,7 +1286,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketParsing) auto* doipLayer = AliveCheckRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Alive check request"); @@ -1318,7 +1319,7 @@ PTF_TEST_CASE(DoIpAliveCheckRequestPacketCreation) PTF_ASSERT_BUF_COMPARE(doIpPacket.getRawPacket()->getRawData() + (50 - 8), bytes, 8); auto* _doipLayer2 = doIpPacket.getLayerOfType(); - PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::Version02Iso2012, enumclass); + PTF_ASSERT_EQUAL(_doipLayer2->getProtocolVersion(), pcpp::DoIpProtocolVersion::ISO13400_2012, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getInvertProtocolVersion(), 0xFD); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadType(), pcpp::DoIpPayloadTypes::ALIVE_CHECK_REQUEST, enumclass); PTF_ASSERT_EQUAL(_doipLayer2->getPayloadTypeAsStr(), "Alive check request"); @@ -1347,7 +1348,7 @@ PTF_TEST_CASE(DoIpVehicleIdentificationRequestWithDefaultVersPacketParsing) auto* doipLayer = vehicleIdentificationRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(doipLayer); - PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::DefaultVersion, enumclass); + PTF_ASSERT_EQUAL(doipLayer->getProtocolVersion(), pcpp::DoIpProtocolVersion::DEFAULT_VALUE, enumclass); PTF_ASSERT_EQUAL(doipLayer->getInvertProtocolVersion(), 0x00); PTF_ASSERT_EQUAL(doipLayer->getPayloadType(), pcpp::DoIpPayloadTypes::VEHICLE_IDENTIFICATION_REQUEST, enumclass); PTF_ASSERT_EQUAL(doipLayer->getPayloadTypeAsStr(), "Vehicle identification request");