diff --git a/Common++/header/Logger.h b/Common++/header/Logger.h index f3d2d425a2..67d4342c88 100644 --- a/Common++/header/Logger.h +++ b/Common++/header/Logger.h @@ -69,6 +69,7 @@ namespace pcpp PacketLogModuleNdpLayer, ///< NdpLayer module (Packet++) PacketLogModuleFtpLayer, ///< FtpLayer module (Packet++) PacketLogModuleSomeIpLayer, ///< SomeIpLayer module (Packet++) + PacketLogModuleSomeIpSdLayer, ///< SomeIpSdLayer module (Packet++) PacketLogModuleWakeOnLanLayer, ///< WakeOnLanLayer module (Packet++) PcapLogModuleWinPcapLiveDevice, ///< WinPcapLiveDevice module (Pcap++) PcapLogModuleRemoteDevice, ///< WinPcapRemoteDevice module (Pcap++) diff --git a/Packet++/header/SomeIpLayer.h b/Packet++/header/SomeIpLayer.h index 0bead9c0bb..ef6418fbc2 100644 --- a/Packet++/header/SomeIpLayer.h +++ b/Packet++/header/SomeIpLayer.h @@ -87,7 +87,7 @@ class SomeIpLayer : public Layer /** * 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 someiphdr) + * @param[in] data A pointer to the raw data (will be casted to someiphdr) * @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 @@ -133,7 +133,7 @@ class SomeIpLayer : public Layer /** * Get a pointer to the basic SOME/IP header. Notice this points directly to the data, so every change will change * the actual packet data - * @return A pointer to the @ref someiphdr + * @return A pointer to the someiphdr */ someiphdr *getSomeIpHeader() const { return (someiphdr *)m_Data; } @@ -328,7 +328,7 @@ class SomeIpLayer : public Layer virtual void computeCalculateFields() {} /** - * Identifies the following next layers: SomeIpLayer, SomeIpTpLayer. Otherwise sets PayloadLayer + * Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); diff --git a/Packet++/header/SomeIpSdLayer.h b/Packet++/header/SomeIpSdLayer.h new file mode 100644 index 0000000000..dfa87e9471 --- /dev/null +++ b/Packet++/header/SomeIpSdLayer.h @@ -0,0 +1,767 @@ +#ifndef PACKETPP_SOMEIPSD_LAYER +#define PACKETPP_SOMEIPSD_LAYER + +#include "EndianPortable.h" +#include "IpAddress.h" +#include "Layer.h" +#include "SomeIpLayer.h" +#include +#include +#include +#include +#include +#include + +/// @file + +/** + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib + */ +namespace pcpp +{ +/** + * Types of protocols that can be referenced in SOME/IP-SD + */ +enum SomeIpSdProtocolType : uint8_t +{ + /** TCP */ + SD_TCP = 0x06, + /** UDP */ + SD_UDP = 0x11 +}; + +class SomeIpSdLayer; + +/** + * @class SomeIpSdOption + * Base class of the SOME/IP-SD options. Cannot be instantiated. + */ +class SomeIpSdOption +{ +public: + friend class SomeIpSdLayer; + + /** + * Types of options currently available for the SOME/IP-SD protocol + */ + enum class OptionType : uint8_t + { + /** Unknown Option Type */ + Unknown = 0x00, + /** Configuration Option */ + ConfigurationString = 0x01, + /** Load Balancing Option */ + LoadBalancing = 0x02, + /** IPv4 Endpoint Option */ + IPv4Endpoint = 0x04, + /** IPv6 Endpoint Option */ + IPv6Endpoint = 0x06, + /** IPv4 Multicast Option */ + IPv4Multicast = 0x14, + /** IPv6 Multicast Option */ + IPv6Multicast = 0x16, + /** IPv4 SD Endpoint Option */ + IPv4SdEndpoint = 0x24, + /** IPv6 SD Endpoint Option */ + IPv6SdEndpoint = 0x26 + }; + + /** + * @struct someipsdhdroptionsbase + * Represents the common base for SOME/IP-SD header options + */ +#pragma pack(push, 1) + struct someipsdhdroptionsbase + { + /** Length - excluding the 16 bit Length field and the 8 bit type flag */ + uint16_t length; + /** Type */ + uint8_t type; + /** Reserved */ + uint8_t reserved; + }; +#pragma pack(pop) + + /** + * Destroy the SOME/IP-SD Option object and delete allocated data if it has been allocated by a constructor + */ + virtual ~SomeIpSdOption(); + + /** + * Get the Option Type + * @return OptionType + */ + OptionType getType() const; + + /** + * Get the Length of the SOME/IP-SD option + * @return size_t + */ + size_t getLength() const { return m_DataLen; } + + /** + * Get the internal data of the SOME/IP-SD Option + * @return uint8_t* + */ + uint8_t *getDataPtr() const; + + /** + * Get a pointer to the SOME/IP-SD Option base header + * @return someipsdhdroptionsbase* + */ + someipsdhdroptionsbase *getSomeIpSdOptionHeader() const; + +protected: + const IDataContainer *m_DataContainer; + size_t m_Offset; + uint8_t *m_ShadowData; + size_t m_DataLen; + + SomeIpSdOption() : m_DataContainer(nullptr), m_Offset(0), m_ShadowData(nullptr), m_DataLen(0) {} + + SomeIpSdOption(const IDataContainer *dataContainer, size_t offset) + : m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(nullptr), m_DataLen(0) {} + + void initStdFields(OptionType type); + + SomeIpSdOption(const SomeIpSdOption &) = delete; + SomeIpSdOption &operator=(const SomeIpSdOption &) = delete; +}; + +/** + * @class SomeIpSdIPv4Option + * Implements the following SOME/IP-SD Options: IPv4 Endpoint, IPv4 Multicast, IPv4 SD Endpoint + */ +class SomeIpSdIPv4Option : public SomeIpSdOption +{ +public: + friend class SomeIpSdLayer; + + /** + * Types of options which are implemented with this class + */ + enum IPv4OptionType + { + /** IPv4 Endpoint Option */ + IPv4Endpoint, + /** IPv4 Multicast Option */ + IPv4Multicast, + /** IPv4 SD Endpoint Option */ + IPv4SdEndpoint, + }; + + /** + * Construct a new SomeIpSdIPv4 Option object + * @param[in] type IPv4 Option type + * @param[in] ipAddress Ipv4 address to use + * @param[in] port Port to use + * @param[in] l4Protocol Protocol to use + */ + SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); + + /** + * Construct a new SomeIpSdIPv4 Option object from already existing memory + * @param[in] dataContainer Data containing the SomeIpSdIPv4 Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdIPv4Option(const IDataContainer *dataContainer, size_t offset); + + /** + * Get the Ip Address + * @return IPv4Address + */ + IPv4Address getIpAddress() const; + + /** + * Get the Port + * @return uint16_t + */ + uint16_t getPort() const; + + /** + * Get the Protocol + * @return SomeIpSdProtocolType + */ + SomeIpSdProtocolType getProtocol() const; + +private: + /** + * @struct someipsdhdroptionsipv4 + * Represents the IPv4 option types for the SOME/IP-SD header + */ +#pragma pack(push, 1) + struct someipsdhdroptionsipv4 : someipsdhdroptionsbase + { + /* IPv4-Address field */ + uint32_t ipv4Address; + /* Reserved */ + uint8_t reserved; + /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ + SomeIpSdProtocolType l4Protocol; + /* Port number of UDP or TCP */ + uint16_t portNumber; + }; +#pragma pack(pop) +}; + +/** + * @class SomeIpSdIPv6Option + * Implements the following SOME/IP-SD Options: IPv6 Endpoint, IPv6 Multicast, IPv6 SD Endpoint + */ +class SomeIpSdIPv6Option : public SomeIpSdOption +{ +public: + friend class SomeIpSdLayer; + + /** + * Types of options which are implemented with this class + */ + enum IPv6OptionType + { + /** IPv6 Endpoint Option */ + IPv6Endpoint, + /** IPv6 Multicast Option */ + IPv6Multicast, + /** IPv6 SD Endpoint Option */ + IPv6SdEndpoint, + }; + + /** + * Construct a new SomeIpSdIPv6 Option object + * @param[in] type IPv6 Option type + * @param[in] ipAddress Ipv6 address to use + * @param[in] port Port to use + * @param[in] l4Protocol Protocol to use + */ + SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); + + /** + * Construct a new SomeIpSdIPv6 Option object from already existing memory + * @param[in] dataContainer Data containing the SomeIpSdIPv6 Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdIPv6Option(const IDataContainer *dataContainer, size_t offset); + + /** + * Get the Ip Address + * @return IPv6Address + */ + IPv6Address getIpAddress() const; + + /** + * Get the Port + * @return uint16_t + */ + uint16_t getPort() const; + + /** + * Get the Protocol + * @return SomeIpSdProtocolType + */ + SomeIpSdProtocolType getProtocol() const; + +private: + /** + * @struct someipsdhdroptionsipv6 + * Represents the IPv6 option types for the SOME/IP-SD header + */ +#pragma pack(push, 1) + struct someipsdhdroptionsipv6 : someipsdhdroptionsbase + { + /* IPv6-Address field */ + uint8_t ipv6Address[16]; + /* Reserved */ + uint8_t reserved; + /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ + SomeIpSdProtocolType l4Protocol; + /* Port number of UDP or TCP */ + uint16_t portNumber; + }; +#pragma pack(pop) +}; + +/** + * @class SomeIpSdConfigurationOption + * Implements the Configuration option of SOME/IP-SD protocol + */ +class SomeIpSdConfigurationOption : public SomeIpSdOption +{ +public: + friend class SomeIpSdLayer; + + /** + * Construct a new Configuration Option object + * @param[in] configurationString the configuration string + */ + SomeIpSdConfigurationOption(const std::string &configurationString); + + /** + * Construct a new Configuration Option object from already existing memory + * @param[in] dataContainer Data containing the Configuration Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdConfigurationOption(const IDataContainer *dataContainer, size_t offset); + + /** + * Get the configuration string + * @return std::string + */ + std::string getConfigurationString() const; +}; + +/** + * @class SomeIpSdLoadBalancingOption + * Implements the Load Balancing option of SOME/IP-SD protocol + */ +class SomeIpSdLoadBalancingOption : public SomeIpSdOption +{ +public: + friend class SomeIpSdLayer; + + /** + * Construct a new Load Balancing object + * @param[in] priority Priority of this instance + * @param[in] weight Weight of this instance + */ + SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight); + + /** + * Construct a new Option object from already existing memory + * @param[in] dataContainer Data containing the option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdLoadBalancingOption(const IDataContainer *dataContainer, size_t offset); + + /** + * Get the priority fild + * @return uint16_t + */ + uint16_t getPriority() const; + + /** + * Get the weight field + * @return uint16_t + */ + uint16_t getWeight() const; + +private: + /** + * @struct someipsdhdroptionsload + * Represents the Load Balancing option header for SOME/IP-SD + */ +#pragma pack(push, 1) + struct someipsdhdroptionsload : someipsdhdroptionsbase + { + /* Priority field */ + uint16_t priority; + /* Weight field */ + uint16_t weight; + }; +#pragma pack(pop) +}; + +/** + * @class SomeIpSdEntry + * Implementation of the SOME/IP-SD Service Entry and Eventgroup Entry Type + */ +class SomeIpSdEntry +{ +public: + friend class SomeIpSdLayer; + + /** + * Types of entries that can occur in SOME/IP-SD + */ + enum class EntryType : uint8_t + { + /** Find Service */ + FindService, + /** Offer Service */ + OfferService, + /** Stop Offer Service */ + StopOfferService, + /** Subscribe Eventgroup */ + SubscribeEventgroup, + /** Stop Subscribe Eventgroup */ + StopSubscribeEventgroup, + /** Subscribe Eventgroup Acknowledgment */ + SubscribeEventgroupAck, + /** Subscribe Eventgroup Negative Acknowledgement */ + SubscribeEventgroupNack, + /** Unknown Entry Type */ + UnknownEntryType + }; + + /** + * @struct someipsdhdrentry + * Represents the Service Entry Type and Eventgroup Entry Type + */ +#pragma pack(push, 1) + struct someipsdhdrentry + { + /** Type */ + uint8_t type; + /** Index 1st option */ + uint8_t indexFirstOption; + /** Index 2nd option */ + uint8_t indexSecondOption; +#if (BYTE_ORDER == LITTLE_ENDIAN) + uint8_t + /** Numbers of Option #2 (4bit) */ + nrOpt2 : 4, + /** Numbers of Option #1 (4bit) */ + nrOpt1 : 4; +#else + uint8_t + /** Numbers of Option #1 (4bit) */ + nrOpt1 : 4, + /** Numbers of Option #2 (4bit) */ + nrOpt2 : 4; +#endif + /** Service ID */ + uint16_t serviceID; + /** Instance ID */ + uint16_t instanceID; + /** Major Version (8 bit) + TTL (24 bit) */ + uint32_t majorVersion_ttl; + /** Minor Version (Service Entry Type) or Counter + Eventgroup ID (Eventgroup Entry Type) */ + uint32_t data; + }; +#pragma pack(pop) + + /** + * Construct a new SOME/IP-SD Service Entry Type + * @param[in] type Type to create + * @param[in] serviceID ServiceID to use + * @param[in] instanceID InstanceID to use + * @param[in] majorVersion MajorVersion to use + * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types + * @param[in] minorVersion MinorVersion to use + */ + SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, + uint32_t minorVersion); + + /** + * Construct a new SOME/IP-SD Eventgroup Entry Type + * @param[in] type Type to create + * @param[in] serviceID ServiceID to use + * @param[in] instanceID InstanceID to use + * @param[in] majorVersion MajorVersion to use + * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types + * @param[in] counter Counter value to use + * @param[in] eventGroupID EventgroupId to use + */ + SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, + uint8_t counter, uint16_t eventGroupID); + + /** + * Construct a new SomeIpSdEntry object from existing data + * @param[in] pSomeIpSdLayer Layer that this entry is created for + * @param[in] offset Offset for pSomeIpSdLayer + */ + SomeIpSdEntry(const SomeIpSdLayer *pSomeIpSdLayer, size_t offset); + + /** + * Destroy the SomeIpSd Entry object and delete allocated data if it has been allocated by a constructor + */ + ~SomeIpSdEntry(); + + /** + * Get the internal data of the SOME/IP-SD Entry + * @return uint8_t* + */ + uint8_t *getDataPtr() const; + + /** + * Get a pointer to the SOME/IP-SD Entry header + * @return someipsdhdrentry* + */ + someipsdhdrentry *getSomeIpSdEntryHeader() const; + + /** + * Get the Entry Type + * @return EntryType + */ + EntryType getType() const { return m_EntryType; } + + /** + * Get the Length of the SomeIpSd Entry + * @return size_t + */ + size_t getLength() const { return sizeof(someipsdhdrentry); } + + /** + * Get the number of Options of this Entry + * @return uint32_t + */ + uint32_t getNumOptions() const; + + /** + * Get the Service Id in host endianness + * @return uint16_t + */ + uint16_t getServiceId() const; + + /** + * Set the Service Id + * @param[in] serviceId + */ + void setServiceId(uint16_t serviceId); + + /** + * Get the Instance Id in host endianness + * @return uint16_t + */ + uint16_t getInstanceId() const; + + /** + * Set the Instance Id + * @param[in] instanceId + */ + void setInstanceId(uint16_t instanceId); + + /** + * Get the Major version field in host endianness + * @return uint16_t + */ + uint8_t getMajorVersion() const; + + /** + * Set the Major Version + * @param[in] majorVersion + */ + void setMajorVersion(uint8_t majorVersion); + + /** + * Get the Ttl field + * @return uint32_t + */ + uint32_t getTtl() const; + + /** + * Set the Ttl field + * @param[in] ttl + */ + void setTtl(uint32_t ttl); + + /** + * Get the minor version + * @return uint32_t + */ + uint32_t getMinorVersion() const; + + /** + * Set the minor version + * @param[in] minorVersion + */ + void setMinorVersion(uint32_t minorVersion); + + /** + * Get the counter value + * @return uint32_t + */ + uint8_t getCounter() const; + + /** + * Set the counter value + * @param[in] counter + */ + void setCounter(uint8_t counter); + + /** + * Get the eventgroup id + * @return uint32_t + */ + uint16_t getEventgroupId() const; + + /** + * Set the eventgroup id + * @param[in] eventgroupID + */ + void setEventgroupId(uint16_t eventgroupID); + +private: + /** + * These are the entry types used by SOME/IP-SD. They cannot be used for parameter passing since the values + * are not unique. + */ + enum class TypeInternal : uint8_t + { + /** Find Service */ + FindService_Internal = 0x00, + /** Offer Service / Stop Offer Service */ + OfferService_Internal = 0x01, + /** Subscribe Eventgroup & Stop Subscribe Eventgroup */ + SubscribeEventgroup_Internal = 0x06, + /** Subscribe Eventgroup Acknowledgment / Negative Acknowledgement */ + SubscribeEventgroupAck_Internal = 0x07, + }; + + EntryType m_EntryType; + const SomeIpSdLayer *m_Layer; + size_t m_Offset; + uint8_t *m_ShadowData; + + void initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL); + + SomeIpSdEntry(const SomeIpSdEntry &) = delete; + SomeIpSdEntry &operator=(const SomeIpSdEntry &) = delete; + + static const uint32_t SOMEIPSD_HDR_ENTRY_MASK_TTL = 0x00FFFFFF; +}; + +/** + * @class SomeIpSdLayer + * Implementation of the SOME/IP-SD protocol + */ +class SomeIpSdLayer : public SomeIpLayer +{ +public: + friend class SomeIpSdEntry; + + typedef SomeIpSdEntry* EntryPtr; + typedef std::vector EntriesVec; + typedef SomeIpSdOption* OptionPtr; + typedef std::vector OptionsVec; + + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + SomeIpSdLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet); + + /** + * Construct a new SomeIpSdLayer object + * @param[in] serviceID Service ID + * @param[in] methodID Method ID + * @param[in] clientID Client ID + * @param[in] sessionID Session ID + * @param[in] interfaceVersion Interface Version + * @param[in] type Type of the message + * @param[in] returnCode Return Code + * @param[in] flags Flags that shall be used in the header + */ + SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags); + + /** + * Destroy the layer object + */ + ~SomeIpSdLayer() {} + + /** + * Checks if given port is a SOME/IP-SD protocol port + * @param[in] port Port to check + * @return true if SOME/IP-SD protocol port, false if not + */ + static bool isSomeIpSdPort(uint16_t port) { return port == 30490; } + + /** + * Get the Flags of the layer + * @return uint8_t Flags + */ + uint8_t getFlags() const; + + /** + * Set the Flags of the layer + * @param[in] flags Flags to set + */ + void setFlags(uint8_t flags); + + /** + * Get the number of entries in this layer + * @return uint32_t + */ + uint32_t getNumEntries() const; + + /** + * Get the number of options in this layer + * @return uint32_t + */ + uint32_t getNumOptions() const; + + /** + * Get the Entries from this layer + * @return EntriesVec Vector holding pointers to the options + */ + const EntriesVec getEntries() const; + + /** + * Get the Options from this layer + * @return OptionsVec Vector holding pointers to the options + */ + const OptionsVec getOptions() const; + + /** + * Get the Options from a specific Entry + * @param[in] index Index of the Entry, starting with 0. + * @return OptionsVec Vector holding pointers to the options + */ + const OptionsVec getOptionsFromEntry(uint32_t index) const; + + /** + * Adds a given entry to the layer and returns the index of the entry + * @param[in] entry Pointer to the entry that shall be added to the layer + * @return uint32_t Returns the index of the entry starting with 0 + */ + uint32_t addEntry(const SomeIpSdEntry &entry); + + /** + * Adds an option to an entry that has already been added to the layer by using addEntry(). The option + * is also added to the layer itself. If the option cannot by assigned to the entry, the option is not + * copied into the layer. + * @param[in] indexEntry Index of the entry where the option shall be added. First Entry has index 0 + * @param[in] option Pointer to the option that shall be added + * @return True if the option could be assigned to the entry and was copied into the layer, false otherwise + */ + bool addOptionTo(uint32_t indexEntry, const SomeIpSdOption &option); + + /** + * Does nothing for this layer + */ + void computeCalculateFields() {}; + + /** + * @return The string representation of the SOME/IP-SD layer + */ + std::string toString() const; + +private: + /** + * @struct someipsdhdr + * Represents an SOME/IP-SD protocol header + */ +#pragma pack(push, 1) + struct someipsdhdr : someiphdr + { + /** Flags (8 bit) */ + uint8_t flags; + /** Reserved1 field (Bits 0-7 of 24-bits reserved field) */ + uint8_t reserved1; + /** Reserved2 field (Bits 8-15 of 24-bits reserved field) */ + uint8_t reserved2; + /** Reserved3 field (Bits 16-23 of 24-bits reserved field) */ + uint8_t reserved3; + }; +#pragma pack(pop) + + uint32_t m_NumOptions; + + uint32_t countOptions(); + uint32_t findOption(const SomeIpSdOption &option); + void addOption(const SomeIpSdOption &option); + bool addOptionIndex(uint32_t indexEntry, uint32_t indexOffset); + OptionPtr parseOption(SomeIpSdOption::OptionType type, size_t offset) const; + + size_t getLenEntries() const; + size_t getLenOptions() const; + void setLenEntries(uint32_t length); + void setLenOptions(uint32_t length); +}; + +} // namespace pcpp +#endif /* PACKETPP_SOMEIPSD_LAYER */ diff --git a/Packet++/src/SomeIpLayer.cpp b/Packet++/src/SomeIpLayer.cpp index 4547b99c29..797af78734 100644 --- a/Packet++/src/SomeIpLayer.cpp +++ b/Packet++/src/SomeIpLayer.cpp @@ -1,6 +1,7 @@ #define LOG_MODULE PacketLogModuleSomeIpLayer #include "SomeIpLayer.h" +#include "SomeIpSdLayer.h" #include "Packet.h" #include "PayloadLayer.h" #include "EndianPortable.h" @@ -34,7 +35,7 @@ SomeIpLayer::SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientI setServiceID(serviceID); setMethodID(methodID); - setPayloadLength(dataLen); + setPayloadLength((uint32_t)dataLen); setClientID(clientID); setSessionID(sessionID); setProtocolVersion(0x01); @@ -78,9 +79,9 @@ Layer* SomeIpLayer::parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevL return new PayloadLayer(data, dataLen, prevLayer, packet); } - if (hdr->serviceID == 0xFFFF && hdr->methodID == 0x8100) + if (be16toh(hdr->serviceID) == 0xFFFF && be16toh(hdr->methodID) == 0x8100) { - return new PayloadLayer(data, dataLen, prevLayer, packet); // TODO: impl SomeIpSdLayer() + return new SomeIpSdLayer(data, dataLen, prevLayer, packet); } else if ((hdr->msgType & (uint8_t)SomeIpLayer::MsgType::TP_REQUEST) != 0) { @@ -94,7 +95,8 @@ Layer* SomeIpLayer::parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevL bool SomeIpLayer::isSomeIpPort(uint16_t port) { - return std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), + return SomeIpSdLayer::isSomeIpSdPort(port) || + std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), [&](const uint16_t &someIpPort) { return someIpPort == port; }); } @@ -228,7 +230,7 @@ uint8_t SomeIpLayer::getMessageTypeAsInt() const void SomeIpLayer::setMessageType(MsgType type) { - setMessageType((uint8_t)type); + setMessageType(static_cast(type)); } void SomeIpLayer::setMessageType(uint8_t type) @@ -295,7 +297,7 @@ SomeIpTpLayer::SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t cli setServiceID(serviceID); setMethodID(methodID); - setPayloadLength(dataLen + sizeof(uint32_t)); + setPayloadLength((uint32_t)(dataLen + sizeof(uint32_t))); setClientID(clientID); setSessionID(sessionID); setProtocolVersion(0x01); diff --git a/Packet++/src/SomeIpSdLayer.cpp b/Packet++/src/SomeIpSdLayer.cpp new file mode 100644 index 0000000000..2524bd29fd --- /dev/null +++ b/Packet++/src/SomeIpSdLayer.cpp @@ -0,0 +1,789 @@ +#define LOG_MODULE PacketLogModuleSomeIpSdLayer + +#include "SomeIpSdLayer.h" +#include +#include +#include +#include + +namespace pcpp +{ + +/* + * SomeIpSdOption + */ +SomeIpSdOption::~SomeIpSdOption() +{ + if (m_ShadowData != NULL) + delete[] m_ShadowData; +} + +SomeIpSdOption::OptionType SomeIpSdOption::getType() const { + return static_cast(getSomeIpSdOptionHeader()->type); +} + +uint8_t* SomeIpSdOption::getDataPtr() const +{ + if (m_DataContainer != NULL) + return m_DataContainer->getDataPtr(m_Offset); + + return m_ShadowData; +} + +SomeIpSdOption::someipsdhdroptionsbase *SomeIpSdOption::getSomeIpSdOptionHeader() const +{ + return (someipsdhdroptionsbase *)getDataPtr(); +} + +void SomeIpSdOption::initStdFields(OptionType type) +{ + someipsdhdroptionsbase *optionHdr = getSomeIpSdOptionHeader(); + + optionHdr->type = static_cast(type); + /* Length field is excluding length field itself and uint8_t type field */ + optionHdr->length = htobe16((uint16_t)(m_DataLen - sizeof(optionHdr->length) - sizeof(optionHdr->type))); +} + +/* + * SomeIpSdIPv4Option + */ +SomeIpSdIPv4Option::SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, + SomeIpSdProtocolType l4Protocol) +{ + m_DataLen = sizeof(someipsdhdroptionsipv4); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); + + switch(type) + { + case IPv4OptionType::IPv4Endpoint: + initStdFields(OptionType::IPv4Endpoint); + break; + case IPv4OptionType::IPv4Multicast: + initStdFields(OptionType::IPv4Multicast); + break; + case IPv4OptionType::IPv4SdEndpoint: + initStdFields(OptionType::IPv4SdEndpoint); + break; + } + + someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); + hdr->ipv4Address = ipAddress.toInt(); + hdr->portNumber = htobe16(port); + hdr->l4Protocol = l4Protocol; +} + +SomeIpSdIPv4Option::SomeIpSdIPv4Option(const IDataContainer *dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) +{ + m_DataLen = sizeof(someipsdhdroptionsipv4); +} + +IPv4Address SomeIpSdIPv4Option::getIpAddress() const +{ + someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); + IPv4Address ipAddr(hdr->ipv4Address); + + return ipAddr; +} + +uint16_t SomeIpSdIPv4Option::getPort() const +{ + someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); + return be16toh(hdr->portNumber); +} + +SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const +{ + someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); + return hdr->l4Protocol; +} + +/* + * SomeIpSdIPv6Option + */ +SomeIpSdIPv6Option::SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, + SomeIpSdProtocolType l4Protocol) +{ + m_DataLen = sizeof(someipsdhdroptionsipv6); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); + + switch(type) + { + case IPv6OptionType::IPv6Endpoint: + initStdFields(OptionType::IPv6Endpoint); + break; + case IPv6OptionType::IPv6Multicast: + initStdFields(OptionType::IPv6Multicast); + break; + case IPv6OptionType::IPv6SdEndpoint: + initStdFields(OptionType::IPv6SdEndpoint); + break; + } + + someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); + std::memcpy(hdr->ipv6Address, ipAddress.toBytes(), 16); + hdr->portNumber = htobe16(port); + hdr->l4Protocol = l4Protocol; +} + +SomeIpSdIPv6Option::SomeIpSdIPv6Option(const IDataContainer *dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) +{ + m_DataLen = sizeof(someipsdhdroptionsipv6); +} + +IPv6Address SomeIpSdIPv6Option::getIpAddress() const +{ + someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); + IPv6Address ipAddr(hdr->ipv6Address); + + return ipAddr; +} + +uint16_t SomeIpSdIPv6Option::getPort() const +{ + someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); + return be16toh(hdr->portNumber); +} + +SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const +{ + someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); + return hdr->l4Protocol; +} + +/* + * SomeIpSdConfigurationOption + */ +SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const std::string &configurationString) +{ + m_DataLen = configurationString.length() + sizeof(someipsdhdroptionsbase); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); + + initStdFields(OptionType::ConfigurationString); + std::memcpy(getDataPtr() + sizeof(someipsdhdroptionsbase), configurationString.c_str(), + configurationString.length()); +} + +SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const IDataContainer *dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) +{ + m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length); +} + +std::string SomeIpSdConfigurationOption::getConfigurationString() const +{ + return std::string((char *)getDataPtr() + sizeof(someipsdhdroptionsbase), + be16toh(getSomeIpSdOptionHeader()->length) - 1); +} + +/* + * SomeIpSdLoadBalancingOption + */ +SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight) +{ + m_DataLen = sizeof(someipsdhdroptionsload); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); + + initStdFields(OptionType::LoadBalancing); + + someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); + hdr->priority = htobe16(priority); + hdr->weight = htobe16(weight); +} + +SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(const IDataContainer *dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) +{ + m_DataLen = sizeof(someipsdhdroptionsload); +} + +uint16_t SomeIpSdLoadBalancingOption::getPriority() const +{ + someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); + return be16toh(hdr->priority); +} + +uint16_t SomeIpSdLoadBalancingOption::getWeight() const +{ + someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); + return be16toh(hdr->weight); +} + +/* + * SomeIpSdEntry + */ + +SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL, uint32_t minorVersion) +{ + initStdFields(type, serviceID, instanceID, majorVersion, TTL); + setMinorVersion(minorVersion); +} + +SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL, uint8_t counter, uint16_t eventGroupID) +{ + initStdFields(type, serviceID, instanceID, majorVersion, TTL); + setCounter(counter); + setEventgroupId(eventGroupID); +} + +SomeIpSdEntry::SomeIpSdEntry(const SomeIpSdLayer *pSomeIpSdLayer, size_t offset) + : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr) +{ + EntryType entryType; + + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + TypeInternal internalType = static_cast(hdr->type); + auto ttl = getTtl(); + + switch(internalType) + { + case SomeIpSdEntry::TypeInternal::FindService_Internal: + entryType = SomeIpSdEntry::EntryType::FindService; + break; + case SomeIpSdEntry::TypeInternal::OfferService_Internal: + if (ttl == 0) + { + entryType = EntryType::StopOfferService; + } + else + { + entryType = EntryType::OfferService; + } + break; + case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal: + if (ttl == 0) + { + entryType = EntryType::StopSubscribeEventgroup; + } + else + { + entryType = EntryType::SubscribeEventgroup; + } + break; + case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal: + if (ttl == 0) + { + entryType = EntryType::SubscribeEventgroupNack; + } + else + { + entryType = EntryType::SubscribeEventgroupAck; + } + break; + default: + entryType = EntryType::UnknownEntryType; + break; + } + + m_EntryType = entryType; +} + +SomeIpSdEntry::~SomeIpSdEntry() +{ + if (m_ShadowData != NULL) + delete[] m_ShadowData; +} + +uint8_t *SomeIpSdEntry::getDataPtr() const +{ + if (m_Layer != NULL) + return m_Layer->getDataPtr(m_Offset); + + return m_ShadowData; +} + +SomeIpSdEntry::someipsdhdrentry *SomeIpSdEntry::getSomeIpSdEntryHeader() const +{ + return (someipsdhdrentry *)getDataPtr(); +} + +uint32_t SomeIpSdEntry::getNumOptions() const +{ + auto *hdr = getSomeIpSdEntryHeader(); + return hdr->nrOpt1 + hdr->nrOpt2; +} + +uint16_t SomeIpSdEntry::getServiceId() const +{ + return be16toh(getSomeIpSdEntryHeader()->serviceID); +} + +void SomeIpSdEntry::setServiceId(uint16_t serviceId) +{ + getSomeIpSdEntryHeader()->serviceID = htobe16(serviceId); +} + +uint16_t SomeIpSdEntry::getInstanceId() const +{ + return be16toh(getSomeIpSdEntryHeader()->instanceID); +} + +void SomeIpSdEntry::setInstanceId(uint16_t instanceId) +{ + getSomeIpSdEntryHeader()->instanceID = htobe16(instanceId); +} + +uint8_t SomeIpSdEntry::getMajorVersion() const +{ + return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24; +} + +void SomeIpSdEntry::setMajorVersion(uint8_t majorVersion) +{ + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + uint32_t val = (majorVersion << 24) | (be32toh(hdr->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL); + hdr->majorVersion_ttl = htobe32(val); +} + +uint32_t SomeIpSdEntry::getTtl() const +{ + return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL; +} + +void SomeIpSdEntry::setTtl(uint32_t ttl) +{ + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + uint32_t val = (ttl & SOMEIPSD_HDR_ENTRY_MASK_TTL) | (be32toh(hdr->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL); + hdr->majorVersion_ttl = htobe32(val); +} + +uint32_t SomeIpSdEntry::getMinorVersion() const +{ + return be32toh(getSomeIpSdEntryHeader()->data); +} + +void SomeIpSdEntry::setMinorVersion(uint32_t minorVersion) +{ + getSomeIpSdEntryHeader()->data = htobe32(minorVersion); +} + +uint8_t SomeIpSdEntry::getCounter() const +{ + return (uint8_t)((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F); +} + +void SomeIpSdEntry::setCounter(uint8_t counter) +{ + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + hdr->data = htobe32((be32toh(hdr->data) & 0xFFF0FFFF) | ((counter & 0x0F) << 16)); +} + +uint16_t SomeIpSdEntry::getEventgroupId() const +{ + return (uint16_t)(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF); +} + +void SomeIpSdEntry::setEventgroupId(uint16_t eventgroupID) +{ + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + hdr->data = htobe32((be32toh(hdr->data) & 0xFFFF0000) | eventgroupID); +} + +void SomeIpSdEntry::initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL) +{ + m_EntryType = type; + m_Layer = nullptr; + m_Offset = 0; + + size_t dataLen = sizeof(someipsdhdrentry); + m_ShadowData = new uint8_t[dataLen]; + memset(m_ShadowData, 0, dataLen); + + someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); + setServiceId(serviceID); + setInstanceId(instanceID); + setMajorVersion(majorVersion); + setTtl(TTL); + + switch (type) + { + case EntryType::FindService: + { + hdr->type = static_cast(TypeInternal::FindService_Internal); + break; + } + case EntryType::OfferService: + case EntryType::StopOfferService: + { + hdr->type = static_cast(TypeInternal::OfferService_Internal); + break; + } + case EntryType::SubscribeEventgroup: + case EntryType::StopSubscribeEventgroup: + { + hdr->type = static_cast(TypeInternal::SubscribeEventgroup_Internal); + break; + } + case EntryType::SubscribeEventgroupAck: + case EntryType::SubscribeEventgroupNack: + { + hdr->type = static_cast(TypeInternal::SubscribeEventgroupAck_Internal); + break; + } + default: + break; + } +} + +/* + * SomeIpSdLayer + */ +SomeIpSdLayer::SomeIpSdLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) + : SomeIpLayer(data, dataLen, prevLayer, packet) +{ + m_NumOptions = countOptions(); +} + +SomeIpSdLayer::SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags) +{ + m_Protocol = SomeIP; + m_DataLen = sizeof(someipsdhdr) + 2 * sizeof(uint32_t); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + + m_NumOptions = 0; + + setServiceID(serviceID); + setMethodID(methodID); + setPayloadLength(sizeof(uint32_t) * 3); // Flags+Reserved, Length Entries, Length Options + setClientID(clientID); + setSessionID(sessionID); + setProtocolVersion(0x01); + setInterfaceVersion(interfaceVersion); + setMessageType(type); + setReturnCode(returnCode); + setFlags(flags); +} + +uint8_t SomeIpSdLayer::getFlags() const +{ + someipsdhdr *hdr = (someipsdhdr *)m_Data; + return hdr->flags; +} + +void SomeIpSdLayer::setFlags(uint8_t flags) +{ + someipsdhdr *hdr = (someipsdhdr *)m_Data; + hdr->flags = flags; +} + +uint32_t SomeIpSdLayer::getNumEntries() const +{ + return (uint32_t)(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry)); +} + +uint32_t SomeIpSdLayer::getNumOptions() const +{ + return m_NumOptions; +} + +const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const +{ + size_t remainingLen = getLenEntries(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t); + + EntriesVec vecEntries; + EntryPtr entry; + + while (remainingLen > 0) + { + entry = new SomeIpSdEntry(this, offset); + + size_t entryLen = entry->getLength(); + remainingLen -= entryLen; + offset += entryLen; + + vecEntries.push_back(entry); + } + + return vecEntries; +}; + +const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const +{ + OptionsVec vecOptions; + OptionPtr option; + + size_t remainingLen = getLenOptions(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + + while (remainingLen > 0) + { + SomeIpSdOption::someipsdhdroptionsbase *hdr = (SomeIpSdOption::someipsdhdroptionsbase *)(m_Data + offset); + SomeIpSdOption::OptionType optionType = static_cast(hdr->type); + + option = parseOption(optionType, offset); + + if (option != nullptr) + { + vecOptions.push_back(std::move(option)); + } + + size_t optionLen = be16toh(hdr->length) + 3; + remainingLen -= optionLen; + offset += optionLen; + } + + return vecOptions; +} + +const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const +{ + OptionsVec vecOptions; + OptionPtr option; + + if (index >= getNumEntries()) + return vecOptions; + + size_t remainingLen = getLenOptions(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + + size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry); + SomeIpSdEntry::someipsdhdrentry *hdrEntry = (SomeIpSdEntry::someipsdhdrentry *)(m_Data + offsetToEntry); + uint8_t startIdxRun1 = hdrEntry->indexFirstOption; + uint8_t lenRun1 = hdrEntry->nrOpt1; + uint8_t startIdxRun2 = hdrEntry->indexSecondOption; + uint8_t lenRun2 = hdrEntry->nrOpt2; + + int idx = 0; + + while (remainingLen > 0) + { + SomeIpSdOption::someipsdhdroptionsbase *hdrOption = (SomeIpSdOption::someipsdhdroptionsbase *)(m_Data + offset); + + if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) || + ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2)))) + { + SomeIpSdOption::OptionType optionType = static_cast(hdrOption->type); + + option = parseOption(optionType, offset); + + if (option != nullptr) + { + vecOptions.push_back(std::move(option)); + } + } + + size_t optionLen = be16toh(hdrOption->length) + 3; + remainingLen -= optionLen; + offset += optionLen; + ++idx; + } + + return vecOptions; +} + +bool SomeIpSdLayer::addOptionTo(uint32_t indexEntry, const SomeIpSdOption &option) +{ + if (indexEntry >= getNumEntries()) + { + return false; + } + + uint32_t indexOption = findOption(option); + bool success = addOptionIndex(indexEntry, indexOption); + + if (!success) + { + return false; + } + + if (indexOption == m_NumOptions) + { + addOption(option); + } + + return true; +} + +std::string SomeIpSdLayer::toString() const +{ + std::stringstream dataStream; + + dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options"; + + return dataStream.str(); +} + +uint32_t SomeIpSdLayer::addEntry(const SomeIpSdEntry &entry) +{ + size_t lenEntries = getLenEntries(); + int offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + lenEntries; + + extendLayer(offsetToAddAt, entry.getLength()); + + setLenEntries(lenEntries + entry.getLength()); + + memcpy(m_Data + offsetToAddAt, entry.getDataPtr(), entry.getLength()); + + auto hdr = getSomeIpHeader(); + hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)entry.getLength()); + + return getNumEntries() - 1; +} + +uint32_t SomeIpSdLayer::countOptions() +{ + size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + size_t lenOptions = getLenOptions(); + uint32_t len = 0; + + uint32_t numOptions = 0; + while (len < lenOptions) + { + uint32_t lenOption = be16toh(*((uint16_t *)(m_Data + offsetOption + len))) + 3 * sizeof(uint8_t); + len += lenOption; + ++numOptions; + } + return numOptions; +} + +uint32_t SomeIpSdLayer::findOption(const SomeIpSdOption &option) +{ + size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + + uint32_t i = 0; + while (i < m_NumOptions) + { + uint32_t lenOption = be16toh(*((uint16_t *)(m_Data + offsetOption))) + 3 * sizeof(uint8_t); + + if (option.getLength() == lenOption) + { + if (memcmp(m_Data + offsetOption, option.getDataPtr(), option.getLength()) == 0) + { + return i; + } + } + + offsetOption += lenOption; + ++i; + } + return i; +} + +void SomeIpSdLayer::addOption(const SomeIpSdOption &option) +{ + int offsetToAddAt = (int)getHeaderLen(); + + extendLayer(offsetToAddAt, option.getLength()); + memcpy(m_Data + offsetToAddAt, option.getDataPtr(), option.getLength()); + + setLenOptions(uint32_t(getLenOptions() + option.getLength())); + + auto hdr = getSomeIpHeader(); + hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)option.getLength()); + + ++m_NumOptions; +} + +bool SomeIpSdLayer::addOptionIndex(uint32_t indexEntry, uint32_t indexOffset) +{ + /* The SOME/IP-SD protocol supports two option runs. Runs meaning that two different starting indices with differing + length can be provided. Of course, this only works if the indices in both runs are consecutive. + + So, indices like this would work: + 1 2 3 ; 7 8 + + What wouldn't work is this: + 1 2 3 ; 7 9 + 1 3 ; 7 8 + */ + + size_t offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + indexEntry*sizeof(SomeIpSdEntry::someipsdhdrentry); + auto hdrEntry = (SomeIpSdEntry::someipsdhdrentry *)(m_Data + offsetToAddAt); + + uint8_t indexFirstOption = hdrEntry->indexFirstOption; + uint8_t lenFirstOption = hdrEntry->nrOpt1; + + if (lenFirstOption == 0) + { + hdrEntry->indexFirstOption = indexOffset; + ++hdrEntry->nrOpt1; + return true; + } + + if (indexFirstOption + lenFirstOption + 1 == indexOffset) + { + ++hdrEntry->nrOpt1; + return true; + } + + uint8_t indexSecondOption = hdrEntry->indexSecondOption; + uint8_t lenSecondOption = hdrEntry->nrOpt2; + + if (lenSecondOption == 0) + { + hdrEntry->indexFirstOption = indexOffset; + ++hdrEntry->nrOpt1; + return true; + } + + if (indexSecondOption + lenSecondOption + 1 == indexOffset) + { + ++hdrEntry->nrOpt2; + return true; + } + + return false; +} + +SomeIpSdLayer::OptionPtr SomeIpSdLayer::parseOption(SomeIpSdOption::OptionType type, size_t offset) const +{ + switch (type) + { + case SomeIpSdOption::OptionType::IPv4Endpoint: + case SomeIpSdOption::OptionType::IPv4Multicast: + case SomeIpSdOption::OptionType::IPv4SdEndpoint: + { + return new SomeIpSdIPv4Option(this, offset); + } + case SomeIpSdOption::OptionType::IPv6Endpoint: + case SomeIpSdOption::OptionType::IPv6Multicast: + case SomeIpSdOption::OptionType::IPv6SdEndpoint: + { + return new SomeIpSdIPv6Option(this, offset); + } + case SomeIpSdOption::OptionType::ConfigurationString: + { + return new SomeIpSdConfigurationOption(this, offset); + } + case SomeIpSdOption::OptionType::LoadBalancing: + { + return new SomeIpSdLoadBalancingOption(this, offset); + } + default: + break; + } + return nullptr; +} + +size_t SomeIpSdLayer::getLenEntries() const +{ + return be32toh(*((uint32_t *)(m_Data + sizeof(someipsdhdr)))); +} + +size_t SomeIpSdLayer::getLenOptions() const +{ + return be32toh(*((uint32_t *)(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries()))); +} + +void SomeIpSdLayer::setLenEntries(uint32_t length) +{ + *((uint32_t *)(m_Data + sizeof(someipsdhdr))) = htobe32(length); +} + +void SomeIpSdLayer::setLenOptions(uint32_t length) +{ + *((uint32_t *)(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries())) = htobe32(length); +} + +} // namespace pcpp diff --git a/Tests/Packet++Test/PacketExamples/SomeIpSd.pcapng b/Tests/Packet++Test/PacketExamples/SomeIpSd.pcapng new file mode 100644 index 0000000000..6184330f06 Binary files /dev/null and b/Tests/Packet++Test/PacketExamples/SomeIpSd.pcapng differ diff --git a/Tests/Packet++Test/PacketExamples/SomeIpSdOffer.dat b/Tests/Packet++Test/PacketExamples/SomeIpSdOffer.dat new file mode 100644 index 0000000000..73c8b7e967 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/SomeIpSdOffer.dat @@ -0,0 +1 @@ +01005e40fffb0054afe9d1c08100004908004500005400004000ff11248fa030c71cefc0fffb771a771a0040c0dcffff8100000000300000000201010200c00000000000001001000010d05f000201000003000000000000000c00090400a030c71c00117726 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/SomeIpSdOffer2.dat b/Tests/Packet++Test/PacketExamples/SomeIpSdOffer2.dat new file mode 100644 index 0000000000..760f4aac00 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/SomeIpSdOffer2.dat @@ -0,0 +1 @@ +333300040000027dfa0010018100000286dd6000000000a911fefd537cb80383000400000000000101e5ff140000000000000000000000040000771a771a00a9f0a8ffff8100000000990000000201010200e00000000000001001000020fffe000105000078000000000000007500150600fd537cb80383000400000000000101e500067449005a01001063617465676f72793d627269646765640c6c3670726f746f3d76697769216f74686572736572763d4164617074697665437275697365417373697374484d4909747874766572733d310d76657273696f6e3d352e302e3000 \ No newline at end of file diff --git a/Tests/Packet++Test/PacketExamples/SomeIpSdSubscribe.dat b/Tests/Packet++Test/PacketExamples/SomeIpSdSubscribe.dat new file mode 100644 index 0000000000..3fb3576980 --- /dev/null +++ b/Tests/Packet++Test/PacketExamples/SomeIpSdSubscribe.dat @@ -0,0 +1 @@ +0054afe9d1c20284cf3bbe0081000049080045000064ed3500004011be57a030c765a030c735771a771a0050ff0fffff8100000000400000000301010200c00000000000002006000010d0630001010000030000000106000010d066000101000003000000010000000c00090400a030c7650011e3f6 \ No newline at end of file diff --git a/Tests/Packet++Test/TestDefinition.h b/Tests/Packet++Test/TestDefinition.h index 901f58a64f..2a1bb53b1f 100644 --- a/Tests/Packet++Test/TestDefinition.h +++ b/Tests/Packet++Test/TestDefinition.h @@ -201,6 +201,10 @@ PTF_TEST_CASE(SomeIpTpParsingTest); PTF_TEST_CASE(SomeIpTpCreationTest); PTF_TEST_CASE(SomeIpTpEditTest); +// Implemented in SomeIpSdTests.cpp +PTF_TEST_CASE(SomeIpSdParsingTest); +PTF_TEST_CASE(SomeIpSdCreationTest); + // Implemented in WakeOnLanTests.cpp PTF_TEST_CASE(WakeOnLanParsingTests); PTF_TEST_CASE(WakeOnLanCreationTests); diff --git a/Tests/Packet++Test/Tests/SomeIpSdTests.cpp b/Tests/Packet++Test/Tests/SomeIpSdTests.cpp new file mode 100644 index 0000000000..f953ea0c2c --- /dev/null +++ b/Tests/Packet++Test/Tests/SomeIpSdTests.cpp @@ -0,0 +1,262 @@ +#include "../TestDefinition.h" +#include "../Utils/TestUtils.h" +#include +#include "EndianPortable.h" +#include "Logger.h" +#include "Packet.h" +#include "SomeIpSdLayer.h" +#include "SystemUtils.h" + +PTF_TEST_CASE(SomeIpSdParsingTest) +{ + timeval time; + gettimeofday(&time, NULL); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/SomeIpSdOffer.dat"); + READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/SomeIpSdOffer2.dat"); + READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/SomeIpSdSubscribe.dat"); + + pcpp::Packet someIpSdPacket(&rawPacket1); + pcpp::Packet someIpSdPacket2(&rawPacket2); + pcpp::Packet someIpSdPacket3(&rawPacket3); + + // OfferService (Entry: OfferService, Option: IPv4Endpoint) + PTF_ASSERT_TRUE(someIpSdPacket.isPacketOfType(pcpp::SomeIP)); + pcpp::SomeIpSdLayer* someIpSdLayer = someIpSdPacket.getLayerOfType(); + PTF_ASSERT_NOT_NULL(someIpSdLayer); + PTF_ASSERT_EQUAL(someIpSdLayer->getHeaderLen(), 56); + PTF_ASSERT_EQUAL(someIpSdLayer->getMessageID(), 0xffff8100); + PTF_ASSERT_EQUAL(someIpSdLayer->getServiceID(), 0xffff); + PTF_ASSERT_EQUAL(someIpSdLayer->getMethodID(), 0x8100); + PTF_ASSERT_EQUAL(someIpSdLayer->getLengthField(), 48); + PTF_ASSERT_EQUAL(someIpSdLayer->getRequestID(), 0x00000002); + PTF_ASSERT_EQUAL(someIpSdLayer->getClientID(), 0x0); + PTF_ASSERT_EQUAL(someIpSdLayer->getSessionID(), 0x2); + PTF_ASSERT_EQUAL(someIpSdLayer->getProtocolVersion(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer->getInterfaceVersion(), 1); + PTF_ASSERT_EQUAL((int)someIpSdLayer->getMessageType(), (int)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer->getMessageTypeAsInt(), (uint8_t)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer->getReturnCode(), 0); + PTF_ASSERT_EQUAL(someIpSdLayer->getNumEntries(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer->getNumOptions(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer->toString(), "SOME/IP-SD Layer, 1 entries, 1 options"); + + pcpp::SomeIpSdLayer::EntriesVec entries1 = someIpSdLayer->getEntries(); + PTF_ASSERT_EQUAL(entries1.size(), 1); + pcpp::SomeIpSdEntry* entry = *(entries1.begin()); + + PTF_ASSERT_EQUAL(entry->getLength(), 16); + PTF_ASSERT_EQUAL(entry->getNumOptions(), 1); + PTF_ASSERT_EQUAL((uint8_t)entry->getType(), (uint8_t)pcpp::SomeIpSdEntry::EntryType::OfferService); + PTF_ASSERT_EQUAL(entry->getServiceId(), 0xd05f); + PTF_ASSERT_EQUAL(entry->getInstanceId(), 0x0002); + PTF_ASSERT_EQUAL(entry->getMajorVersion(), 1); + PTF_ASSERT_EQUAL(entry->getTtl(), 3); + PTF_ASSERT_EQUAL(entry->getMinorVersion(), 0); + PTF_ASSERT_EQUAL(entry->getDataPtr()[0], 0x01); + + pcpp::SomeIpSdLayer::OptionsVec options = someIpSdLayer->getOptions(); + PTF_ASSERT_EQUAL(options.size(), 1); + pcpp::SomeIpSdOption* option = *(options.begin()); + PTF_ASSERT_EQUAL(option->getLength(), 12); + PTF_ASSERT_EQUAL((uint8_t)option->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv4Endpoint); + PTF_ASSERT_EQUAL(option->getDataPtr()[1], 0x09); + + pcpp::SomeIpSdIPv4Option* ipv4Option = (pcpp::SomeIpSdIPv4Option*) option; + PTF_ASSERT_EQUAL(ipv4Option->getIpAddress(), pcpp::IPv4Address("160.48.199.28")); + PTF_ASSERT_EQUAL(ipv4Option->getProtocol(), pcpp::SomeIpSdProtocolType::SD_UDP); + PTF_ASSERT_EQUAL(ipv4Option->getPort(), 30502); + + // OfferService (Entry: OfferService, Option: IPv6Endpoint, ConfigurationString) + PTF_ASSERT_TRUE(someIpSdPacket2.isPacketOfType(pcpp::SomeIP)); + pcpp::SomeIpSdLayer* someIpSdLayer2 = someIpSdPacket2.getLayerOfType(); + PTF_ASSERT_NOT_NULL(someIpSdLayer2); + PTF_ASSERT_EQUAL(someIpSdLayer2->getHeaderLen(), 161); + PTF_ASSERT_EQUAL(someIpSdLayer2->getMessageID(), 0xffff8100); + PTF_ASSERT_EQUAL(someIpSdLayer2->getServiceID(), 0xffff); + PTF_ASSERT_EQUAL(someIpSdLayer2->getMethodID(), 0x8100); + PTF_ASSERT_EQUAL(someIpSdLayer2->getLengthField(), 153); + PTF_ASSERT_EQUAL(someIpSdLayer2->getRequestID(), 0x00000002); + PTF_ASSERT_EQUAL(someIpSdLayer2->getClientID(), 0x0); + PTF_ASSERT_EQUAL(someIpSdLayer2->getSessionID(), 0x2); + PTF_ASSERT_EQUAL(someIpSdLayer2->getProtocolVersion(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer2->getInterfaceVersion(), 1); + PTF_ASSERT_EQUAL((int)someIpSdLayer2->getMessageType(), (int)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer2->getMessageTypeAsInt(), (uint8_t)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer2->getReturnCode(), 0); + PTF_ASSERT_EQUAL(someIpSdLayer2->getNumEntries(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer2->getNumOptions(), 2); + PTF_ASSERT_EQUAL(someIpSdLayer2->toString(), "SOME/IP-SD Layer, 1 entries, 2 options"); + + pcpp::SomeIpSdLayer::EntriesVec entries2 = someIpSdLayer2->getEntries(); + PTF_ASSERT_EQUAL(entries2.size(), 1); + + pcpp::SomeIpSdEntry* entry2 = *(entries2.begin()); + PTF_ASSERT_EQUAL(entry2->getLength(), 16); + PTF_ASSERT_EQUAL(entry2->getNumOptions(), 2); + PTF_ASSERT_EQUAL((uint8_t)entry2->getType(), (uint8_t)pcpp::SomeIpSdEntry::EntryType::OfferService); + PTF_ASSERT_EQUAL(entry2->getServiceId(), 0xfffe); + PTF_ASSERT_EQUAL(entry2->getInstanceId(), 0x0001); + PTF_ASSERT_EQUAL(entry2->getMajorVersion(), 5); + PTF_ASSERT_EQUAL(entry2->getTtl(), 120); + PTF_ASSERT_EQUAL(entry2->getMinorVersion(), 0); + PTF_ASSERT_EQUAL(entry2->getDataPtr()[0], 0x01); + + pcpp::SomeIpSdLayer::OptionsVec options2 = someIpSdLayer2->getOptions(); + PTF_ASSERT_EQUAL(options2.size(), 2); + + pcpp::SomeIpSdOption* option2_1 = *(options2.begin()); + PTF_ASSERT_EQUAL(option2_1->getLength(), 24); + PTF_ASSERT_EQUAL((uint8_t)option2_1->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv6Endpoint); + PTF_ASSERT_EQUAL(option2_1->getDataPtr()[1], 0x15); + + pcpp::SomeIpSdIPv6Option* ipv6Option2_1 = (pcpp::SomeIpSdIPv6Option*) option2_1; + PTF_ASSERT_EQUAL(ipv6Option2_1->getIpAddress(), pcpp::IPv6Address("fd53:7cb8:383:4::1:1e5")); + PTF_ASSERT_EQUAL(ipv6Option2_1->getProtocol(), pcpp::SomeIpSdProtocolType::SD_TCP); + PTF_ASSERT_EQUAL(ipv6Option2_1->getPort(), 29769); + + pcpp::SomeIpSdOption* option2_2 = *(options2.begin()+1); + PTF_ASSERT_EQUAL(option2_2->getLength(), 93); + PTF_ASSERT_EQUAL((uint8_t)option2_2->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::ConfigurationString); + PTF_ASSERT_EQUAL(option2_2->getDataPtr()[5], 0x63); + + pcpp::SomeIpSdConfigurationOption* configurationOption = (pcpp::SomeIpSdConfigurationOption*) option2_2; + for(int i = 0; i < 89; i++){ + PTF_ASSERT_EQUAL(configurationOption->getConfigurationString()[i], someIpSdPacket2.getRawPacket()->getRawData()[138+i]); + } + + pcpp::SomeIpSdLayer::OptionsVec options2Entry0 = someIpSdLayer2->getOptionsFromEntry(0); + PTF_ASSERT_EQUAL(options2Entry0.size(), 2); + + pcpp::SomeIpSdOption* options2Entry0_1 = *(options2Entry0.begin()); + PTF_ASSERT_EQUAL(options2Entry0_1->getLength(), 24); + PTF_ASSERT_EQUAL((uint8_t)options2Entry0_1->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv6Endpoint); + PTF_ASSERT_EQUAL(options2Entry0_1->getDataPtr()[1], 0x15); + + pcpp::SomeIpSdOption* options2Entry0_2 = *(options2Entry0.begin()+1); + PTF_ASSERT_EQUAL(options2Entry0_2->getLength(), 93); + PTF_ASSERT_EQUAL((uint8_t)options2Entry0_2->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::ConfigurationString); + PTF_ASSERT_EQUAL(options2Entry0_2->getDataPtr()[5], 0x63); + + pcpp::SomeIpSdLayer::OptionsVec options2Entry1 = someIpSdLayer2->getOptionsFromEntry(1); + PTF_ASSERT_EQUAL(options2Entry1.size(), 0); + + // Subscribe (Entry: 2xSubscribeEventgroup, Option: IPv4Endpoint) + PTF_ASSERT_TRUE(someIpSdPacket3.isPacketOfType(pcpp::SomeIP)); + pcpp::SomeIpSdLayer* someIpSdLayer3 = someIpSdPacket3.getLayerOfType(); + PTF_ASSERT_NOT_NULL(someIpSdLayer3); + PTF_ASSERT_EQUAL(someIpSdLayer3->getHeaderLen(), 72); + PTF_ASSERT_EQUAL(someIpSdLayer3->getMessageID(), 0xffff8100); + PTF_ASSERT_EQUAL(someIpSdLayer3->getServiceID(), 0xffff); + PTF_ASSERT_EQUAL(someIpSdLayer3->getMethodID(), 0x8100); + PTF_ASSERT_EQUAL(someIpSdLayer3->getLengthField(), 64); + PTF_ASSERT_EQUAL(someIpSdLayer3->getRequestID(), 0x00000003); + PTF_ASSERT_EQUAL(someIpSdLayer3->getClientID(), 0x0); + PTF_ASSERT_EQUAL(someIpSdLayer3->getSessionID(), 0x3); + PTF_ASSERT_EQUAL(someIpSdLayer3->getProtocolVersion(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer3->getInterfaceVersion(), 1); + PTF_ASSERT_EQUAL((int)someIpSdLayer3->getMessageType(), (int)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer3->getMessageTypeAsInt(), (uint8_t)pcpp::SomeIpLayer::MsgType::NOTIFICATION); + PTF_ASSERT_EQUAL(someIpSdLayer3->getReturnCode(), 0); + PTF_ASSERT_EQUAL(someIpSdLayer3->getNumEntries(), 2); + PTF_ASSERT_EQUAL(someIpSdLayer3->getNumOptions(), 1); + PTF_ASSERT_EQUAL(someIpSdLayer3->toString(), "SOME/IP-SD Layer, 2 entries, 1 options"); + + pcpp::SomeIpSdLayer::EntriesVec entries3 = someIpSdLayer3->getEntries(); + PTF_ASSERT_EQUAL(entries3.size(), 2); + + pcpp::SomeIpSdEntry* entry3_1 = *(entries3.begin()); + PTF_ASSERT_EQUAL(entry3_1->getLength(), 16); + PTF_ASSERT_EQUAL(entry3_1->getNumOptions(), 1); + PTF_ASSERT_EQUAL((uint8_t)entry3_1->getType(), (uint8_t)pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup); + PTF_ASSERT_EQUAL(entry3_1->getServiceId(), 0xd063); + PTF_ASSERT_EQUAL(entry3_1->getInstanceId(), 0x0001); + PTF_ASSERT_EQUAL(entry3_1->getMajorVersion(), 1); + PTF_ASSERT_EQUAL(entry3_1->getTtl(), 3); + PTF_ASSERT_EQUAL(entry3_1->getCounter(), 0); + PTF_ASSERT_EQUAL(entry3_1->getEventgroupId(), 1); + PTF_ASSERT_EQUAL(entry3_1->getDataPtr()[0], 0x06); + + pcpp::SomeIpSdEntry* entry3_2 = *(entries3.begin()+1); + PTF_ASSERT_EQUAL(entry3_2->getLength(), 16); + PTF_ASSERT_EQUAL(entry3_2->getNumOptions(), 1); + PTF_ASSERT_EQUAL((uint8_t)entry3_2->getType(), (uint8_t)pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup); + PTF_ASSERT_EQUAL(entry3_2->getServiceId(), 0xd066); + PTF_ASSERT_EQUAL(entry3_2->getInstanceId(), 0x0001); + PTF_ASSERT_EQUAL(entry3_2->getMajorVersion(), 1); + PTF_ASSERT_EQUAL(entry3_2->getTtl(), 3); + PTF_ASSERT_EQUAL(entry3_2->getCounter(), 0); + PTF_ASSERT_EQUAL(entry3_2->getEventgroupId(), 1); + PTF_ASSERT_EQUAL(entry3_2->getDataPtr()[0], 0x06); + + pcpp::SomeIpSdLayer::OptionsVec options3 = someIpSdLayer3->getOptions(); + PTF_ASSERT_EQUAL(options3.size(), 1); + + pcpp::SomeIpSdOption* option3 = *(options3.begin()); + PTF_ASSERT_EQUAL(option3->getLength(), 12); + PTF_ASSERT_EQUAL((uint8_t)option3->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv4Endpoint); + PTF_ASSERT_EQUAL(option3->getDataPtr()[1], 0x09); + + delete entry; + delete option; + entries1.clear(); + options.clear(); + + delete entry2; + delete option2_1; + delete option2_2; + delete options2Entry0_1; + delete options2Entry0_2; + entries2.clear(); + options2.clear(); + options2Entry0.clear(); + + delete entry3_1; + delete entry3_2; + delete option3; + entries3.clear(); + options3.clear(); +} + +PTF_TEST_CASE(SomeIpSdCreationTest) +{ + timeval time; + gettimeofday(&time, NULL); + + READ_FILE_INTO_BUFFER(1, "PacketExamples/SomeIpSdOffer.dat"); + READ_FILE_INTO_BUFFER(2, "PacketExamples/SomeIpSdSubscribe.dat"); + + // OfferService (Entry: OfferService, Option: IPv4Endpoint) + pcpp::SomeIpSdLayer someIpSdLayer(0xffff, 0x8100, 0, 0x2, 0x1, pcpp::SomeIpLayer::MsgType::NOTIFICATION, 0, 0xc0); + auto pEntry = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::OfferService, 0xd05f, 2, 1, 3, 0)); + auto pOption = std::unique_ptr(new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, pcpp::IPv4Address("160.48.199.28"), 30502, pcpp::SomeIpSdProtocolType::SD_UDP)); + auto offsetEntry = someIpSdLayer.addEntry(*pEntry); + someIpSdLayer.addOptionTo(offsetEntry, *pOption); + + pcpp::Packet someIpSdPacket(100); + PTF_ASSERT_TRUE(someIpSdPacket.addLayer(&someIpSdLayer)); + someIpSdPacket.computeCalculateFields(); + + PTF_ASSERT_EQUAL(someIpSdPacket.getRawPacket()->getRawDataLen(), bufferLength1-46); + PTF_ASSERT_BUF_COMPARE(someIpSdPacket.getRawPacket()->getRawData(), buffer1+46, bufferLength1-46); + + // Subscribe (Entry: 2xSubscribeEventgroup, Option: IPv4Endpoint) + pcpp::SomeIpSdLayer someIpSdLayer2(0xffff, 0x8100, 0, 0x3, 0x1, pcpp::SomeIpLayer::MsgType::NOTIFICATION, 0, 0xc0); + auto pEntry2_1 = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd063, 1, 1, 3, 0, 1)); + auto pEntry2_2 = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd066, 1, 1, 3, 0, 1)); + auto pOption2 = std::unique_ptr(new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, pcpp::IPv4Address("160.48.199.101"), 58358, pcpp::SomeIpSdProtocolType::SD_UDP)); + auto offsetEntry2_1 = someIpSdLayer2.addEntry(*pEntry2_1); + someIpSdLayer2.addOptionTo(offsetEntry2_1, *pOption2); + auto offsetEntry2_2 = someIpSdLayer2.addEntry(*pEntry2_2); + someIpSdLayer2.addOptionTo(offsetEntry2_2, *pOption2); + + pcpp::Packet someIpSdPacket2(100); + PTF_ASSERT_TRUE(someIpSdPacket2.addLayer(&someIpSdLayer2)); + someIpSdPacket2.computeCalculateFields(); + + PTF_ASSERT_EQUAL(someIpSdPacket2.getRawPacket()->getRawDataLen(), bufferLength2-46); + PTF_ASSERT_BUF_COMPARE(someIpSdPacket2.getRawPacket()->getRawData(), buffer2+46, bufferLength2-46); + + delete [] buffer1; + delete [] buffer2; +} diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 6b166a63c7..5ab57c7223 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -278,6 +278,9 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(SomeIpTpCreationTest, "someip"); PTF_RUN_TEST(SomeIpTpEditTest, "someip"); + PTF_RUN_TEST(SomeIpSdParsingTest, "someipsd"); + PTF_RUN_TEST(SomeIpSdCreationTest, "someipsd"); + PTF_RUN_TEST(WakeOnLanParsingTests, "wol"); PTF_RUN_TEST(WakeOnLanCreationTests, "wol"); PTF_RUN_TEST(WakeOnLanEditTests, "wol"); diff --git a/mk/vs/Packet++.vcxproj.filters b/mk/vs/Packet++.vcxproj.filters index cefe4058b4..3da8bca9b9 100644 --- a/mk/vs/Packet++.vcxproj.filters +++ b/mk/vs/Packet++.vcxproj.filters @@ -144,6 +144,9 @@ Header Files + + Header Files + Header Files @@ -293,6 +296,9 @@ Source Files + + Source Files + Source Files diff --git a/mk/vs/Packet++.vcxproj.template b/mk/vs/Packet++.vcxproj.template index 57ddc16679..112720d527 100644 --- a/mk/vs/Packet++.vcxproj.template +++ b/mk/vs/Packet++.vcxproj.template @@ -222,6 +222,7 @@ xcopy "$(PcapPlusPlusHome)\Packet++\header\*" "$(PcapPlusPlusHome)\Dist\header" + @@ -277,6 +278,7 @@ xcopy "$(PcapPlusPlusHome)\Packet++\header\*" "$(PcapPlusPlusHome)\Dist\header" + diff --git a/mk/vs/Packet++Test.vcxproj.filters b/mk/vs/Packet++Test.vcxproj.filters index 268807fc51..290eceef9a 100644 --- a/mk/vs/Packet++Test.vcxproj.filters +++ b/mk/vs/Packet++Test.vcxproj.filters @@ -98,6 +98,9 @@ Source Files\Tests + + Source Files\Tests + Source Files\Tests diff --git a/mk/vs/Packet++Test.vcxproj.template b/mk/vs/Packet++Test.vcxproj.template index 54ecefcab0..35b1b0fcf8 100644 --- a/mk/vs/Packet++Test.vcxproj.template +++ b/mk/vs/Packet++Test.vcxproj.template @@ -193,6 +193,7 @@ +