From a50cf6874bf82870fa35a4b70b4eb0f46106d2dd Mon Sep 17 00:00:00 2001 From: raissi-oussema Date: Sun, 8 Dec 2024 01:57:14 -0500 Subject: [PATCH 01/16] 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/16] 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/16] 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/16] 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/16] .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/16] 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/16] 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/16] 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/16] 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/16] . 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/16] 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/16] 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/16] 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/16] 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/16] 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/16] 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"; }