From 71754092fd8d2309c9350eef7c318261fb35f9f5 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Wed, 21 May 2025 21:29:48 +0300 Subject: [PATCH 01/52] Added initial framework for Parser configuration. --- Packet++/CMakeLists.txt | 1 + Packet++/header/ArpLayer.h | 2 +- Packet++/header/BgpLayer.h | 2 +- Packet++/header/CiscoHdlcLayer.h | 2 +- Packet++/header/CotpLayer.h | 2 +- Packet++/header/DhcpLayer.h | 2 +- Packet++/header/DhcpV6Layer.h | 2 +- Packet++/header/DnsLayer.h | 2 +- Packet++/header/EthDot3Layer.h | 2 +- Packet++/header/EthLayer.h | 2 +- Packet++/header/FtpLayer.h | 2 +- Packet++/header/GreLayer.h | 4 +- Packet++/header/GtpLayer.h | 4 +- Packet++/header/IPSecLayer.h | 4 +- Packet++/header/IPv4Layer.h | 2 +- Packet++/header/IPv6Layer.h | 2 +- Packet++/header/IcmpLayer.h | 2 +- Packet++/header/IcmpV6Layer.h | 2 +- Packet++/header/IgmpLayer.h | 2 +- Packet++/header/LLCLayer.h | 2 +- Packet++/header/Layer.h | 8 ++- Packet++/header/LdapLayer.h | 2 +- Packet++/header/MplsLayer.h | 2 +- Packet++/header/NflogLayer.h | 2 +- Packet++/header/NtpLayer.h | 2 +- Packet++/header/NullLoopbackLayer.h | 2 +- Packet++/header/PPPoELayer.h | 4 +- Packet++/header/PacketTrailerLayer.h | 2 +- Packet++/header/ParserConfig.h | 95 ++++++++++++++++++++++++++++ Packet++/header/PayloadLayer.h | 2 +- Packet++/header/RadiusLayer.h | 2 +- Packet++/header/S7CommLayer.h | 2 +- Packet++/header/SSHLayer.h | 2 +- Packet++/header/SSLLayer.h | 2 +- Packet++/header/SipLayer.h | 2 +- Packet++/header/Sll2Layer.h | 2 +- Packet++/header/SllLayer.h | 2 +- Packet++/header/SmtpLayer.h | 2 +- Packet++/header/SomeIpLayer.h | 2 +- Packet++/header/StpLayer.h | 8 +-- Packet++/header/TcpLayer.h | 2 +- Packet++/header/TelnetLayer.h | 2 +- Packet++/header/TextBasedProtocol.h | 2 +- Packet++/header/TpktLayer.h | 2 +- Packet++/header/UdpLayer.h | 2 +- Packet++/header/VlanLayer.h | 2 +- Packet++/header/VrrpLayer.h | 2 +- Packet++/header/VxlanLayer.h | 2 +- Packet++/header/WakeOnLanLayer.h | 2 +- Packet++/header/WireGuardLayer.h | 2 +- Packet++/src/BgpLayer.cpp | 2 +- Packet++/src/CiscoHdlcLayer.cpp | 2 +- Packet++/src/CotpLayer.cpp | 2 +- Packet++/src/EthDot3Layer.cpp | 2 +- Packet++/src/EthLayer.cpp | 2 +- Packet++/src/GreLayer.cpp | 4 +- Packet++/src/GtpLayer.cpp | 4 +- Packet++/src/IPSecLayer.cpp | 4 +- Packet++/src/IPv4Layer.cpp | 2 +- Packet++/src/IPv6Layer.cpp | 2 +- Packet++/src/IcmpLayer.cpp | 2 +- Packet++/src/LLCLayer.cpp | 2 +- Packet++/src/LdapLayer.cpp | 2 +- Packet++/src/MplsLayer.cpp | 2 +- Packet++/src/NflogLayer.cpp | 2 +- Packet++/src/NullLoopbackLayer.cpp | 2 +- Packet++/src/PPPoELayer.cpp | 2 +- Packet++/src/SSHLayer.cpp | 2 +- Packet++/src/SSLLayer.cpp | 2 +- Packet++/src/SipLayer.cpp | 2 +- Packet++/src/Sll2Layer.cpp | 2 +- Packet++/src/SllLayer.cpp | 2 +- Packet++/src/SomeIpLayer.cpp | 2 +- Packet++/src/StpLayer.cpp | 6 +- Packet++/src/TcpLayer.cpp | 2 +- Packet++/src/TextBasedProtocol.cpp | 2 +- Packet++/src/TpktLayer.cpp | 2 +- Packet++/src/UdpLayer.cpp | 2 +- Packet++/src/VlanLayer.cpp | 2 +- Packet++/src/VxlanLayer.cpp | 2 +- 80 files changed, 192 insertions(+), 90 deletions(-) create mode 100644 Packet++/header/ParserConfig.h diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index b6e25bab0f..46acad3927 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -109,6 +109,7 @@ set( header/Packet.h header/PacketTrailerLayer.h header/PacketUtils.h + header/ParserConfig.h header/PayloadLayer.h header/PPPoELayer.h header/ProtocolType.h diff --git a/Packet++/header/ArpLayer.h b/Packet++/header/ArpLayer.h index 6402a5b753..f177fb3aaa 100644 --- a/Packet++/header/ArpLayer.h +++ b/Packet++/header/ArpLayer.h @@ -239,7 +239,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (ArpLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The size of @ref arphdr diff --git a/Packet++/header/BgpLayer.h b/Packet++/header/BgpLayer.h index 00ced23bfe..c989e91cc9 100644 --- a/Packet++/header/BgpLayer.h +++ b/Packet++/header/BgpLayer.h @@ -84,7 +84,7 @@ namespace pcpp /// Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message /// is another BGP message. This method checks for remaining data and parses it as another BGP layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; std::string toString() const override; diff --git a/Packet++/header/CiscoHdlcLayer.h b/Packet++/header/CiscoHdlcLayer.h index fe444bdf73..24a70d79f6 100644 --- a/Packet++/header/CiscoHdlcLayer.h +++ b/Packet++/header/CiscoHdlcLayer.h @@ -73,7 +73,7 @@ namespace pcpp void computeCalculateFields() override; /// Parses the next layer. Currently, supports IPv4 and IPv6 - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; std::string toString() const override; diff --git a/Packet++/header/CotpLayer.h b/Packet++/header/CotpLayer.h index bbd2ec5f18..1cf027271e 100644 --- a/Packet++/header/CotpLayer.h +++ b/Packet++/header/CotpLayer.h @@ -76,7 +76,7 @@ namespace pcpp {} /// Currently parses the rest of the packet as a S7COMM or generic payload (PayloadLayer) - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// A static method that takes a byte array and detects whether it is a COTP /// @param[in] data A byte array diff --git a/Packet++/header/DhcpLayer.h b/Packet++/header/DhcpLayer.h index 34daea5b8c..c3ae79bcec 100644 --- a/Packet++/header/DhcpLayer.h +++ b/Packet++/header/DhcpLayer.h @@ -733,7 +733,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (DhcpLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The size of @ref dhcp_header + size of options diff --git a/Packet++/header/DhcpV6Layer.h b/Packet++/header/DhcpV6Layer.h index 019274d550..d954a09732 100644 --- a/Packet++/header/DhcpV6Layer.h +++ b/Packet++/header/DhcpV6Layer.h @@ -349,7 +349,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (DhcpV6Layer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The size of @ref dhcpv6_header + size of options diff --git a/Packet++/header/DnsLayer.h b/Packet++/header/DnsLayer.h index c79f269e27..04c20f5eaf 100644 --- a/Packet++/header/DnsLayer.h +++ b/Packet++/header/DnsLayer.h @@ -350,7 +350,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (DnsLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The size of the DNS data in the packet including he DNS header and size of all queries, answers, diff --git a/Packet++/header/EthDot3Layer.h b/Packet++/header/EthDot3Layer.h index c725cd86f4..74e271af0a 100644 --- a/Packet++/header/EthDot3Layer.h +++ b/Packet++/header/EthDot3Layer.h @@ -94,7 +94,7 @@ namespace pcpp // implement abstract methods /// Parses next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of ether_dot3_header size_t getHeaderLen() const override diff --git a/Packet++/header/EthLayer.h b/Packet++/header/EthLayer.h index 750dbfe691..7302b0b333 100644 --- a/Packet++/header/EthLayer.h +++ b/Packet++/header/EthLayer.h @@ -132,7 +132,7 @@ namespace pcpp /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of ether_header size_t getHeaderLen() const override diff --git a/Packet++/header/FtpLayer.h b/Packet++/header/FtpLayer.h index 63cd6565b4..483fff76de 100644 --- a/Packet++/header/FtpLayer.h +++ b/Packet++/header/FtpLayer.h @@ -36,7 +36,7 @@ namespace pcpp // overridden methods /// FTP is the always last so does nothing for this layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Get the size of the layer diff --git a/Packet++/header/GreLayer.h b/Packet++/header/GreLayer.h index 38c25d64a6..24768adf1d 100644 --- a/Packet++/header/GreLayer.h +++ b/Packet++/header/GreLayer.h @@ -128,7 +128,7 @@ namespace pcpp /// Currently identifies the following next layers: /// IPv4Layer, IPv6Layer, VlanLayer, MplsLayer, PPP_PPTPLayer, EthLayer, EthDot3Layer /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of GRE header (may change if optional fields are added or removed) size_t getHeaderLen() const override; @@ -368,7 +368,7 @@ namespace pcpp // implement abstract methods /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The size of @ref ppp_pptp_header size_t getHeaderLen() const override diff --git a/Packet++/header/GtpLayer.h b/Packet++/header/GtpLayer.h index 91428fb3df..a7d9ba28af 100644 --- a/Packet++/header/GtpLayer.h +++ b/Packet++/header/GtpLayer.h @@ -391,7 +391,7 @@ namespace pcpp // implement abstract methods /// Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The size of the GTP header. For GTP-C packets the size is determined by the value of /// gtpv1_header#messageLength and for GTP-U the size only includes the GTP header itself (meaning @@ -1099,7 +1099,7 @@ namespace pcpp // implement abstract methods /// Identifies if the next layer is GTPv2 piggyback. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The size of the GTPv2 header including its Information Elements (IE) size_t getHeaderLen() const override; diff --git a/Packet++/header/IPSecLayer.h b/Packet++/header/IPSecLayer.h index b38cd3a54f..52a5b40306 100644 --- a/Packet++/header/IPSecLayer.h +++ b/Packet++/header/IPSecLayer.h @@ -93,7 +93,7 @@ namespace pcpp /// Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Does nothing for this layer void computeCalculateFields() override @@ -152,7 +152,7 @@ namespace pcpp } /// The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer) - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Does nothing for this layer void computeCalculateFields() override diff --git a/Packet++/header/IPv4Layer.h b/Packet++/header/IPv4Layer.h index 20829b9f4e..30cdd5a9d4 100644 --- a/Packet++/header/IPv4Layer.h +++ b/Packet++/header/IPv4Layer.h @@ -575,7 +575,7 @@ namespace pcpp /// - ESPLayer (IPSec) /// /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of IPv4 header (including IPv4 options if exist) size_t getHeaderLen() const override diff --git a/Packet++/header/IPv6Layer.h b/Packet++/header/IPv6Layer.h index 87cffaafbe..fb220acd96 100644 --- a/Packet++/header/IPv6Layer.h +++ b/Packet++/header/IPv6Layer.h @@ -168,7 +168,7 @@ namespace pcpp /// - ESPLayer (IPSec) /// /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of @ref ip6_hdr size_t getHeaderLen() const override diff --git a/Packet++/header/IcmpLayer.h b/Packet++/header/IcmpLayer.h index 940aa8ce3d..7bba4be151 100644 --- a/Packet++/header/IcmpLayer.h +++ b/Packet++/header/IcmpLayer.h @@ -596,7 +596,7 @@ namespace pcpp /// ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, /// ICMP_PARAM_PROBLEM have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses /// these headers as separate layers on top of the ICMP layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The ICMP header length. This length varies according to the ICMP message type. This length doesn't /// include IPv4 and L4 headers in case ICMP message type are: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, diff --git a/Packet++/header/IcmpV6Layer.h b/Packet++/header/IcmpV6Layer.h index 4038b5e2f2..e4a2075e5e 100644 --- a/Packet++/header/IcmpV6Layer.h +++ b/Packet++/header/IcmpV6Layer.h @@ -166,7 +166,7 @@ namespace pcpp uint16_t getChecksum() const; /// Does nothing for this layer. ICMPv6 is the last layer. - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The size of the ICMPv6 message diff --git a/Packet++/header/IgmpLayer.h b/Packet++/header/IgmpLayer.h index 45e00a391a..b642f7f388 100644 --- a/Packet++/header/IgmpLayer.h +++ b/Packet++/header/IgmpLayer.h @@ -188,7 +188,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (IGMP layer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Size of IGMP header = 8B diff --git a/Packet++/header/LLCLayer.h b/Packet++/header/LLCLayer.h index ddaf7a99ad..791853829c 100644 --- a/Packet++/header/LLCLayer.h +++ b/Packet++/header/LLCLayer.h @@ -53,7 +53,7 @@ namespace pcpp // overridden methods /// Parses the next layer. Currently only STP supported as next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Does nothing for this layer void computeCalculateFields() override diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h index eeb7eaa238..4cf7bbf593 100644 --- a/Packet++/header/Layer.h +++ b/Packet++/header/Layer.h @@ -3,6 +3,7 @@ #include #include #include "ProtocolType.h" +#include "ParserConfig.h" #include #include #include @@ -142,7 +143,12 @@ namespace pcpp // abstract methods /// Each layer is responsible for parsing the next layer - virtual void parseNextLayer() = 0; + void parseNextLayer() + { + parseNextLayer(ParserConfiguration()); + } + + virtual void parseNextLayer(ParserConfiguration const& config) = 0; /// @return The header length in bytes virtual size_t getHeaderLen() const = 0; diff --git a/Packet++/header/LdapLayer.h b/Packet++/header/LdapLayer.h index 4485d17c28..bc7227f07f 100644 --- a/Packet++/header/LdapLayer.h +++ b/Packet++/header/LdapLayer.h @@ -359,7 +359,7 @@ namespace pcpp // implement abstract methods /// Tries to identify more LDAP messages in this packet if exist - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The size of the LDAP message size_t getHeaderLen() const override diff --git a/Packet++/header/MplsLayer.h b/Packet++/header/MplsLayer.h index 12ea1cd817..c06f8a35b8 100644 --- a/Packet++/header/MplsLayer.h +++ b/Packet++/header/MplsLayer.h @@ -88,7 +88,7 @@ namespace pcpp // implement abstract methods /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of MPLS header (4 bytes) size_t getHeaderLen() const override diff --git a/Packet++/header/NflogLayer.h b/Packet++/header/NflogLayer.h index ed997e50b5..6fc02303a4 100644 --- a/Packet++/header/NflogLayer.h +++ b/Packet++/header/NflogLayer.h @@ -184,7 +184,7 @@ namespace pcpp /// Currently identifies the following next layers: IPv4Layer, IPv6Layer using address family /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of nflog_header size_t getHeaderLen() const override; diff --git a/Packet++/header/NtpLayer.h b/Packet++/header/NtpLayer.h index 7dec0ae463..5a669248c6 100644 --- a/Packet++/header/NtpLayer.h +++ b/Packet++/header/NtpLayer.h @@ -536,7 +536,7 @@ namespace pcpp // overridden methods /// Parses the next layer. NTP is the always last so does nothing for this layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Get the size of the layer (Including the extension and authentication fields if exists) diff --git a/Packet++/header/NullLoopbackLayer.h b/Packet++/header/NullLoopbackLayer.h index 0903781771..87b8ad2940 100644 --- a/Packet++/header/NullLoopbackLayer.h +++ b/Packet++/header/NullLoopbackLayer.h @@ -60,7 +60,7 @@ namespace pcpp /// - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is /// IPv6Layer /// - for other values the next layer in PayloadLayer (unknown protocol) - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of Null/Loopback header = 4B size_t getHeaderLen() const override diff --git a/Packet++/header/PPPoELayer.h b/Packet++/header/PPPoELayer.h index aba14b0c8a..65f365068d 100644 --- a/Packet++/header/PPPoELayer.h +++ b/Packet++/header/PPPoELayer.h @@ -149,7 +149,7 @@ namespace pcpp // abstract methods implementation /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of @ref pppoe_header size_t getHeaderLen() const override @@ -350,7 +350,7 @@ namespace pcpp // abstract methods implementation /// Does nothing for this layer (PPPoE discovery is always the last layer) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return The header length which is size of strcut pppoe_header plus the total size of tags diff --git a/Packet++/header/PacketTrailerLayer.h b/Packet++/header/PacketTrailerLayer.h index fdcb8e6487..15e39df185 100644 --- a/Packet++/header/PacketTrailerLayer.h +++ b/Packet++/header/PacketTrailerLayer.h @@ -62,7 +62,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (PacketTrailerLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return trailer data length in bytes diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h new file mode 100644 index 0000000000..7a90cd706a --- /dev/null +++ b/Packet++/header/ParserConfig.h @@ -0,0 +1,95 @@ +#pragma once + +#include +#include +#include + +#include "ProtocolType.h" + +namespace pcpp +{ + class PortRule + { + public: + virtual ~PortRule() = default; + + /// @brief Check if the port rule matches a specific source or destination port + /// @param srcPort The source port to check + /// @return True if the port rule matches the source port, false otherwise + virtual bool matchesSrcPort(uint16_t srcPort) const = 0; + + /// @brief Check if the port rule matches a specific destination port + /// @param dstPort The destination port to check + /// @return True if the port rule matches the destination port, false otherwise + virtual bool matchesDstPort(uint16_t dstPort) const = 0; + + /// @brief Check if the port rule matches a specific combination of source and destination ports + /// @param srcPort The source port to check + /// @param dstPort The destination port to check + /// @return True if the port rule matches the combination of source and destination ports, false otherwise + virtual bool matches(uint16_t srcPort, uint16_t dstPort) const = 0; + }; + + // TODO: Better Name? + class SinglePortRule : public PortRule + { + public: + SinglePortRule(uint16_t port) : port(port) + {} + + bool matchesSrcPort(uint16_t srcPort) const override + { + return srcPort == port; + } + bool matchesDstPort(uint16_t dstPort) const override + { + return dstPort == port; + } + bool matches(uint16_t srcPort, uint16_t dstPort) const override + { + return matchesSrcPort(srcPort) || matchesDstPort(dstPort); + } + + uint16_t port; + }; + + class PortMapper + { + public: + PortMapper() = default; + + /// @brief Add or replace a port rule for a specific protocol + /// @param protocol The protocol type to associate with the port rule + /// @param portRule The port rule to associate with the protocol + void addPortRule(ProtocolType protocol, std::unique_ptr portRule) + { + m_ProtocolToPortRuleMap[protocol] = std::move(portRule); + } + + /// @brief Remove the port rule for a specific protocol + /// @param protocol The protocol type to remove the port rule for + void removePortRule(ProtocolType protocol) + { + m_ProtocolToPortRuleMap.erase(protocol); + } + + /// @brief Get the port rule for a specific protocol + /// @param protocol The protocol type to get the port rule for + /// @return A pointer to the port rule associated with the protocol, or nullptr if not found + const PortRule* getPortRule(ProtocolType protocol) const + { + auto it = m_ProtocolToPortRuleMap.find(protocol); + return it != m_ProtocolToPortRuleMap.end() ? it->second.get() : nullptr; + } + + private: + std::unordered_map> m_ProtocolToPortRuleMap; + }; + + struct ParserConfiguration + { + ParserConfiguration() = default; + + PortMapper portMapper; + }; +} // namespace pcpp \ No newline at end of file diff --git a/Packet++/header/PayloadLayer.h b/Packet++/header/PayloadLayer.h index 2c760d1178..460e79a59a 100644 --- a/Packet++/header/PayloadLayer.h +++ b/Packet++/header/PayloadLayer.h @@ -54,7 +54,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (PayloadLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Payload data length in bytes diff --git a/Packet++/header/RadiusLayer.h b/Packet++/header/RadiusLayer.h index f65fb66b66..bf9aa53767 100644 --- a/Packet++/header/RadiusLayer.h +++ b/Packet++/header/RadiusLayer.h @@ -254,7 +254,7 @@ namespace pcpp size_t getHeaderLen() const override; /// Does nothing for this layer, RADIUS is always last - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// Calculate and store the value of radius_header#length according to the layer size diff --git a/Packet++/header/S7CommLayer.h b/Packet++/header/S7CommLayer.h index 6a65e7913b..1682aa86c4 100644 --- a/Packet++/header/S7CommLayer.h +++ b/Packet++/header/S7CommLayer.h @@ -152,7 +152,7 @@ namespace pcpp {} /// Does nothing for this layer (S7CommLayer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// A static method that takes a byte array and detects whether it is a S7COMM diff --git a/Packet++/header/SSHLayer.h b/Packet++/header/SSHLayer.h index ef07f14d5f..3fd44e7538 100644 --- a/Packet++/header/SSHLayer.h +++ b/Packet++/header/SSHLayer.h @@ -98,7 +98,7 @@ namespace pcpp /// Several SSH records can reside in a single packets. This method examins the remaining data and creates /// additional SSH records if applicable - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Does nothing for this layer void computeCalculateFields() override diff --git a/Packet++/header/SSLLayer.h b/Packet++/header/SSLLayer.h index 5c7a5fc010..c5dea5ed5d 100644 --- a/Packet++/header/SSLLayer.h +++ b/Packet++/header/SSLLayer.h @@ -241,7 +241,7 @@ namespace pcpp /// Several SSL/TLS records can reside in a single packets. So this method checks the remaining data and if it's /// identified as SSL/TLS it creates another SSL/TLS record layer as the next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; OsiModelLayer getOsiModelLayer() const override { diff --git a/Packet++/header/SipLayer.h b/Packet++/header/SipLayer.h index bd25e4cd83..042e47c514 100644 --- a/Packet++/header/SipLayer.h +++ b/Packet++/header/SipLayer.h @@ -101,7 +101,7 @@ namespace pcpp /// Currently identifies only SDP if content-length field exists and set to a value greater than zero. /// If content-length field doesn't exist or set to zero and still there is data after this layer, a /// PayloadLayer will be created - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Set the content-length only if a content-length field already exists and if its current value is different /// than the total length of the next layer(s) diff --git a/Packet++/header/Sll2Layer.h b/Packet++/header/Sll2Layer.h index 83a55253c2..ac2c9df67f 100644 --- a/Packet++/header/Sll2Layer.h +++ b/Packet++/header/Sll2Layer.h @@ -130,7 +130,7 @@ namespace pcpp /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// Calculate the next protocol type for known protocols: IPv4, IPv6, ARP, VLAN void computeCalculateFields() override; diff --git a/Packet++/header/SllLayer.h b/Packet++/header/SllLayer.h index a97b83e983..58c3f59616 100644 --- a/Packet++/header/SllLayer.h +++ b/Packet++/header/SllLayer.h @@ -71,7 +71,7 @@ namespace pcpp /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of sll_header size_t getHeaderLen() const override diff --git a/Packet++/header/SmtpLayer.h b/Packet++/header/SmtpLayer.h index 871a597233..25ff0ff0b9 100644 --- a/Packet++/header/SmtpLayer.h +++ b/Packet++/header/SmtpLayer.h @@ -32,7 +32,7 @@ namespace pcpp // overridden methods /// SMTP is the always last so does nothing for this layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Get the size of the layer diff --git a/Packet++/header/SomeIpLayer.h b/Packet++/header/SomeIpLayer.h index 1f67adb9f0..066a360cd4 100644 --- a/Packet++/header/SomeIpLayer.h +++ b/Packet++/header/SomeIpLayer.h @@ -258,7 +258,7 @@ namespace pcpp {} /// Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The string representation of the SOME/IP layer virtual std::string toString() const override; diff --git a/Packet++/header/StpLayer.h b/Packet++/header/StpLayer.h index 26c90312f4..b5ae529544 100644 --- a/Packet++/header/StpLayer.h +++ b/Packet++/header/StpLayer.h @@ -262,7 +262,7 @@ namespace pcpp } /// Parses next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Returns the protocol info as readable string std::string toString() const override @@ -451,7 +451,7 @@ namespace pcpp } /// Parses next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Returns the protocol info as readable string std::string toString() const override @@ -521,7 +521,7 @@ namespace pcpp } /// Parses next layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Returns the protocol info as readable string std::string toString() const override @@ -688,7 +688,7 @@ namespace pcpp // overridden methods /// Parses next layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Returns the protocol info as readable string diff --git a/Packet++/header/TcpLayer.h b/Packet++/header/TcpLayer.h index 43b0adac47..0245e65ac0 100644 --- a/Packet++/header/TcpLayer.h +++ b/Packet++/header/TcpLayer.h @@ -554,7 +554,7 @@ namespace pcpp /// Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets /// PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of @ref tcphdr + all TCP options size_t getHeaderLen() const override diff --git a/Packet++/header/TelnetLayer.h b/Packet++/header/TelnetLayer.h index 6b56529b5c..701c993b57 100644 --- a/Packet++/header/TelnetLayer.h +++ b/Packet++/header/TelnetLayer.h @@ -294,7 +294,7 @@ namespace pcpp // overridden methods /// Parses the next layer. Telnet is the always last so does nothing for this layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Get the size of the layer diff --git a/Packet++/header/TextBasedProtocol.h b/Packet++/header/TextBasedProtocol.h index 67e109ca7f..ca5fdeff7c 100644 --- a/Packet++/header/TextBasedProtocol.h +++ b/Packet++/header/TextBasedProtocol.h @@ -201,7 +201,7 @@ namespace pcpp // implement Layer's abstract methods /// Currently set only PayloadLayer for the rest of the data - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The message length size_t getHeaderLen() const override; diff --git a/Packet++/header/TpktLayer.h b/Packet++/header/TpktLayer.h index 073942ca54..2546770a91 100644 --- a/Packet++/header/TpktLayer.h +++ b/Packet++/header/TpktLayer.h @@ -73,7 +73,7 @@ namespace pcpp {} /// Currently parses the rest of the packet as a COTP protocol or generic payload (PayloadLayer) - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// A static method that checks whether a source or dest port match those associated with the TPKT protocol /// @param[in] portSrc Source port number to check diff --git a/Packet++/header/UdpLayer.h b/Packet++/header/UdpLayer.h index c78bc2ded9..5557b49372 100644 --- a/Packet++/header/UdpLayer.h +++ b/Packet++/header/UdpLayer.h @@ -74,7 +74,7 @@ namespace pcpp /// Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, /// SipResponseLayer, RadiusLayer. Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of @ref udphdr size_t getHeaderLen() const override diff --git a/Packet++/header/VlanLayer.h b/Packet++/header/VlanLayer.h index 238d36bd1d..ae5a771a99 100644 --- a/Packet++/header/VlanLayer.h +++ b/Packet++/header/VlanLayer.h @@ -94,7 +94,7 @@ namespace pcpp /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. /// Otherwise sets PayloadLayer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of vlan_header size_t getHeaderLen() const override diff --git a/Packet++/header/VrrpLayer.h b/Packet++/header/VrrpLayer.h index eb6f888d88..33074642e1 100644 --- a/Packet++/header/VrrpLayer.h +++ b/Packet++/header/VrrpLayer.h @@ -244,7 +244,7 @@ namespace pcpp // implement abstract methods /// Does nothing for this layer (VRRP layer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// Calculate the VRRP checksum diff --git a/Packet++/header/VxlanLayer.h b/Packet++/header/VxlanLayer.h index 0924dc5b3e..390db95798 100644 --- a/Packet++/header/VxlanLayer.h +++ b/Packet++/header/VxlanLayer.h @@ -115,7 +115,7 @@ namespace pcpp // implement abstract methods /// Next layer for VXLAN is always Ethernet - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return Size of vxlan_header size_t getHeaderLen() const override diff --git a/Packet++/header/WakeOnLanLayer.h b/Packet++/header/WakeOnLanLayer.h index 3e98acc46a..103d4bdc27 100644 --- a/Packet++/header/WakeOnLanLayer.h +++ b/Packet++/header/WakeOnLanLayer.h @@ -116,7 +116,7 @@ namespace pcpp // overridden methods /// Parses the next layer. Wake on LAN is the always last so does nothing for this layer - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Get the size of the layer diff --git a/Packet++/header/WireGuardLayer.h b/Packet++/header/WireGuardLayer.h index 0d59287e93..0417bd4133 100644 --- a/Packet++/header/WireGuardLayer.h +++ b/Packet++/header/WireGuardLayer.h @@ -96,7 +96,7 @@ namespace pcpp void setReserved(const std::array& reserved); /// Does nothing for this layer (WireGuard layer is always last) - void parseNextLayer() override + void parseNextLayer(ParserConfiguration const& config) override {} /// @return Size of the header in bytes. diff --git a/Packet++/src/BgpLayer.cpp b/Packet++/src/BgpLayer.cpp index b32ab8d010..9c1a18b76e 100644 --- a/Packet++/src/BgpLayer.cpp +++ b/Packet++/src/BgpLayer.cpp @@ -77,7 +77,7 @@ namespace pcpp } } - void BgpLayer::parseNextLayer() + void BgpLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen || headerLen == 0) diff --git a/Packet++/src/CiscoHdlcLayer.cpp b/Packet++/src/CiscoHdlcLayer.cpp index 7fac1ae5cd..b34bc73307 100644 --- a/Packet++/src/CiscoHdlcLayer.cpp +++ b/Packet++/src/CiscoHdlcLayer.cpp @@ -43,7 +43,7 @@ namespace pcpp } } - void CiscoHdlcLayer::parseNextLayer() + void CiscoHdlcLayer::parseNextLayer(ParserConfiguration const& config) { auto payload = m_Data + sizeof(cisco_hdlc_header); auto payloadLen = m_DataLen - sizeof(cisco_hdlc_header); diff --git a/Packet++/src/CotpLayer.cpp b/Packet++/src/CotpLayer.cpp index 1183df5f13..610bd0ca14 100644 --- a/Packet++/src/CotpLayer.cpp +++ b/Packet++/src/CotpLayer.cpp @@ -63,7 +63,7 @@ namespace pcpp return data[1] == 0xf0 && data[0] == 2; } - void CotpLayer::parseNextLayer() + void CotpLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/EthDot3Layer.cpp b/Packet++/src/EthDot3Layer.cpp index 35d6d48b14..c4694a4f8b 100644 --- a/Packet++/src/EthDot3Layer.cpp +++ b/Packet++/src/EthDot3Layer.cpp @@ -21,7 +21,7 @@ namespace pcpp m_Protocol = Ethernet; } - void EthDot3Layer::parseNextLayer() + void EthDot3Layer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(ether_dot3_header)) return; diff --git a/Packet++/src/EthLayer.cpp b/Packet++/src/EthLayer.cpp index 40954d3174..01d6a5d341 100644 --- a/Packet++/src/EthLayer.cpp +++ b/Packet++/src/EthLayer.cpp @@ -27,7 +27,7 @@ namespace pcpp m_Protocol = Ethernet; } - void EthLayer::parseNextLayer() + void EthLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(ether_header)) return; diff --git a/Packet++/src/GreLayer.cpp b/Packet++/src/GreLayer.cpp index 37eee3a879..ec2e549edc 100644 --- a/Packet++/src/GreLayer.cpp +++ b/Packet++/src/GreLayer.cpp @@ -192,7 +192,7 @@ namespace pcpp return true; } - void GreLayer::parseNextLayer() + void GreLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) @@ -563,7 +563,7 @@ namespace pcpp header->control = control; } - void PPP_PPTPLayer::parseNextLayer() + void PPP_PPTPLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/GtpLayer.cpp b/Packet++/src/GtpLayer.cpp index 97129b1418..d91fc05c31 100644 --- a/Packet++/src/GtpLayer.cpp +++ b/Packet++/src/GtpLayer.cpp @@ -559,7 +559,7 @@ namespace pcpp return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE; } - void GtpV1Layer::parseNextLayer() + void GtpV1Layer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (headerLen < sizeof(gtpv1_header)) @@ -1302,7 +1302,7 @@ namespace pcpp return GtpV2InformationElement(newInfoElementPtr); } - void GtpV2Layer::parseNextLayer() + void GtpV2Layer::parseNextLayer(ParserConfiguration const& config) { auto headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/IPSecLayer.cpp b/Packet++/src/IPSecLayer.cpp index 5f26dc0468..de0b1b4b17 100644 --- a/Packet++/src/IPSecLayer.cpp +++ b/Packet++/src/IPSecLayer.cpp @@ -51,7 +51,7 @@ namespace pcpp return byteArrayToHexString(bytes, getICVLength()); } - void AuthenticationHeaderLayer::parseNextLayer() + void AuthenticationHeaderLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) @@ -112,7 +112,7 @@ namespace pcpp return be32toh(getESPHeader()->sequenceNumber); } - void ESPLayer::parseNextLayer() + void ESPLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/IPv4Layer.cpp b/Packet++/src/IPv4Layer.cpp index 4a09134b96..cecedfa0cc 100644 --- a/Packet++/src/IPv4Layer.cpp +++ b/Packet++/src/IPv4Layer.cpp @@ -244,7 +244,7 @@ namespace pcpp return *this; } - void IPv4Layer::parseNextLayer() + void IPv4Layer::parseNextLayer(ParserConfiguration const& config) { size_t hdrLen = getHeaderLen(); if (m_DataLen <= hdrLen || hdrLen == 0) diff --git a/Packet++/src/IPv6Layer.cpp b/Packet++/src/IPv6Layer.cpp index fb17d09051..b5b7ab2a46 100644 --- a/Packet++/src/IPv6Layer.cpp +++ b/Packet++/src/IPv6Layer.cpp @@ -193,7 +193,7 @@ namespace pcpp return getExtensionOfType() != nullptr; } - void IPv6Layer::parseNextLayer() + void IPv6Layer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); diff --git a/Packet++/src/IcmpLayer.cpp b/Packet++/src/IcmpLayer.cpp index a69f4a3769..84b75cf9c1 100644 --- a/Packet++/src/IcmpLayer.cpp +++ b/Packet++/src/IcmpLayer.cpp @@ -561,7 +561,7 @@ namespace pcpp return header; } - void IcmpLayer::parseNextLayer() + void IcmpLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); diff --git a/Packet++/src/LLCLayer.cpp b/Packet++/src/LLCLayer.cpp index 5cfe5d84da..25d537d940 100644 --- a/Packet++/src/LLCLayer.cpp +++ b/Packet++/src/LLCLayer.cpp @@ -24,7 +24,7 @@ namespace pcpp header->control = control; } - void LLCLayer::parseNextLayer() + void LLCLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(llc_header)) return; diff --git a/Packet++/src/LdapLayer.cpp b/Packet++/src/LdapLayer.cpp index 9b16619e2f..e079e94572 100644 --- a/Packet++/src/LdapLayer.cpp +++ b/Packet++/src/LdapLayer.cpp @@ -356,7 +356,7 @@ namespace pcpp return LdapOperationType::fromUintValue(tagType); } - void LdapLayer::parseNextLayer() + void LdapLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen || headerLen == 0) diff --git a/Packet++/src/MplsLayer.cpp b/Packet++/src/MplsLayer.cpp index fe57a68529..025a9451fb 100644 --- a/Packet++/src/MplsLayer.cpp +++ b/Packet++/src/MplsLayer.cpp @@ -101,7 +101,7 @@ namespace pcpp return true; } - void MplsLayer::parseNextLayer() + void MplsLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen < headerLen + 1) diff --git a/Packet++/src/NflogLayer.cpp b/Packet++/src/NflogLayer.cpp index 3dc6f94480..011b2f6d53 100644 --- a/Packet++/src/NflogLayer.cpp +++ b/Packet++/src/NflogLayer.cpp @@ -37,7 +37,7 @@ namespace pcpp return tlv; } - void NflogLayer::parseNextLayer() + void NflogLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(nflog_header)) { diff --git a/Packet++/src/NullLoopbackLayer.cpp b/Packet++/src/NullLoopbackLayer.cpp index 2717d8ff6c..d92c869eec 100644 --- a/Packet++/src/NullLoopbackLayer.cpp +++ b/Packet++/src/NullLoopbackLayer.cpp @@ -50,7 +50,7 @@ namespace pcpp *m_Data = family; } - void NullLoopbackLayer::parseNextLayer() + void NullLoopbackLayer::parseNextLayer(ParserConfiguration const& config) { uint8_t* payload = m_Data + sizeof(uint32_t); size_t payloadLen = m_DataLen - sizeof(uint32_t); diff --git a/Packet++/src/PPPoELayer.cpp b/Packet++/src/PPPoELayer.cpp index c30625cfd9..85bbee9e56 100644 --- a/Packet++/src/PPPoELayer.cpp +++ b/Packet++/src/PPPoELayer.cpp @@ -40,7 +40,7 @@ namespace pcpp /// PPPoESessionLayer /// ~~~~~~~~~~~~~~~~~ - void PPPoESessionLayer::parseNextLayer() + void PPPoESessionLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SSHLayer.cpp b/Packet++/src/SSHLayer.cpp index 468f91b6c1..4aebce5e2c 100644 --- a/Packet++/src/SSHLayer.cpp +++ b/Packet++/src/SSHLayer.cpp @@ -28,7 +28,7 @@ namespace pcpp return new SSHEncryptedMessage(data, dataLen, prevLayer, packet); } - void SSHLayer::parseNextLayer() + void SSHLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SSLLayer.cpp b/Packet++/src/SSLLayer.cpp index e83b789c07..6113ac3369 100644 --- a/Packet++/src/SSLLayer.cpp +++ b/Packet++/src/SSLLayer.cpp @@ -88,7 +88,7 @@ namespace pcpp return len; } - void SSLLayer::parseNextLayer() + void SSLLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SipLayer.cpp b/Packet++/src/SipLayer.cpp index ac9acb1289..bb3ddbbea8 100644 --- a/Packet++/src/SipLayer.cpp +++ b/Packet++/src/SipLayer.cpp @@ -64,7 +64,7 @@ namespace pcpp return contentLengthField; } - void SipLayer::parseNextLayer() + void SipLayer::parseNextLayer(ParserConfiguration const& config) { if (getLayerPayloadSize() == 0) return; diff --git a/Packet++/src/Sll2Layer.cpp b/Packet++/src/Sll2Layer.cpp index 8bcbd3cedd..b5a066d80e 100644 --- a/Packet++/src/Sll2Layer.cpp +++ b/Packet++/src/Sll2Layer.cpp @@ -56,7 +56,7 @@ namespace pcpp return setLinkLayerAddr(macAddrAsArr, 6); } - void Sll2Layer::parseNextLayer() + void Sll2Layer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(sll2_header)) return; diff --git a/Packet++/src/SllLayer.cpp b/Packet++/src/SllLayer.cpp index 1f5b9daa84..6826c40f69 100644 --- a/Packet++/src/SllLayer.cpp +++ b/Packet++/src/SllLayer.cpp @@ -48,7 +48,7 @@ namespace pcpp return setLinkLayerAddr(macAddrAsArr, 6); } - void SllLayer::parseNextLayer() + void SllLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(sll_header)) return; diff --git a/Packet++/src/SomeIpLayer.cpp b/Packet++/src/SomeIpLayer.cpp index 1c7bdec1c3..d816c9bdf3 100644 --- a/Packet++/src/SomeIpLayer.cpp +++ b/Packet++/src/SomeIpLayer.cpp @@ -255,7 +255,7 @@ namespace pcpp payloadLength); } - void SomeIpLayer::parseNextLayer() + void SomeIpLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/StpLayer.cpp b/Packet++/src/StpLayer.cpp index 147395018d..f4ce554202 100644 --- a/Packet++/src/StpLayer.cpp +++ b/Packet++/src/StpLayer.cpp @@ -79,7 +79,7 @@ namespace pcpp setType(0x80); } - void StpTopologyChangeBPDULayer::parseNextLayer() + void StpTopologyChangeBPDULayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(stp_tcn_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_tcn_bpdu), this, m_Packet); @@ -224,7 +224,7 @@ namespace pcpp getStpConfHeader()->forwardDelay = value; } - void StpConfigurationBPDULayer::parseNextLayer() + void StpConfigurationBPDULayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(stp_conf_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_conf_bpdu), this, m_Packet); @@ -239,7 +239,7 @@ namespace pcpp setType(0x2); } - void RapidStpLayer::parseNextLayer() + void RapidStpLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(rstp_conf_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(rstp_conf_bpdu), this, m_Packet); diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 5fe34027ba..75a61bf4f4 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -354,7 +354,7 @@ namespace pcpp return *this; } - void TcpLayer::parseNextLayer() + void TcpLayer::parseNextLayer(ParserConfiguration const& config) { const size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/TextBasedProtocol.cpp b/Packet++/src/TextBasedProtocol.cpp index 1d35996384..b0bb03285c 100644 --- a/Packet++/src/TextBasedProtocol.cpp +++ b/Packet++/src/TextBasedProtocol.cpp @@ -403,7 +403,7 @@ namespace pcpp return result; } - void TextBasedProtocolMessage::parseNextLayer() + void TextBasedProtocolMessage::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/TpktLayer.cpp b/Packet++/src/TpktLayer.cpp index c3fe3a9ff7..6e61a8b87b 100644 --- a/Packet++/src/TpktLayer.cpp +++ b/Packet++/src/TpktLayer.cpp @@ -54,7 +54,7 @@ namespace pcpp return "TPKT Layer, version: " + versionStream.str() + ", length: " + lengthStream.str(); } - void TpktLayer::parseNextLayer() + void TpktLayer::parseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 9cfaa2cbe0..f4a1274c4f 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -89,7 +89,7 @@ namespace pcpp return checksumRes; } - void UdpLayer::parseNextLayer() + void UdpLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(udphdr)) return; diff --git a/Packet++/src/VlanLayer.cpp b/Packet++/src/VlanLayer.cpp index f12ca798ae..766abfd4f9 100644 --- a/Packet++/src/VlanLayer.cpp +++ b/Packet++/src/VlanLayer.cpp @@ -59,7 +59,7 @@ namespace pcpp getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(7 << 13))) | ((priority & 7) << 13)); } - void VlanLayer::parseNextLayer() + void VlanLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(vlan_header)) return; diff --git a/Packet++/src/VxlanLayer.cpp b/Packet++/src/VxlanLayer.cpp index 6001b4197b..9d6513f557 100644 --- a/Packet++/src/VxlanLayer.cpp +++ b/Packet++/src/VxlanLayer.cpp @@ -49,7 +49,7 @@ namespace pcpp return "VXLAN Layer"; } - void VxlanLayer::parseNextLayer() + void VxlanLayer::parseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(vxlan_header)) return; From a37a63f6e8f197e579308d21acf24d2b6f58b9d4 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Wed, 21 May 2025 21:35:27 +0300 Subject: [PATCH 02/52] Added nullptr guard and a helper method fetching required rules. --- Packet++/header/ParserConfig.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 7a90cd706a..564aa13170 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -61,8 +61,14 @@ namespace pcpp /// @brief Add or replace a port rule for a specific protocol /// @param protocol The protocol type to associate with the port rule /// @param portRule The port rule to associate with the protocol + /// @throw std::invalid_argument if the port rule is null void addPortRule(ProtocolType protocol, std::unique_ptr portRule) { + if (portRule == nullptr) + { + throw std::invalid_argument("Port rule cannot be null"); + } + m_ProtocolToPortRuleMap[protocol] = std::move(portRule); } @@ -82,6 +88,15 @@ namespace pcpp return it != m_ProtocolToPortRuleMap.end() ? it->second.get() : nullptr; } + /// @brief Get the required port rule for a specific protocol + /// @param protocol The protocol type to get the port rule for + /// @return A reference to the port rule associated with the protocol + /// @throw std::out_of_range if the protocol is not found + PortRule const& getRequiredPortRule(ProtocolType protocol) const + { + return *m_ProtocolToPortRuleMap.at(protocol); + } + private: std::unordered_map> m_ProtocolToPortRuleMap; }; From 319ca9c6567b30e0886edbc53bace804c1ba0ba2 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Wed, 21 May 2025 21:39:17 +0300 Subject: [PATCH 03/52] Renamed methods to tryGetPortRule and getPortRule. --- Packet++/header/ParserConfig.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 564aa13170..c478071105 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -2,6 +2,7 @@ #include #include +#include #include #include "ProtocolType.h" @@ -82,7 +83,7 @@ namespace pcpp /// @brief Get the port rule for a specific protocol /// @param protocol The protocol type to get the port rule for /// @return A pointer to the port rule associated with the protocol, or nullptr if not found - const PortRule* getPortRule(ProtocolType protocol) const + const PortRule* tryGetPortRule(ProtocolType protocol) const { auto it = m_ProtocolToPortRuleMap.find(protocol); return it != m_ProtocolToPortRuleMap.end() ? it->second.get() : nullptr; @@ -92,7 +93,7 @@ namespace pcpp /// @param protocol The protocol type to get the port rule for /// @return A reference to the port rule associated with the protocol /// @throw std::out_of_range if the protocol is not found - PortRule const& getRequiredPortRule(ProtocolType protocol) const + PortRule const& getPortRule(ProtocolType protocol) const { return *m_ProtocolToPortRuleMap.at(protocol); } From 3c269629626141c858f3a72581dc3b1db08b5ab1 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 19:27:05 +0300 Subject: [PATCH 04/52] Rework the port mapper. --- Packet++/header/Layer.h | 2 +- Packet++/header/ParserConfig.h | 191 ++++++++++++++++++++++----------- 2 files changed, 131 insertions(+), 62 deletions(-) diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h index 4cf7bbf593..0408003164 100644 --- a/Packet++/header/Layer.h +++ b/Packet++/header/Layer.h @@ -145,7 +145,7 @@ namespace pcpp /// Each layer is responsible for parsing the next layer void parseNextLayer() { - parseNextLayer(ParserConfiguration()); + parseNextLayer(ParserConfiguration::getDefault()); } virtual void parseNextLayer(ParserConfiguration const& config) = 0; diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index c478071105..02d339fa1e 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -5,101 +5,147 @@ #include #include +#include "Logger.h" #include "ProtocolType.h" namespace pcpp { - class PortRule + struct PortPair { - public: - virtual ~PortRule() = default; - - /// @brief Check if the port rule matches a specific source or destination port - /// @param srcPort The source port to check - /// @return True if the port rule matches the source port, false otherwise - virtual bool matchesSrcPort(uint16_t srcPort) const = 0; - - /// @brief Check if the port rule matches a specific destination port - /// @param dstPort The destination port to check - /// @return True if the port rule matches the destination port, false otherwise - virtual bool matchesDstPort(uint16_t dstPort) const = 0; - - /// @brief Check if the port rule matches a specific combination of source and destination ports - /// @param srcPort The source port to check - /// @param dstPort The destination port to check - /// @return True if the port rule matches the combination of source and destination ports, false otherwise - virtual bool matches(uint16_t srcPort, uint16_t dstPort) const = 0; - }; + static constexpr uint16_t AnyPort = 0; - // TODO: Better Name? - class SinglePortRule : public PortRule - { - public: - SinglePortRule(uint16_t port) : port(port) - {} + uint16_t portSrc = AnyPort; ///< Source port number + uint16_t portDst = AnyPort; ///< Destination port number - bool matchesSrcPort(uint16_t srcPort) const override + constexpr static PortPair fromSrc(uint16_t portSrc) { - return srcPort == port; + return { portSrc, AnyPort }; } - bool matchesDstPort(uint16_t dstPort) const override - { - return dstPort == port; - } - bool matches(uint16_t srcPort, uint16_t dstPort) const override + + constexpr static PortPair fromDst(uint16_t portDst) { - return matchesSrcPort(srcPort) || matchesDstPort(dstPort); + return { AnyPort, portDst }; } - - uint16_t port; }; class PortMapper { public: + /// @brief Create an empty PortMapper. PortMapper() = default; + /// @brief Create a PortMapper with a predefined mapping of ports to protocol types. + /// @param portToProtocolMap An unordered map where keys are port numbers and values are ProtocolType values. + PortMapper(std::unordered_map portToProtocolMap) + : m_PortToProtocolMap(std::move(portToProtocolMap)) + {} - /// @brief Add or replace a port rule for a specific protocol - /// @param protocol The protocol type to associate with the port rule - /// @param portRule The port rule to associate with the protocol - /// @throw std::invalid_argument if the port rule is null - void addPortRule(ProtocolType protocol, std::unique_ptr portRule) + /// @brief Add a port mapping to the port mapper. + /// @param port The port number to map. + /// @param protocol The ProtocolType to associate with the port. + /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the same). + void addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical = false) { - if (portRule == nullptr) + if (port == PortPair()) { - throw std::invalid_argument("Port rule cannot be null"); + throw std::invalid_argument("PortPair cannot be empty (both src and dst ports are 0)"); } - m_ProtocolToPortRuleMap[protocol] = std::move(portRule); + auto insertResult = m_PortToProtocolMap.insert({ port, protocol }); + insertResult.first->second = protocol; // Update the protocol if it already exists + if (!insertResult.second) + { + PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << insertResult.first->second + << ", updating to " << protocol); + } + + if (symmetrical && port.portSrc != port.portDst) + { + // Add the symmetrical mapping + PortPair symmetricalPort = { port.portDst, port.portSrc }; + addPortMapping(symmetricalPort, protocol, false); + } } - /// @brief Remove the port rule for a specific protocol - /// @param protocol The protocol type to remove the port rule for - void removePortRule(ProtocolType protocol) + /// @brief Remove a port mapping from the port mapper. + /// @param port The port number to remove from the mapping. + void removePortMapping(PortPair port) { - m_ProtocolToPortRuleMap.erase(protocol); + auto it = m_PortToProtocolMap.find(port); + if (it != m_PortToProtocolMap.end()) + { + m_PortToProtocolMap.erase(it); + } + else + { + PCPP_LOG_DEBUG("Port " << port << " not found in port mapper, nothing to remove"); + } } - /// @brief Get the port rule for a specific protocol - /// @param protocol The protocol type to get the port rule for - /// @return A pointer to the port rule associated with the protocol, or nullptr if not found - const PortRule* tryGetPortRule(ProtocolType protocol) const + /// @brief Get the protocol type associated with a specific port. + /// + /// The method checks for an exact match of the port pair first. + /// If `exact` is false, it will also check for a match on either the source or destination port. + /// + /// @param port The port number to look up. + /// @param exact If true, only an exact match of the port pair is considered. If false, src or dst port matches + /// @return The ProtocolType associated with the port, or UnknownProtocol if not found. + ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const { - auto it = m_ProtocolToPortRuleMap.find(protocol); - return it != m_ProtocolToPortRuleMap.end() ? it->second.get() : nullptr; + // Order of precedence: + // 1. Check for exact match of port pair + // 1.a If exact is true, return the protocol type if found, go to step 4 if not found + // 2. If not found, check for src port match + // 3. If not found, check for dst port match + // 4. If still not found, return UnknownProtocol + + auto it = m_PortToProtocolMap.find(port); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + if (exact) + return UnknownProtocol; // Return UnknownProtocol if exact match not found + + // Check for src port match + it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + // Check for dst port match + it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + return UnknownProtocol; // Return UnknownProtocol if port not found } - /// @brief Get the required port rule for a specific protocol - /// @param protocol The protocol type to get the port rule for - /// @return A reference to the port rule associated with the protocol - /// @throw std::out_of_range if the protocol is not found - PortRule const& getPortRule(ProtocolType protocol) const + /// @brief Check if a port matches a specific protocol type. + /// @param port The port number to check. + /// @param protocol The ProtocolType to match against. + /// @return True if the port matches the protocol type, false otherwise. + bool matchesPortAndProtocol(PortPair port, ProtocolType protocol) const { - return *m_ProtocolToPortRuleMap.at(protocol); + return getProtocolByPortPair(port) == protocol; + } + + static PortMapper makeDefaultPortMapper() + { + PortMapper mapper; + // Add HTTP port mappings + mapper.addPortMapping(PortPair::fromDst(80), HTTPRequest, false); + mapper.addPortMapping(PortPair::fromSrc(80), HTTPResponse, false); + mapper.addPortMapping(PortPair::fromDst(8080), HTTPRequest, false); + mapper.addPortMapping(PortPair::fromSrc(8080), HTTPResponse, false); + return mapper; } private: - std::unordered_map> m_ProtocolToPortRuleMap; + std::unordered_map m_PortToProtocolMap; }; struct ParserConfiguration @@ -107,5 +153,28 @@ namespace pcpp ParserConfiguration() = default; PortMapper portMapper; + + /// @brief Creates a new instance of ParserConfiguration with default settings. + /// + /// Prefer using `getDefault()` to obtain the default configuration if a new instance is not required. + /// + /// @return A ParserConfiguration instance with default port mappings. + static ParserConfiguration makeDefaultConfiguration() + { + ParserConfiguration config; + config.portMapper = PortMapper::makeDefaultPortMapper(); + return config; + } + + /// @brief Get the default parser configuration. + /// + /// The returned reference can be used to configure the parser globally. + /// + /// @return A reference to the default ParserConfiguration instance. + static inline ParserConfiguration& getDefault() + { + static ParserConfiguration defaultConfig = makeDefaultConfiguration(); + return defaultConfig; + } }; } // namespace pcpp \ No newline at end of file From 938c74ee646f6bc716c5317ff10c2cc0cb386599 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 19:43:06 +0300 Subject: [PATCH 05/52] Moved some functions to cpp file. --- Packet++/CMakeLists.txt | 1 + Packet++/header/ParserConfig.h | 117 +++++++++++---------------------- Packet++/src/ParserConfig.cpp | 82 +++++++++++++++++++++++ 3 files changed, 120 insertions(+), 80 deletions(-) create mode 100644 Packet++/src/ParserConfig.cpp diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index f31e959362..744f278355 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -37,6 +37,7 @@ add_library( src/Packet.cpp src/PacketTrailerLayer.cpp src/PacketUtils.cpp + src/ParserConfig.cpp src/PayloadLayer.cpp src/PPPoELayer.cpp src/RadiusLayer.cpp diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 02d339fa1e..9e94c6681a 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -26,103 +26,60 @@ namespace pcpp { return { AnyPort, portDst }; } + + constexpr bool operator==(const PortPair& other) const noexcept + { + return portSrc == other.portSrc && portDst == other.portDst; + } + + friend std::ostream& operator<<(std::ostream& os, PortPair const pair) + { + os << "PortPair(src: " << pair.portSrc << ", dst: " << pair.portDst << ")"; + return os; + } + }; +} // namespace pcpp + +namespace std +{ + template <> + struct hash + { + size_t operator()(const pcpp::PortPair& portPair) const noexcept + { + return std::hash()(portPair.portDst << 16 | portPair.portSrc); + } }; +} // namespace std +namespace pcpp +{ class PortMapper { public: /// @brief Create an empty PortMapper. PortMapper() = default; - /// @brief Create a PortMapper with a predefined mapping of ports to protocol types. - /// @param portToProtocolMap An unordered map where keys are port numbers and values are ProtocolType values. - PortMapper(std::unordered_map portToProtocolMap) - : m_PortToProtocolMap(std::move(portToProtocolMap)) - {} /// @brief Add a port mapping to the port mapper. /// @param port The port number to map. /// @param protocol The ProtocolType to associate with the port. - /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the same). - void addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical = false) - { - if (port == PortPair()) - { - throw std::invalid_argument("PortPair cannot be empty (both src and dst ports are 0)"); - } - - auto insertResult = m_PortToProtocolMap.insert({ port, protocol }); - insertResult.first->second = protocol; // Update the protocol if it already exists - if (!insertResult.second) - { - PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << insertResult.first->second - << ", updating to " << protocol); - } - - if (symmetrical && port.portSrc != port.portDst) - { - // Add the symmetrical mapping - PortPair symmetricalPort = { port.portDst, port.portSrc }; - addPortMapping(symmetricalPort, protocol, false); - } - } + /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the interchangable). + void addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical = false); /// @brief Remove a port mapping from the port mapper. /// @param port The port number to remove from the mapping. - void removePortMapping(PortPair port) - { - auto it = m_PortToProtocolMap.find(port); - if (it != m_PortToProtocolMap.end()) - { - m_PortToProtocolMap.erase(it); - } - else - { - PCPP_LOG_DEBUG("Port " << port << " not found in port mapper, nothing to remove"); - } - } + /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the interchangable). + void removePortMapping(PortPair port, bool symmetrical = false); /// @brief Get the protocol type associated with a specific port. - /// + /// /// The method checks for an exact match of the port pair first. /// If `exact` is false, it will also check for a match on either the source or destination port. - /// + /// /// @param port The port number to look up. /// @param exact If true, only an exact match of the port pair is considered. If false, src or dst port matches /// @return The ProtocolType associated with the port, or UnknownProtocol if not found. - ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const - { - // Order of precedence: - // 1. Check for exact match of port pair - // 1.a If exact is true, return the protocol type if found, go to step 4 if not found - // 2. If not found, check for src port match - // 3. If not found, check for dst port match - // 4. If still not found, return UnknownProtocol - - auto it = m_PortToProtocolMap.find(port); - if (it != m_PortToProtocolMap.end()) - { - return it->second; - } - - if (exact) - return UnknownProtocol; // Return UnknownProtocol if exact match not found - - // Check for src port match - it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); - if (it != m_PortToProtocolMap.end()) - { - return it->second; - } - - // Check for dst port match - it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); - if (it != m_PortToProtocolMap.end()) - { - return it->second; - } - - return UnknownProtocol; // Return UnknownProtocol if port not found - } + ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const; /// @brief Check if a port matches a specific protocol type. /// @param port The port number to check. @@ -155,9 +112,9 @@ namespace pcpp PortMapper portMapper; /// @brief Creates a new instance of ParserConfiguration with default settings. - /// + /// /// Prefer using `getDefault()` to obtain the default configuration if a new instance is not required. - /// + /// /// @return A ParserConfiguration instance with default port mappings. static ParserConfiguration makeDefaultConfiguration() { @@ -167,9 +124,9 @@ namespace pcpp } /// @brief Get the default parser configuration. - /// + /// /// The returned reference can be used to configure the parser globally. - /// + /// /// @return A reference to the default ParserConfiguration instance. static inline ParserConfiguration& getDefault() { diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp new file mode 100644 index 0000000000..34b1d95774 --- /dev/null +++ b/Packet++/src/ParserConfig.cpp @@ -0,0 +1,82 @@ +#include "ParserConfig.h" + +namespace pcpp +{ + void PortMapper::addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical) + { + if (port == PortPair()) + { + throw std::invalid_argument("PortPair cannot be empty (both src and dst ports are 0)"); + } + + auto insertResult = m_PortToProtocolMap.insert({ port, protocol }); + insertResult.first->second = protocol; // Update the protocol if it already exists + if (!insertResult.second) + { + PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << insertResult.first->second + << ", updating to " << protocol); + } + + if (symmetrical && port.portSrc != port.portDst) + { + // Add the symmetrical mapping + PortPair symmetricalPort = { port.portDst, port.portSrc }; + addPortMapping(symmetricalPort, protocol, false); + } + } + + void PortMapper::removePortMapping(PortPair port, bool symmetrical) + { + auto it = m_PortToProtocolMap.find(port); + if (it != m_PortToProtocolMap.end()) + { + m_PortToProtocolMap.erase(it); + } + else + { + PCPP_LOG_DEBUG("Port " << port << " not found in port mapper, nothing to remove"); + } + + if (symmetrical && port.portSrc != port.portDst) + { + // Remove the symmetrical mapping + PortPair symmetricalPort = { port.portDst, port.portSrc }; + removePortMapping(symmetricalPort, false); + } + } + + ProtocolType PortMapper::getProtocolByPortPair(PortPair port, bool exact) const + { + // Order of precedence: + // 1. Check for exact match of port pair + // 1.a If exact is true, return the protocol type if found, go to step 4 if not found + // 2. If not found, check for src port match + // 3. If not found, check for dst port match + // 4. If still not found, return UnknownProtocol + + auto it = m_PortToProtocolMap.find(port); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + if (exact) + return UnknownProtocol; // Return UnknownProtocol if exact match not found + + // Check for src port match + it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + // Check for dst port match + it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); + if (it != m_PortToProtocolMap.end()) + { + return it->second; + } + + return UnknownProtocol; // Return UnknownProtocol if port not found + } +} \ No newline at end of file From 94084f8be1b3b0754500ea96d6f35bfdba231290 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 19:50:06 +0300 Subject: [PATCH 06/52] Fixed parser memory leak false positive. --- Tests/Packet++Test/main.cpp | 5 +++++ Tests/Pcap++Test/main.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 7b44df3e0d..87b3d8fdad 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -3,6 +3,7 @@ #include "PcppTestFrameworkRun.h" #include "TestDefinition.h" #include "Logger.h" +#include "ParserConfig.h" #include "../../Tests/Packet++Test/Utils/TestUtils.h" static struct option PacketTestOptions[] = { @@ -88,6 +89,10 @@ int main(int argc, char* argv[]) // Disables context pooling to avoid false positives in the memory leak check, as the contexts persist in the pool. pcpp::Logger::getInstance().useContextPooling(false); + // Required to initialize the logger singleton before running tests. + // Lazy initialization will be detected as a false positive memory leak + pcpp::ParserConfiguration::getDefault(); + // cppcheck-suppress knownConditionTrueFalse if (skipMemLeakCheck) { diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index f37f34b761..601c4ca512 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -1,5 +1,6 @@ #include "PcapPlusPlusVersion.h" #include "Logger.h" +#include "ParserConfig.h" #include "PcppTestFrameworkRun.h" #include "TestDefinition.h" #include "Common/GlobalTestArgs.h" @@ -147,6 +148,10 @@ int main(int argc, char* argv[]) // Disables context pooling to avoid false positives in the memory leak check, as the contexts persist in the pool. pcpp::Logger::getInstance().useContextPooling(false); + // Required to initialize the logger singleton before running tests. + // Lazy initialization will be detected as a false positive memory leak + pcpp::ParserConfiguration::getDefault(); + // cppcheck-suppress knownConditionTrueFalse if (skipMemLeakCheck) { From c7b79bffcc908aaded91ec00d2f746a1517f792a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 19:56:21 +0300 Subject: [PATCH 07/52] Moved default factories to cpp file. --- Packet++/header/ParserConfig.h | 18 ++---------------- Packet++/src/ParserConfig.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 9e94c6681a..16f07a9ccb 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -90,16 +90,7 @@ namespace pcpp return getProtocolByPortPair(port) == protocol; } - static PortMapper makeDefaultPortMapper() - { - PortMapper mapper; - // Add HTTP port mappings - mapper.addPortMapping(PortPair::fromDst(80), HTTPRequest, false); - mapper.addPortMapping(PortPair::fromSrc(80), HTTPResponse, false); - mapper.addPortMapping(PortPair::fromDst(8080), HTTPRequest, false); - mapper.addPortMapping(PortPair::fromSrc(8080), HTTPResponse, false); - return mapper; - } + static PortMapper makeDefaultPortMapper(); private: std::unordered_map m_PortToProtocolMap; @@ -116,12 +107,7 @@ namespace pcpp /// Prefer using `getDefault()` to obtain the default configuration if a new instance is not required. /// /// @return A ParserConfiguration instance with default port mappings. - static ParserConfiguration makeDefaultConfiguration() - { - ParserConfiguration config; - config.portMapper = PortMapper::makeDefaultPortMapper(); - return config; - } + static ParserConfiguration makeDefaultConfiguration(); /// @brief Get the default parser configuration. /// diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 34b1d95774..7b03c118f8 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -2,6 +2,17 @@ namespace pcpp { + PortMapper PortMapper::makeDefaultPortMapper() + { + PortMapper mapper; + // Add HTTP port mappings + mapper.addPortMapping(PortPair::fromDst(80), HTTPRequest, false); + mapper.addPortMapping(PortPair::fromSrc(80), HTTPResponse, false); + mapper.addPortMapping(PortPair::fromDst(8080), HTTPRequest, false); + mapper.addPortMapping(PortPair::fromSrc(8080), HTTPResponse, false); + return mapper; + } + void PortMapper::addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical) { if (port == PortPair()) @@ -79,4 +90,11 @@ namespace pcpp return UnknownProtocol; // Return UnknownProtocol if port not found } + + ParserConfiguration ParserConfiguration::makeDefaultConfiguration() + { + ParserConfiguration config; + config.portMapper = PortMapper::makeDefaultPortMapper(); + return config; + } } \ No newline at end of file From 7252620eb583933a9a93ba46ff8ca3db03e21e80 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 20:01:44 +0300 Subject: [PATCH 08/52] Convert HTTP implementation to use PortMapper. --- Packet++/src/TcpLayer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index 75a61bf4f4..64a5269b2f 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -366,12 +366,14 @@ namespace pcpp const uint16_t portSrc = getSrcPort(); const char* payloadChar = reinterpret_cast(payload); - if (HttpMessage::isHttpPort(portDst) && + auto const& portMapper = config.portMapper; + + if (portMapper.matchesPortAndProtocol(PortPair::fromDst(portDst), HTTPRequest) && HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) { constructNextLayer(payload, payloadLen, m_Packet); } - else if (HttpMessage::isHttpPort(portSrc) && + else if (portMapper.matchesPortAndProtocol(PortPair::fromSrc(portSrc), HTTPResponse) && HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown && !HttpResponseFirstLine::parseStatusCode(payloadChar, payloadLen).isUnsupportedCode()) { From 9652a06f96f9e8d0717136dead909ab8fc241052 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 20:02:52 +0300 Subject: [PATCH 09/52] Lint --- Packet++/header/ParserConfig.h | 11 ++++++----- Packet++/src/ParserConfig.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 16f07a9ccb..1384af143f 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -42,8 +42,7 @@ namespace pcpp namespace std { - template <> - struct hash + template <> struct hash { size_t operator()(const pcpp::PortPair& portPair) const noexcept { @@ -63,12 +62,14 @@ namespace pcpp /// @brief Add a port mapping to the port mapper. /// @param port The port number to map. /// @param protocol The ProtocolType to associate with the port. - /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the interchangable). + /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the + /// interchangeable). void addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical = false); /// @brief Remove a port mapping from the port mapper. /// @param port The port number to remove from the mapping. - /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the interchangable). + /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the + /// interchangeable). void removePortMapping(PortPair port, bool symmetrical = false); /// @brief Get the protocol type associated with a specific port. @@ -120,4 +121,4 @@ namespace pcpp return defaultConfig; } }; -} // namespace pcpp \ No newline at end of file +} // namespace pcpp diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 7b03c118f8..b2c99cb5ef 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -97,4 +97,4 @@ namespace pcpp config.portMapper = PortMapper::makeDefaultPortMapper(); return config; } -} \ No newline at end of file +} // namespace pcpp From 1682e4baac47ff388fd96a75e14528102b31861f Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 20:16:26 +0300 Subject: [PATCH 10/52] Added helper method to reset the default config/ --- Packet++/header/ParserConfig.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 1384af143f..8cbe0ffa1b 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -120,5 +120,11 @@ namespace pcpp static ParserConfiguration defaultConfig = makeDefaultConfiguration(); return defaultConfig; } + + /// @brief Reset the default parser configuration to its initial state. + static inline void resetDefault() + { + getDefault() = makeDefaultConfiguration(); + } }; } // namespace pcpp From 89ca885f7741fbc74c3c5a5c79dd30df45500f1f Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 21:08:13 +0300 Subject: [PATCH 11/52] Added explicit cast to uint32_t in hash function. --- Packet++/header/ParserConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 8cbe0ffa1b..7add8a0b8d 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -46,7 +46,7 @@ namespace std { size_t operator()(const pcpp::PortPair& portPair) const noexcept { - return std::hash()(portPair.portDst << 16 | portPair.portSrc); + return std::hash()(static_cast(portPair.portDst) << 16 | portPair.portSrc); } }; } // namespace std From 216accc4ba3db37428860310583f780d0e769b9f Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 17 Jul 2025 21:12:17 +0300 Subject: [PATCH 12/52] Added documentation. --- Packet++/header/ParserConfig.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 7add8a0b8d..557bb5f8a3 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -10,18 +10,26 @@ namespace pcpp { + /// @brief A structure representing a pair of ports. struct PortPair { + /// @brief Represents a value that indicates any port can be matched. static constexpr uint16_t AnyPort = 0; uint16_t portSrc = AnyPort; ///< Source port number uint16_t portDst = AnyPort; ///< Destination port number + /// @brief Constructs a PortPair with the specified source port and destination port set to AnyPort. + /// @param portSrc Source port number. + /// @return A PortPair with the specified source port and destination port set to AnyPort. constexpr static PortPair fromSrc(uint16_t portSrc) { return { portSrc, AnyPort }; } + /// @brief Constructs a PortPair with the specified destination port and source port set to AnyPort. + /// @param portDst Destination port number. + /// @return A PortPair with the specified destination port and source port set to AnyPort. constexpr static PortPair fromDst(uint16_t portDst) { return { AnyPort, portDst }; @@ -42,6 +50,7 @@ namespace pcpp namespace std { + /// @brief Specialization of std::hash for PortPair. template <> struct hash { size_t operator()(const pcpp::PortPair& portPair) const noexcept @@ -53,6 +62,7 @@ namespace std namespace pcpp { + /// @brief A class that maps port pairs to protocol types. class PortMapper { public: @@ -91,12 +101,15 @@ namespace pcpp return getProtocolByPortPair(port) == protocol; } + /// @brief Creates a default PortMapper with common port mappings. + /// @return A PortMapper instance with default port mappings. static PortMapper makeDefaultPortMapper(); private: std::unordered_map m_PortToProtocolMap; }; + /// @brief A parser configuration that can be used to configure the behavior of the packet parser. struct ParserConfiguration { ParserConfiguration() = default; From deb3e2e008f9ab95db7c31c5a99bbaed75b5c940 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 10:51:25 +0300 Subject: [PATCH 13/52] Added method returning a match matrix instead of a single port. --- Packet++/header/ParserConfig.h | 20 ++++++++++++++++++++ Packet++/src/ParserConfig.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 557bb5f8a3..ff1ce90e08 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -92,6 +93,25 @@ namespace pcpp /// @return The ProtocolType associated with the port, or UnknownProtocol if not found. ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const; + /// @brief Get the protocol mappings that correspond to a specific port pair. + /// + /// The method returns an array of ProtocolType values associated with the port pair. + /// + /// The elements in the array represent the following mappings: + /// Src Port | Dst Port | Match Type + /// - Index 0: Original | Original | Full Match + /// - Index 1: Original | Any Port | Src Port Match + /// - Index 2: Any Port | Original | Dst Port Match + /// + /// If the comparison + /// + /// If a port pair is not found, the corresponding index in the array will contain UnknownProtocol. + /// If a port pair is not mapped to any protocol, the array will contain UnknownProtocol in all indices. + /// + /// @param port The port pair to look up. + /// @return An array of ProtocolType values representing the protocols associated with the port pair. + std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; + /// @brief Check if a port matches a specific protocol type. /// @param port The port number to check. /// @param protocol The ProtocolType to match against. diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index b2c99cb5ef..a247b40f21 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -91,6 +91,33 @@ namespace pcpp return UnknownProtocol; // Return UnknownProtocol if port not found } + std::array PortMapper::getProtocolMappingsMatrixForPortPair(PortPair port) const + { + std::array protocols = { UnknownProtocol, UnknownProtocol, UnknownProtocol }; + // Check for exact match + auto it = m_PortToProtocolMap.find(port); + if (it != m_PortToProtocolMap.end()) + { + protocols[0] = it->second; // Full match + return protocols; + } + + // Check for src port match + it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); + if (it != m_PortToProtocolMap.end()) + { + protocols[1] = it->second; // Src port match + } + + // Check for dst port match + it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); + if (it != m_PortToProtocolMap.end()) + { + protocols[2] = it->second; // Dst port match + } + return protocols; + } + ParserConfiguration ParserConfiguration::makeDefaultConfiguration() { ParserConfiguration config; From 855e7df9df48b48e8b6a7882a737264a6f8d4dc8 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 12:18:51 +0300 Subject: [PATCH 14/52] Added port mappings from TCP Layer. --- Packet++/src/ParserConfig.cpp | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index a247b40f21..d0998660ab 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -10,6 +10,69 @@ namespace pcpp mapper.addPortMapping(PortPair::fromSrc(80), HTTPResponse, false); mapper.addPortMapping(PortPair::fromDst(8080), HTTPRequest, false); mapper.addPortMapping(PortPair::fromSrc(8080), HTTPResponse, false); + + // SSL and TLS port mappings + mapper.addPortMapping(PortPair::fromDst(443), SSL, true); // HTTPS + mapper.addPortMapping(PortPair::fromDst(261), SSL, true); // NSIIOPS + mapper.addPortMapping(PortPair::fromDst(448), SSL, true); // DDM-SSL + mapper.addPortMapping(PortPair::fromDst(465), SSL, true); // SMTPS + mapper.addPortMapping(PortPair::fromDst(563), SSL, true); // NNTPS + mapper.addPortMapping(PortPair::fromDst(614), SSL, true); // SSHELL + mapper.addPortMapping(PortPair::fromDst(636), SSL, true); // LDAPS + mapper.addPortMapping(PortPair::fromDst(989), SSL, true); // FTPS - data + mapper.addPortMapping(PortPair::fromDst(990), SSL, true); // FTPS - control + mapper.addPortMapping(PortPair::fromDst(992), SSL, true); // Telnet over TLS/SSL + mapper.addPortMapping(PortPair::fromDst(993), SSL, true); // IMAPS + mapper.addPortMapping(PortPair::fromDst(994), SSL, true); // IRCS + mapper.addPortMapping(PortPair::fromDst(995), SSL, true); // POP3S + + // SIP port mappings + mapper.addPortMapping(PortPair::fromDst(5060), SIP, true); // SIP over UDP + mapper.addPortMapping(PortPair::fromDst(5061), SIP, true); // SIP over TLS + + // BGP port mappings + mapper.addPortMapping(PortPair::fromDst(179), BGP, true); // BGP over TCP + + // SSH port mappings + mapper.addPortMapping(PortPair::fromDst(22), SSH, true); // SSH over TCP + + // DNS port mappings + mapper.addPortMapping(PortPair::fromDst(53), DNS, true); // DNS over TCP/UDP + mapper.addPortMapping(PortPair::fromDst(5353), DNS, true); // mDNS + mapper.addPortMapping(PortPair::fromDst(5355), DNS, true); // LLMNR + + // Telnet port mappings + mapper.addPortMapping(PortPair::fromDst(23), Telnet, true); // Telnet over TCP + + // FTP port mappings + // FTP Control parses to FTPRequest and FTPResponse, but only one FTP protocol type is defined. + // The specific parsing determined based on if the port is src or dst. + // A port pairing (21, 21) for example is UB. + mapper.addPortMapping(PortPair{ 21, 21 }, UnknownProtocol, false); // Symmetrical connection is UB + mapper.addPortMapping(PortPair::fromSrc(21), FTP, false); // FTP control + mapper.addPortMapping(PortPair::fromDst(21), FTP, false); // FTP control + // TODO: FTP data needs a separate ProtocolType + // mapper.addPortMapping(PortPair::fromDst(20), FTP, false); // FTP data + + // SomeIP port mappings + mapper.addPortMapping(PortPair::fromDst(30490), SomeIP, true); // SomeIP over UDP or TCP + + // Tpkt port mappings + makeDefaultPortMapper().addPortMapping(PortPair::fromDst(102), TPKT, true); // TPKT over TCP + + // Smtp port mappings + // NOTE: Symmetrical mapping but decodes to SMTPRequest and SMTPResponse + // A port pairing (25, 25) for example is UB. + mapper.addPortMapping(PortPair{ 25, 25 }, UnknownProtocol, false); // Symmetrical connection is UB + mapper.addPortMapping(PortPair::fromDst(25), SMTP, true); // SMTP over TCP + mapper.addPortMapping(PortPair::fromDst(587), SMTP, true); // SMTP over TCP (submission) + + // LDAP port mappings + mapper.addPortMapping(PortPair::fromDst(389), LDAP, true); // LDAP over TCP + + // GTP port mappings + mapper.addPortMapping(PortPair::fromDst(2123), GTPv2, true); // GTPv2-C over UDP / TCP + return mapper; } From e5b9f9c8187f14a8d448551d745fbeae749f3300 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 12:24:30 +0300 Subject: [PATCH 15/52] Fixed SIP mappings. --- Packet++/src/ParserConfig.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index d0998660ab..3fa269f7a3 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -27,8 +27,10 @@ namespace pcpp mapper.addPortMapping(PortPair::fromDst(995), SSL, true); // POP3S // SIP port mappings - mapper.addPortMapping(PortPair::fromDst(5060), SIP, true); // SIP over UDP - mapper.addPortMapping(PortPair::fromDst(5061), SIP, true); // SIP over TLS + mapper.addPortMapping(PortPair::fromDst(5060), SIPRequest, false); // SIP over UDP / TCP + mapper.addPortMapping(PortPair::fromSrc(5060), SIPResponse, false); // SIP over UDP / TCP + mapper.addPortMapping(PortPair::fromDst(5061), SIPRequest, false); // SIP over TLS + mapper.addPortMapping(PortPair::fromSrc(5061), SIPResponse, false); // SIP over TLS // BGP port mappings mapper.addPortMapping(PortPair::fromDst(179), BGP, true); // BGP over TCP From 78071f3b66eca987a50283712a03fade0af8b92d Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 12:25:36 +0300 Subject: [PATCH 16/52] Fixed recursion error. --- Packet++/src/ParserConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 3fa269f7a3..73f030212b 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -60,7 +60,7 @@ namespace pcpp mapper.addPortMapping(PortPair::fromDst(30490), SomeIP, true); // SomeIP over UDP or TCP // Tpkt port mappings - makeDefaultPortMapper().addPortMapping(PortPair::fromDst(102), TPKT, true); // TPKT over TCP + mapper.addPortMapping(PortPair::fromDst(102), TPKT, true); // TPKT over TCP // Smtp port mappings // NOTE: Symmetrical mapping but decodes to SMTPRequest and SMTPResponse From ea10b970e41591300d930b11368560ca77e630ff Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 12:25:51 +0300 Subject: [PATCH 17/52] Lint --- Packet++/src/ParserConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 73f030212b..e4fe9afc17 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -51,8 +51,8 @@ namespace pcpp // The specific parsing determined based on if the port is src or dst. // A port pairing (21, 21) for example is UB. mapper.addPortMapping(PortPair{ 21, 21 }, UnknownProtocol, false); // Symmetrical connection is UB - mapper.addPortMapping(PortPair::fromSrc(21), FTP, false); // FTP control - mapper.addPortMapping(PortPair::fromDst(21), FTP, false); // FTP control + mapper.addPortMapping(PortPair::fromSrc(21), FTP, false); // FTP control + mapper.addPortMapping(PortPair::fromDst(21), FTP, false); // FTP control // TODO: FTP data needs a separate ProtocolType // mapper.addPortMapping(PortPair::fromDst(20), FTP, false); // FTP data From a6ba3922219c8b668fe2f6eef8f8dc978e9a5706 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 12:46:30 +0300 Subject: [PATCH 18/52] Fixed warn / update execution order. --- Packet++/src/ParserConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index e4fe9afc17..43b4eec7b5 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -86,12 +86,12 @@ namespace pcpp } auto insertResult = m_PortToProtocolMap.insert({ port, protocol }); - insertResult.first->second = protocol; // Update the protocol if it already exists if (!insertResult.second) { - PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << insertResult.first->second + PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << std::to_string(insertResult.first->second) << ", updating to " << protocol); } + insertResult.first->second = protocol; // Update the protocol if it already exists if (symmetrical && port.portSrc != port.portDst) { From e3c187684a872299afeee4e5dfe80df092b6d704 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 13:02:32 +0300 Subject: [PATCH 19/52] Add port mappings from UDP Layer. --- Packet++/src/ParserConfig.cpp | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 43b4eec7b5..4482700742 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -73,7 +73,39 @@ namespace pcpp mapper.addPortMapping(PortPair::fromDst(389), LDAP, true); // LDAP over TCP // GTP port mappings - mapper.addPortMapping(PortPair::fromDst(2123), GTPv2, true); // GTPv2-C over UDP / TCP + mapper.addPortMapping(PortPair::fromDst(2152), GTPv1, true); // GTP-U over UDP + + // Note: GTP v1 and v2 both utilize port (2123) for GTP-C over UDP / TCP. + // Parser implementations must determine the version based on the packet content. + mapper.addPortMapping(PortPair::fromDst(2123), GTPv2, true); // GTP-C over UDP / TCP (v2 only) + + // DCHP port mappings + mapper.addPortMapping(PortPair{ 67, 67 }, DHCP, true); // DHCP over UDP + mapper.addPortMapping(PortPair{ 68, 67 }, DHCP, true); // DHCP over UDP (client to server) + + // DCHPv6 port mappings + mapper.addPortMapping(PortPair::fromDst(546), DHCPv6, true); // DHCPv6 over UDP + mapper.addPortMapping(PortPair::fromDst(547), DHCPv6, true); // DHCPv6 over UDP + + // VXLAN port mappings + mapper.addPortMapping(PortPair::fromDst(4789), VXLAN, false); // VXLAN over UDP + + // Radius port mappings + mapper.addPortMapping(PortPair::fromDst(1812), Radius, true); // RADIUS over UDP + mapper.addPortMapping(PortPair::fromDst(1813), Radius, true); // RADIUS accounting over UDP + mapper.addPortMapping(PortPair::fromDst(3799), Radius, true); // RADIUS over TCP + + // NTP port mappings + mapper.addPortMapping(PortPair::fromDst(123), NTP, true); // NTP over UDP + + // Wake-on-LAN port mappings + mapper.addPortMapping(PortPair::fromDst(9), WakeOnLan, false); // Wake-on-LAN over UDP + mapper.addPortMapping(PortPair::fromDst(7), WakeOnLan, false); // Wake-on-LAN over UDP + // Would result in Pair (0, 0) which is invalid for the mapper. + // mapper.addPortMapping(PortPair::fromDst(0), WakeOnLan, false); // Wake-on-LAN over UDP (broadcast) + + // WireGuard port mappings + mapper.addPortMapping(PortPair::fromDst(51820), WireGuard, true); // WireGuard over UDP return mapper; } @@ -88,8 +120,8 @@ namespace pcpp auto insertResult = m_PortToProtocolMap.insert({ port, protocol }); if (!insertResult.second) { - PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " << std::to_string(insertResult.first->second) - << ", updating to " << protocol); + PCPP_LOG_WARN("Port " << port << " is already mapped to protocol " + << std::to_string(insertResult.first->second) << ", updating to " << protocol); } insertResult.first->second = protocol; // Update the protocol if it already exists From 8f4f3b5644d35919763299f34f0a940fcbeab89f Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 13:03:21 +0300 Subject: [PATCH 20/52] Lint --- Packet++/header/ParserConfig.h | 10 +++++----- Packet++/src/ParserConfig.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index ff1ce90e08..16cd3019a2 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -94,20 +94,20 @@ namespace pcpp ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const; /// @brief Get the protocol mappings that correspond to a specific port pair. - /// + /// /// The method returns an array of ProtocolType values associated with the port pair. - /// + /// /// The elements in the array represent the following mappings: /// Src Port | Dst Port | Match Type /// - Index 0: Original | Original | Full Match /// - Index 1: Original | Any Port | Src Port Match /// - Index 2: Any Port | Original | Dst Port Match - /// + /// /// If the comparison - /// + /// /// If a port pair is not found, the corresponding index in the array will contain UnknownProtocol. /// If a port pair is not mapped to any protocol, the array will contain UnknownProtocol in all indices. - /// + /// /// @param port The port pair to look up. /// @return An array of ProtocolType values representing the protocols associated with the port pair. std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 4482700742..25fe62e57b 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -79,11 +79,11 @@ namespace pcpp // Parser implementations must determine the version based on the packet content. mapper.addPortMapping(PortPair::fromDst(2123), GTPv2, true); // GTP-C over UDP / TCP (v2 only) - // DCHP port mappings + // DHCP port mappings mapper.addPortMapping(PortPair{ 67, 67 }, DHCP, true); // DHCP over UDP mapper.addPortMapping(PortPair{ 68, 67 }, DHCP, true); // DHCP over UDP (client to server) - // DCHPv6 port mappings + // DHCPv6 port mappings mapper.addPortMapping(PortPair::fromDst(546), DHCPv6, true); // DHCPv6 over UDP mapper.addPortMapping(PortPair::fromDst(547), DHCPv6, true); // DHCPv6 over UDP From f5ff15b53e4e7ae88c18f838419d91159e08d9c9 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 18 Jul 2025 22:21:19 +0300 Subject: [PATCH 21/52] Added member methods to PortPair to create a new pair from only one side. --- Packet++/header/ParserConfig.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 16cd3019a2..1f269aee3e 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -36,6 +36,16 @@ namespace pcpp return { AnyPort, portDst }; } + constexpr PortPair onlyDest() const + { + return fromDst(portDst); + } + + constexpr PortPair onlySrc() const + { + return fromSrc(portSrc); + } + constexpr bool operator==(const PortPair& other) const noexcept { return portSrc == other.portSrc && portDst == other.portDst; From 5d2df595f130b64b04eb4df15c08d17f85a6b57d Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 17:36:31 +0300 Subject: [PATCH 22/52] Extended the mapping to work with protocol families. --- Packet++/header/ParserConfig.h | 20 ++++++++++---------- Packet++/src/ParserConfig.cpp | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 1f269aee3e..cb91c9efc7 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -82,10 +82,10 @@ namespace pcpp /// @brief Add a port mapping to the port mapper. /// @param port The port number to map. - /// @param protocol The ProtocolType to associate with the port. + /// @param protocolFamily The ProtocolTypeFamily to associate with the port. /// @param symmetrical If true, the mapping is considered symmetrical (both src and dst ports are the /// interchangeable). - void addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical = false); + void addPortMapping(PortPair port, ProtocolTypeFamily protocolFamily, bool symmetrical = false); /// @brief Remove a port mapping from the port mapper. /// @param port The port number to remove from the mapping. @@ -100,8 +100,8 @@ namespace pcpp /// /// @param port The port number to look up. /// @param exact If true, only an exact match of the port pair is considered. If false, src or dst port matches - /// @return The ProtocolType associated with the port, or UnknownProtocol if not found. - ProtocolType getProtocolByPortPair(PortPair port, bool exact = true) const; + /// @return The ProtocolTypeFamily associated with the port, or UnknownProtocol if not found. + ProtocolTypeFamily getProtocolByPortPair(PortPair port, bool exact = true) const; /// @brief Get the protocol mappings that correspond to a specific port pair. /// @@ -119,16 +119,16 @@ namespace pcpp /// If a port pair is not mapped to any protocol, the array will contain UnknownProtocol in all indices. /// /// @param port The port pair to look up. - /// @return An array of ProtocolType values representing the protocols associated with the port pair. - std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; + /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. + std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; /// @brief Check if a port matches a specific protocol type. /// @param port The port number to check. - /// @param protocol The ProtocolType to match against. + /// @param protocol The ProtocolTypeFamily to match against. /// @return True if the port matches the protocol type, false otherwise. - bool matchesPortAndProtocol(PortPair port, ProtocolType protocol) const + bool matchesPortAndProtocol(PortPair port, ProtocolTypeFamily protocolFamily) const { - return getProtocolByPortPair(port) == protocol; + return getProtocolByPortPair(port) == protocolFamily; } /// @brief Creates a default PortMapper with common port mappings. @@ -136,7 +136,7 @@ namespace pcpp static PortMapper makeDefaultPortMapper(); private: - std::unordered_map m_PortToProtocolMap; + std::unordered_map m_PortToProtocolMap; }; /// @brief A parser configuration that can be used to configure the behavior of the packet parser. diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 25fe62e57b..d9cb48ae7f 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -110,7 +110,7 @@ namespace pcpp return mapper; } - void PortMapper::addPortMapping(PortPair port, ProtocolType protocol, bool symmetrical) + void PortMapper::addPortMapping(PortPair port, ProtocolTypeFamily protocol, bool symmetrical) { if (port == PortPair()) { @@ -153,7 +153,7 @@ namespace pcpp } } - ProtocolType PortMapper::getProtocolByPortPair(PortPair port, bool exact) const + ProtocolTypeFamily PortMapper::getProtocolByPortPair(PortPair port, bool exact) const { // Order of precedence: // 1. Check for exact match of port pair @@ -188,9 +188,9 @@ namespace pcpp return UnknownProtocol; // Return UnknownProtocol if port not found } - std::array PortMapper::getProtocolMappingsMatrixForPortPair(PortPair port) const + std::array PortMapper::getProtocolMappingsMatrixForPortPair(PortPair port) const { - std::array protocols = { UnknownProtocol, UnknownProtocol, UnknownProtocol }; + std::array protocols = { UnknownProtocol, UnknownProtocol, UnknownProtocol }; // Check for exact match auto it = m_PortToProtocolMap.find(port); if (it != m_PortToProtocolMap.end()) From 5a60efa5fe615b06e51de8905002e7e1e346d254 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 17:43:54 +0300 Subject: [PATCH 23/52] Updated port mapping for GTPv2 to GTP --- Packet++/src/ParserConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index d9cb48ae7f..8c792fd4e5 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -77,7 +77,7 @@ namespace pcpp // Note: GTP v1 and v2 both utilize port (2123) for GTP-C over UDP / TCP. // Parser implementations must determine the version based on the packet content. - mapper.addPortMapping(PortPair::fromDst(2123), GTPv2, true); // GTP-C over UDP / TCP (v2 only) + mapper.addPortMapping(PortPair::fromDst(2123), GTP, true); // GTP-C over UDP / TCP (v2 only) // DHCP port mappings mapper.addPortMapping(PortPair{ 67, 67 }, DHCP, true); // DHCP over UDP From e77dc466229cc1fb12508d3291925f971d1e1024 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 17:56:22 +0300 Subject: [PATCH 24/52] Added utility function for quering port pair matrix. --- Packet++/header/ParserConfig.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index cb91c9efc7..5cc30637ae 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -122,6 +122,18 @@ namespace pcpp /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; + /// @brief Get the protocol mappings that correspond to a specific port pair. + /// + /// See `getProtocolMappingsMatrixForPortPair(PortPair port)` for details. + /// + /// @param portSrc The source port number. + /// @param portDst The destination port number. + /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. + std::array getProtocolMappingsMatrixForPortPair(uint16_t portSrc, uint16_t portDst) const + { + return getProtocolMappingsMatrixForPortPair({ portSrc, portDst }); + } + /// @brief Check if a port matches a specific protocol type. /// @param port The port number to check. /// @param protocol The ProtocolTypeFamily to match against. From 90bb41068175c2193dc24b03192c687e0ea9f8e7 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 17:57:28 +0300 Subject: [PATCH 25/52] Added todo. --- Packet++/header/ParserConfig.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 5cc30637ae..272452b0b7 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -148,6 +148,7 @@ namespace pcpp static PortMapper makeDefaultPortMapper(); private: + // todo: A flat map might be more performant here, due to cache locality. std::unordered_map m_PortToProtocolMap; }; From 18f02a213b8c05d14452fb955aa72f18a189da87 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 18:24:46 +0300 Subject: [PATCH 26/52] Merged SIP port rules to SIP family. --- Packet++/src/ParserConfig.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 8c792fd4e5..ed66c10e2b 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -27,10 +27,8 @@ namespace pcpp mapper.addPortMapping(PortPair::fromDst(995), SSL, true); // POP3S // SIP port mappings - mapper.addPortMapping(PortPair::fromDst(5060), SIPRequest, false); // SIP over UDP / TCP - mapper.addPortMapping(PortPair::fromSrc(5060), SIPResponse, false); // SIP over UDP / TCP - mapper.addPortMapping(PortPair::fromDst(5061), SIPRequest, false); // SIP over TLS - mapper.addPortMapping(PortPair::fromSrc(5061), SIPResponse, false); // SIP over TLS + mapper.addPortMapping(PortPair::fromDst(5060), SIP, true); // SIP over UDP / TCP + mapper.addPortMapping(PortPair::fromDst(5061), SIP, true); // SIP over TLS // BGP port mappings mapper.addPortMapping(PortPair::fromDst(179), BGP, true); // BGP over TCP From 08f67cdaf7f570b9685a9f98487e90b2d9fb2913 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 19:32:25 +0300 Subject: [PATCH 27/52] Updated UDPLayer to utilize the dynamic protocol mapper. --- Packet++/src/UdpLayer.cpp | 169 ++++++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 42 deletions(-) diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index f4a1274c4f..6b1489edda 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -100,52 +100,137 @@ namespace pcpp uint8_t* udpData = m_Data + sizeof(udphdr); size_t udpDataLen = m_DataLen - sizeof(udphdr); - if (DhcpLayer::isDhcpPorts(portSrc, portDst)) - m_NextLayer = new DhcpLayer(udpData, udpDataLen, this, m_Packet); - else if (VxlanLayer::isVxlanPort(portDst)) - m_NextLayer = new VxlanLayer(udpData, udpDataLen, this, m_Packet); - else if (DnsLayer::isDataValid(udpData, udpDataLen) && - (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) - m_NextLayer = new DnsLayer(udpData, udpDataLen, this, m_Packet); - else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) + // Queries the port mapper for protocol mappings based on the source and destination ports + // The returned array protocol family for exact match, source only match, destination only match. + // The first protocol family that passes secondary validation (if any) will be used to construct the next layer. + auto const portMatrix = config.portMapper.getProtocolMappingsMatrixForPortPair(portSrc, portDst); + + for (auto protoFamily : portMatrix) { - if (SipRequestFirstLine::parseMethod((char*)udpData, udpDataLen) != SipRequestLayer::SipMethodUnknown) - m_NextLayer = new SipRequestLayer(udpData, udpDataLen, this, m_Packet); - else if (SipResponseFirstLine::parseStatusCode((char*)udpData, udpDataLen) != - SipResponseLayer::SipStatusCodeUnknown && - SipResponseFirstLine::parseVersion((char*)udpData, udpDataLen) != "") - m_NextLayer = new SipResponseLayer(udpData, udpDataLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); + // If the protocol family is UnknownProtocol, skip all other checks + if (protoFamily == UnknownProtocol) + continue; + + switch (protoFamily) + { + case DHCP: + { + constructNextLayer(udpData, udpDataLen, m_Packet); + break; + } + case VXLAN: + { + constructNextLayer(udpData, udpDataLen, m_Packet); + break; + } + case DNS: + { + if (DnsLayer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case SIPRequest: + case SIPResponse: + case SIP: + { + if (SipRequestFirstLine::parseMethod((char*)udpData, udpDataLen) != SipRequestLayer::SipMethodUnknown) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + else if (SipResponseFirstLine::parseStatusCode((char*)udpData, udpDataLen) != + SipResponseLayer::SipStatusCodeUnknown && + SipResponseFirstLine::parseVersion((char*)udpData, udpDataLen) != "") + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + else + { + // todo: If the data is not a valid SIP request or response, should be instead try to continue + // matching? + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case Radius: + { + if (RadiusLayer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case GTPv1: + case GTPv2: + case GTP: + { + // GTP can be either v1 or v2 + if (GtpV1Layer::isGTPv1(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + else if (GtpV2Layer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case DHCPv6: + { + if (DhcpV6Layer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case NTP: + { + if (NtpLayer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case SomeIP: + { + setNextLayer(SomeIpLayer::parseSomeIpLayer(udpData, udpDataLen, this, m_Packet)); + break; + } + case WakeOnLan: + { + if (WakeOnLanLayer::isDataValid(udpData, udpDataLen)) + { + constructNextLayer(udpData, udpDataLen, m_Packet); + } + break; + } + case WireGuard: + { + if (WireGuardLayer::isDataValid(udpData, udpDataLen)) + { + setNextLayer(WireGuardLayer::parseWireGuardLayer(udpData, udpDataLen, this, m_Packet)); + if (!m_NextLayer) + { + // If parsing failed, fallback to PayloadLayer + // todo: Maybe continue matching partial matches instead? + constructNextLayer(udpData, udpDataLen, m_Packet); + } + } + break; + } + } + + // If we already have a next layer, we don't need to parse further + if (hasNextLayer()) + break; } - else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) && - RadiusLayer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new RadiusLayer(udpData, udpDataLen, this, m_Packet); - else if ((GtpV1Layer::isGTPv1Port(portDst) || GtpV1Layer::isGTPv1Port(portSrc)) && - GtpV1Layer::isGTPv1(udpData, udpDataLen)) - m_NextLayer = new GtpV1Layer(udpData, udpDataLen, this, m_Packet); - else if ((GtpV2Layer::isGTPv2Port(portDst) || GtpV2Layer::isGTPv2Port(portSrc)) && - GtpV2Layer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new GtpV2Layer(udpData, udpDataLen, this, m_Packet); - else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && - (DhcpV6Layer::isDataValid(udpData, udpDataLen))) - m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); - else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && - NtpLayer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); - else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) - m_NextLayer = SomeIpLayer::parseSomeIpLayer(udpData, udpDataLen, this, m_Packet); - else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) - m_NextLayer = new WakeOnLanLayer(udpData, udpDataLen, this, m_Packet); - else if ((WireGuardLayer::isWireGuardPorts(portDst, portSrc) && - WireGuardLayer::isDataValid(udpData, udpDataLen))) + + if (!hasNextLayer()) { - m_NextLayer = WireGuardLayer::parseWireGuardLayer(udpData, udpDataLen, this, m_Packet); - if (!m_NextLayer) - m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); + // No specific layer matched, set as PayloadLayer + constructNextLayer(udpData, udpDataLen, m_Packet); } - else - m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); } void UdpLayer::computeCalculateFields() From d6cdddd59bcd607ee8023aee90b7292a5abc1799 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 19:50:58 +0300 Subject: [PATCH 28/52] Fixed SomeIP test --- Tests/Packet++Test/Tests/SomeIpTests.cpp | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Tests/Packet++Test/Tests/SomeIpTests.cpp b/Tests/Packet++Test/Tests/SomeIpTests.cpp index 216b9b34b0..818e9f0b5a 100644 --- a/Tests/Packet++Test/Tests/SomeIpTests.cpp +++ b/Tests/Packet++Test/Tests/SomeIpTests.cpp @@ -22,6 +22,34 @@ class SomeIpTeardown } }; +class SomeIpScopedPortRegistration +{ +public: + SomeIpScopedPortRegistration(pcpp::PortPair portPair) : m_RegisteredPort(portPair) + { + auto& portMapper = pcpp::ParserConfiguration::getDefault().portMapper; + m_PreviousMapping = portMapper.getProtocolByPortPair(m_RegisteredPort, true); + portMapper.addPortMapping(m_RegisteredPort, pcpp::SomeIP, true); + } + ~SomeIpScopedPortRegistration() + { + auto& portMapper = pcpp::ParserConfiguration::getDefault().portMapper; + + if (m_PreviousMapping != pcpp::UnknownProtocol) + { + portMapper.addPortMapping(m_RegisteredPort, m_PreviousMapping, true); + } + else + { + portMapper.removePortMapping(m_RegisteredPort, true); + } + } + +private: + pcpp::PortPair m_RegisteredPort; + pcpp::ProtocolTypeFamily m_PreviousMapping; +}; + PTF_TEST_CASE(SomeIpPortTest) { // cppcheck-suppress unusedVariable @@ -50,6 +78,9 @@ PTF_TEST_CASE(SomeIpParsingTest) // cppcheck-suppress unusedVariable SomeIpTeardown someIpTeardown; + + // Add port mapping for SOME/IP + SomeIpScopedPortRegistration someIpPortRegistration(pcpp::PortPair::fromDst(29180)); pcpp::SomeIpLayer::addSomeIpPort(29180); READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/someip.dat"); @@ -122,6 +153,9 @@ PTF_TEST_CASE(SomeIpParsingTest) PTF_ASSERT_EQUAL(someIpLayer2_2->getPduPayload()[19], 0x14); PTF_ASSERT_EQUAL(someIpLayer2_2->toString(), "SOME/IP Layer, Service ID: 0x6060, Method ID: 0x410d, Length: 28"); PTF_ASSERT_NULL(someIpLayer2_2->getNextLayer()); + + // Remove port mapping for SOME/IP + pcpp::ParserConfiguration::getDefault().portMapper.removePortMapping(pcpp::PortPair::fromDst(29180), true); } PTF_TEST_CASE(SomeIpCreationTest) @@ -183,6 +217,7 @@ PTF_TEST_CASE(SomeIpTpParsingTest) // cppcheck-suppress unusedVariable SomeIpTeardown someIpTeardown; + SomeIpScopedPortRegistration someIpPortRegistration(pcpp::PortPair::fromDst(16832)); pcpp::SomeIpLayer::addSomeIpPort(16832); READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/SomeIpTp1.dat"); From d134241cad46b44e9ed64b6da078bb9a5c372411 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 19:51:21 +0300 Subject: [PATCH 29/52] Lint --- Packet++/header/ParserConfig.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 272452b0b7..37cf4b9039 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -123,9 +123,9 @@ namespace pcpp std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; /// @brief Get the protocol mappings that correspond to a specific port pair. - /// + /// /// See `getProtocolMappingsMatrixForPortPair(PortPair port)` for details. - /// + /// /// @param portSrc The source port number. /// @param portDst The destination port number. /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. From 800789f442a102df929060fdae87a16ab05c3b32 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 19:54:03 +0300 Subject: [PATCH 30/52] Fix docs. --- Packet++/header/ParserConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 37cf4b9039..d331bb3604 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -136,7 +136,7 @@ namespace pcpp /// @brief Check if a port matches a specific protocol type. /// @param port The port number to check. - /// @param protocol The ProtocolTypeFamily to match against. + /// @param protocolFamily The ProtocolTypeFamily to match against. /// @return True if the port matches the protocol type, false otherwise. bool matchesPortAndProtocol(PortPair port, ProtocolTypeFamily protocolFamily) const { From a23b41bf5bccf7d55d98ef4c1f16b1c8204e0624 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 20:02:59 +0300 Subject: [PATCH 31/52] Fix explicit ctor. --- Tests/Packet++Test/Tests/SomeIpTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Packet++Test/Tests/SomeIpTests.cpp b/Tests/Packet++Test/Tests/SomeIpTests.cpp index 818e9f0b5a..edac94be0e 100644 --- a/Tests/Packet++Test/Tests/SomeIpTests.cpp +++ b/Tests/Packet++Test/Tests/SomeIpTests.cpp @@ -25,7 +25,7 @@ class SomeIpTeardown class SomeIpScopedPortRegistration { public: - SomeIpScopedPortRegistration(pcpp::PortPair portPair) : m_RegisteredPort(portPair) + explicit SomeIpScopedPortRegistration(pcpp::PortPair portPair) : m_RegisteredPort(portPair) { auto& portMapper = pcpp::ParserConfiguration::getDefault().portMapper; m_PreviousMapping = portMapper.getProtocolByPortPair(m_RegisteredPort, true); From 6fe00cd401be231b8d18a99003e25aef70dad2b9 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 20:30:06 +0300 Subject: [PATCH 32/52] Docs fix. --- Packet++/header/ParserConfig.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index d331bb3604..bf85e501d4 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -113,8 +113,6 @@ namespace pcpp /// - Index 1: Original | Any Port | Src Port Match /// - Index 2: Any Port | Original | Dst Port Match /// - /// If the comparison - /// /// If a port pair is not found, the corresponding index in the array will contain UnknownProtocol. /// If a port pair is not mapped to any protocol, the array will contain UnknownProtocol in all indices. /// From 25bc58af0ce264887dc9d7a73e08b728d28e521a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 20:59:59 +0300 Subject: [PATCH 33/52] Changed getProtocolByPortPair to only check exact matches. Use `getProtocolMappingsMatrixForPortPair` for partial matches. --- Packet++/header/ParserConfig.h | 7 +------ Packet++/src/ParserConfig.cpp | 28 ++-------------------------- 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index bf85e501d4..75bf4130ee 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -94,14 +94,9 @@ namespace pcpp void removePortMapping(PortPair port, bool symmetrical = false); /// @brief Get the protocol type associated with a specific port. - /// - /// The method checks for an exact match of the port pair first. - /// If `exact` is false, it will also check for a match on either the source or destination port. - /// /// @param port The port number to look up. - /// @param exact If true, only an exact match of the port pair is considered. If false, src or dst port matches /// @return The ProtocolTypeFamily associated with the port, or UnknownProtocol if not found. - ProtocolTypeFamily getProtocolByPortPair(PortPair port, bool exact = true) const; + ProtocolTypeFamily getProtocolByPortPair(PortPair port) const; /// @brief Get the protocol mappings that correspond to a specific port pair. /// diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index ed66c10e2b..86b71767fb 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -151,39 +151,15 @@ namespace pcpp } } - ProtocolTypeFamily PortMapper::getProtocolByPortPair(PortPair port, bool exact) const + ProtocolTypeFamily PortMapper::getProtocolByPortPair(PortPair port) const { - // Order of precedence: - // 1. Check for exact match of port pair - // 1.a If exact is true, return the protocol type if found, go to step 4 if not found - // 2. If not found, check for src port match - // 3. If not found, check for dst port match - // 4. If still not found, return UnknownProtocol - auto it = m_PortToProtocolMap.find(port); if (it != m_PortToProtocolMap.end()) { return it->second; } - if (exact) - return UnknownProtocol; // Return UnknownProtocol if exact match not found - - // Check for src port match - it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); - if (it != m_PortToProtocolMap.end()) - { - return it->second; - } - - // Check for dst port match - it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); - if (it != m_PortToProtocolMap.end()) - { - return it->second; - } - - return UnknownProtocol; // Return UnknownProtocol if port not found + return UnknownProtocol; // Return UnknownProtocol if exact match not found } std::array PortMapper::getProtocolMappingsMatrixForPortPair(PortPair port) const From 27e79425f3e978ad6eac0170124bde00999d730c Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 20 Jul 2025 21:15:06 +0300 Subject: [PATCH 34/52] todo change --- Packet++/header/ParserConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 75bf4130ee..3070b1fddc 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -141,7 +141,7 @@ namespace pcpp static PortMapper makeDefaultPortMapper(); private: - // todo: A flat map might be more performant here, due to cache locality. + // todo: profile lookup performance. std::unordered_map m_PortToProtocolMap; }; From ef5ca859d7ae2807636685fcaf7497cda30de1a7 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Tue, 22 Jul 2025 12:28:11 +0300 Subject: [PATCH 35/52] Fixed leftover parameter. --- Tests/Packet++Test/Tests/SomeIpTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Packet++Test/Tests/SomeIpTests.cpp b/Tests/Packet++Test/Tests/SomeIpTests.cpp index edac94be0e..ce3d300d4b 100644 --- a/Tests/Packet++Test/Tests/SomeIpTests.cpp +++ b/Tests/Packet++Test/Tests/SomeIpTests.cpp @@ -28,7 +28,7 @@ class SomeIpScopedPortRegistration explicit SomeIpScopedPortRegistration(pcpp::PortPair portPair) : m_RegisteredPort(portPair) { auto& portMapper = pcpp::ParserConfiguration::getDefault().portMapper; - m_PreviousMapping = portMapper.getProtocolByPortPair(m_RegisteredPort, true); + m_PreviousMapping = portMapper.getProtocolByPortPair(m_RegisteredPort); portMapper.addPortMapping(m_RegisteredPort, pcpp::SomeIP, true); } ~SomeIpScopedPortRegistration() From 067364d6f34ead60d89087a85b74bfb77b5f2dac Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Tue, 22 Jul 2025 23:11:08 +0300 Subject: [PATCH 36/52] Expanded PortPair to allow port 0 as a valid port. --- Packet++/header/ParserConfig.h | 169 ++++++++++++++++++++++++++++----- Packet++/src/ParserConfig.cpp | 14 ++- 2 files changed, 149 insertions(+), 34 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 3070b1fddc..db4dca3015 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -11,14 +11,28 @@ namespace pcpp { - /// @brief A structure representing a pair of ports. - struct PortPair + /// @brief Represents a pair of ports, typically used for network protocol matching. + class PortPair { + public: /// @brief Represents a value that indicates any port can be matched. - static constexpr uint16_t AnyPort = 0; + static constexpr struct AnyPortWildcard + { + } AnyPort = {}; + + constexpr PortPair() = default; + + constexpr PortPair(uint16_t portSrc, uint16_t portDst) + : m_PortSrc(portSrc), m_PortDst(portDst), m_PortSrcSet(true), m_PortDstSet(true) + {} - uint16_t portSrc = AnyPort; ///< Source port number - uint16_t portDst = AnyPort; ///< Destination port number + constexpr PortPair(uint16_t portSrc, AnyPortWildcard) + : m_PortSrc(portSrc), m_PortDst(0), m_PortSrcSet(true), m_PortDstSet(false) + {} + + constexpr PortPair(AnyPortWildcard, uint16_t portDst) + : m_PortSrc(0), m_PortDst(portDst), m_PortSrcSet(false), m_PortDstSet(true) + {} /// @brief Constructs a PortPair with the specified source port and destination port set to AnyPort. /// @param portSrc Source port number. @@ -36,43 +50,118 @@ namespace pcpp return { AnyPort, portDst }; } - constexpr PortPair onlyDest() const + /// @brief Returns a PortPair with the source port replaced by AnyPort wildcard. + /// @return A new PortPair with the source port set to AnyPort. + constexpr PortPair withAnySrc() const + { + return fromDst(m_PortDst); + } + + /// @brief Returns a PortPair with the destination port replaced by AnyPort wildcard. + /// @return A new PortPair with the destination port set to AnyPort. + constexpr PortPair withAnyDst() const + { + return fromSrc(m_PortSrc); + } + + /// @brief Returns a PortPair with the source and destination ports reversed. + /// @return A new PortPair with the source and destination ports swapped. + constexpr PortPair withSwappedPorts() const noexcept + { + PortPair reversed; + reversed.m_PortSrc = m_PortDst; + reversed.m_PortSrcSet = m_PortDstSet; + reversed.m_PortDst = m_PortSrc; + reversed.m_PortDstSet = m_PortSrcSet; + return reversed; + } + + constexpr bool isSrcPortSet() const noexcept + { + return m_PortSrcSet; + } + + constexpr bool isDstPortSet() const noexcept + { + return m_PortDstSet; + } + + constexpr bool hasWildcards() const noexcept + { + return !(isSrcPortSet() && isDstPortSet()); + } + + constexpr uint16_t portSrc() const noexcept + { + return m_PortSrc; + } + + constexpr uint16_t portDst() const noexcept + { + return m_PortDst; + } + + constexpr void setSrcPort(uint16_t portSrc) noexcept + { + m_PortSrc = portSrc; + m_PortSrcSet = true; + } + + constexpr void setSrcPort(AnyPortWildcard) noexcept { - return fromDst(portDst); + m_PortSrc = 0; + m_PortSrcSet = false; } - constexpr PortPair onlySrc() const + constexpr void setDstPort(uint16_t portDst) noexcept { - return fromSrc(portSrc); + m_PortDst = portDst; + m_PortDstSet = true; + } + + constexpr void setDstPort(AnyPortWildcard) noexcept + { + m_PortDst = 0; + m_PortDstSet = false; } constexpr bool operator==(const PortPair& other) const noexcept { - return portSrc == other.portSrc && portDst == other.portDst; + return m_PortSrc == other.m_PortSrc && m_PortDst == other.m_PortDst; } friend std::ostream& operator<<(std::ostream& os, PortPair const pair) { - os << "PortPair(src: " << pair.portSrc << ", dst: " << pair.portDst << ")"; + os << "PortPair(src: "; + if (pair.m_PortSrcSet) + { + os << pair.m_PortSrc; + } + else + { + os << "AnyPort"; + } + + os << ", dst: "; + if (pair.m_PortDstSet) + { + os << pair.m_PortDst; + } + else + { + os << "AnyPort"; + } + os << ')'; return os; } - }; -} // namespace pcpp -namespace std -{ - /// @brief Specialization of std::hash for PortPair. - template <> struct hash - { - size_t operator()(const pcpp::PortPair& portPair) const noexcept - { - return std::hash()(static_cast(portPair.portDst) << 16 | portPair.portSrc); - } + private: + uint16_t m_PortSrc = 0; ///< Source port number + uint16_t m_PortDst = 0; ///< Destination port number + bool m_PortSrcSet = false; ///< Indicates if the src port is set, on false consider the port as wildcard + bool m_PortDstSet = false; ///< Indicates if the dst port is set, on false consider the port as wildcard }; -} // namespace std -namespace pcpp -{ /// @brief A class that maps port pairs to protocol types. class PortMapper { @@ -141,8 +230,36 @@ namespace pcpp static PortMapper makeDefaultPortMapper(); private: + struct PackedPortPairHasher + { + std::size_t operator()(const PortPair& portPair) const noexcept + { + return static_cast(splitMix64(encodePair(portPair))); + } + + constexpr uint64_t encodePair(const PortPair& portPair) const noexcept + { + // Encodes the port pair as a uint64_t + // 30 bits unused, 2 bits wildcard flags, 16 bits for src port, 16 bits for dst port, + uint64_t srcPort = portPair.portSrc(); + uint64_t dstPort = static_cast(portPair.portDst()) << 16; + uint64_t srcPortSet = static_cast(portPair.isSrcPortSet() ? 1 : 0) << 32; + uint64_t dstPortSet = static_cast(portPair.isDstPortSet() ? 1 : 0) << 33; + + return srcPort | dstPort | srcPortSet | dstPortSet; + } + + constexpr uint64_t splitMix64(uint64_t key) const noexcept + { + uint64_t z = key + 0x9E3779B97F4A7C15ULL; + z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL; + z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL; + return z ^ (z >> 31); + } + }; + // todo: profile lookup performance. - std::unordered_map m_PortToProtocolMap; + std::unordered_map m_PortToProtocolMap; }; /// @brief A parser configuration that can be used to configure the behavior of the packet parser. diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 86b71767fb..8a13d445c4 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -123,11 +123,10 @@ namespace pcpp } insertResult.first->second = protocol; // Update the protocol if it already exists - if (symmetrical && port.portSrc != port.portDst) + if (symmetrical && (port.hasWildcards() || port.portSrc() != port.portDst())) { // Add the symmetrical mapping - PortPair symmetricalPort = { port.portDst, port.portSrc }; - addPortMapping(symmetricalPort, protocol, false); + addPortMapping(port.withSwappedPorts(), protocol, false); } } @@ -143,11 +142,10 @@ namespace pcpp PCPP_LOG_DEBUG("Port " << port << " not found in port mapper, nothing to remove"); } - if (symmetrical && port.portSrc != port.portDst) + if (symmetrical && (port.hasWildcards() || port.portSrc() != port.portDst())) { // Remove the symmetrical mapping - PortPair symmetricalPort = { port.portDst, port.portSrc }; - removePortMapping(symmetricalPort, false); + removePortMapping(port.withSwappedPorts(), false); } } @@ -174,14 +172,14 @@ namespace pcpp } // Check for src port match - it = m_PortToProtocolMap.find(PortPair::fromSrc(port.portSrc)); + it = m_PortToProtocolMap.find(port.withAnyDst()); if (it != m_PortToProtocolMap.end()) { protocols[1] = it->second; // Src port match } // Check for dst port match - it = m_PortToProtocolMap.find(PortPair::fromDst(port.portDst)); + it = m_PortToProtocolMap.find(port.withAnySrc()); if (it != m_PortToProtocolMap.end()) { protocols[2] = it->second; // Dst port match From a89eadb93feb0760512fa1ab7dfd8dff5fca8546 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 24 Jul 2025 18:06:29 +0300 Subject: [PATCH 37/52] Fixed PortPair equalify operator. --- Packet++/header/ParserConfig.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index db4dca3015..555eb500a8 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -127,7 +127,8 @@ namespace pcpp constexpr bool operator==(const PortPair& other) const noexcept { - return m_PortSrc == other.m_PortSrc && m_PortDst == other.m_PortDst; + return comparePort(m_PortSrc, other.m_PortSrc, m_PortSrcSet, other.m_PortSrcSet) && + comparePort(m_PortDst, other.m_PortDst, m_PortDstSet, other.m_PortDstSet); } friend std::ostream& operator<<(std::ostream& os, PortPair const pair) @@ -156,6 +157,19 @@ namespace pcpp } private: + constexpr bool comparePort(uint16_t port1, uint16_t port2, bool isSet1, bool isSet2) const noexcept + { + // If both ports are set, compare them directly + // If one of the ports is not set, return false. + // If both ports are not set, return true. + + if (isSet1 && isSet2) + { + return port1 == port2; + } + return !isSet1 && !isSet2; // Both ports are wildcard + } + uint16_t m_PortSrc = 0; ///< Source port number uint16_t m_PortDst = 0; ///< Destination port number bool m_PortSrcSet = false; ///< Indicates if the src port is set, on false consider the port as wildcard From bd3ca9a9231535567de3f04e8c823c9c54b3f8db Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 24 Jul 2025 18:06:57 +0300 Subject: [PATCH 38/52] Added inequality operator. --- Packet++/header/ParserConfig.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 555eb500a8..a706484239 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -131,6 +131,11 @@ namespace pcpp comparePort(m_PortDst, other.m_PortDst, m_PortDstSet, other.m_PortDstSet); } + constexpr bool operator!=(const PortPair& other) const noexcept + { + return !(*this == other); + } + friend std::ostream& operator<<(std::ostream& os, PortPair const pair) { os << "PortPair(src: "; From 1dd6bbe7bd17853318d4def43afe92e95efe721a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 24 Jul 2025 18:07:52 +0300 Subject: [PATCH 39/52] Enabled WakeOnLan port 0 mapping. --- Packet++/src/ParserConfig.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 8a13d445c4..2f4831dbcc 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -99,8 +99,7 @@ namespace pcpp // Wake-on-LAN port mappings mapper.addPortMapping(PortPair::fromDst(9), WakeOnLan, false); // Wake-on-LAN over UDP mapper.addPortMapping(PortPair::fromDst(7), WakeOnLan, false); // Wake-on-LAN over UDP - // Would result in Pair (0, 0) which is invalid for the mapper. - // mapper.addPortMapping(PortPair::fromDst(0), WakeOnLan, false); // Wake-on-LAN over UDP (broadcast) + mapper.addPortMapping(PortPair::fromDst(0), WakeOnLan, false); // Wake-on-LAN over UDP (broadcast) // WireGuard port mappings mapper.addPortMapping(PortPair::fromDst(51820), WireGuard, true); // WireGuard over UDP From 6da2493b144e7831232832b1c1dcdbb94170321f Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 24 Jul 2025 18:10:57 +0300 Subject: [PATCH 40/52] Changed comparePort to static helper. --- Packet++/header/ParserConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index a706484239..b2c32de57b 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -162,7 +162,7 @@ namespace pcpp } private: - constexpr bool comparePort(uint16_t port1, uint16_t port2, bool isSet1, bool isSet2) const noexcept + constexpr static bool comparePort(uint16_t port1, uint16_t port2, bool isSet1, bool isSet2) noexcept { // If both ports are set, compare them directly // If one of the ports is not set, return false. From 4be73ef27753d8e44e067edbed70b6087acb1517 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 10:56:52 +0300 Subject: [PATCH 41/52] Fixed withAnySrc and withAnyDst not respecting port set flags. --- Packet++/header/ParserConfig.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index b2c32de57b..7cce9fc598 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -54,14 +54,24 @@ namespace pcpp /// @return A new PortPair with the source port set to AnyPort. constexpr PortPair withAnySrc() const { - return fromDst(m_PortDst); + if (m_PortDstSet) + { + return fromDst(m_PortDst); + } + + return PortPair{ AnyPort, AnyPort }; } /// @brief Returns a PortPair with the destination port replaced by AnyPort wildcard. /// @return A new PortPair with the destination port set to AnyPort. constexpr PortPair withAnyDst() const { - return fromSrc(m_PortSrc); + if (m_PortSrcSet) + { + return fromSrc(m_PortSrc); + } + + return PortPair{ AnyPort, AnyPort }; } /// @brief Returns a PortPair with the source and destination ports reversed. From 96297b5b3c9e82ed2478f218a541c391592f2248 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 10:57:54 +0300 Subject: [PATCH 42/52] Added constructor that takes anyport + anyport. --- Packet++/header/ParserConfig.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 7cce9fc598..604709f744 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -21,6 +21,8 @@ namespace pcpp } AnyPort = {}; constexpr PortPair() = default; + constexpr PortPair(AnyPortWildcard, AnyPortWildcard) : PortPair() + {} constexpr PortPair(uint16_t portSrc, uint16_t portDst) : m_PortSrc(portSrc), m_PortDst(portDst), m_PortSrcSet(true), m_PortDstSet(true) From d82845269c2dc3302e6a5da7f6d856c0642323f5 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 10 Aug 2025 08:53:00 +0300 Subject: [PATCH 43/52] Fix parseNextLayer params in DoIP layer. --- Packet++/header/DoIpLayer.h | 2 +- Packet++/src/DoIpLayer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index 04248833f9..da834f9ee9 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -621,7 +621,7 @@ namespace pcpp // implement abstract methods /// parse UDS layer - void parseNextLayer() override; + void parseNextLayer(ParserConfiguration const& config) override; /// @return The size of @ref doiphdr + attached fields length size_t getHeaderLen() const override diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index 2944888109..a1238d9149 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -382,7 +382,7 @@ namespace pcpp setPayloadLength(length); } - void DoIpLayer::parseNextLayer() + void DoIpLayer::parseNextLayer(ParserConfiguration const& config) { if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE) { From c0b6ebdcaa27be96df56e7f769bb88016192e941 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 10 Aug 2025 09:06:27 +0300 Subject: [PATCH 44/52] Added DoIP mappings to default mapper. --- Packet++/src/ParserConfig.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index 2f4831dbcc..f3d9553075 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -96,6 +96,10 @@ namespace pcpp // NTP port mappings mapper.addPortMapping(PortPair::fromDst(123), NTP, true); // NTP over UDP + // DoIP port mappings + mapper.addPortMapping(PortPair::fromDst(13400), DOIP, true); // DoIP over TCP/UDP + mapper.addPortMapping(PortPair::fromDst(3496), DOIP, true); // DoIP over TLS + // Wake-on-LAN port mappings mapper.addPortMapping(PortPair::fromDst(9), WakeOnLan, false); // Wake-on-LAN over UDP mapper.addPortMapping(PortPair::fromDst(7), WakeOnLan, false); // Wake-on-LAN over UDP From be81263da65cb4c1dc1bab0abcd4d2fb0dc94b3a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 10 Aug 2025 10:13:02 +0300 Subject: [PATCH 45/52] Added dedicated benchmark target. --- Benchmarks/CMakeLists.txt | 23 ++++ .../Benchmarks/PortMapperBench.cpp | 100 ++++++++++++++++++ Benchmarks/Packet++Bench/CMakeLists.txt | 8 ++ Benchmarks/Packet++Bench/main.cpp | 12 +++ CMakeLists.txt | 5 + 5 files changed, 148 insertions(+) create mode 100644 Benchmarks/CMakeLists.txt create mode 100644 Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp create mode 100644 Benchmarks/Packet++Bench/CMakeLists.txt create mode 100644 Benchmarks/Packet++Bench/main.cpp diff --git a/Benchmarks/CMakeLists.txt b/Benchmarks/CMakeLists.txt new file mode 100644 index 0000000000..c8658e384d --- /dev/null +++ b/Benchmarks/CMakeLists.txt @@ -0,0 +1,23 @@ + +include(FetchContent) + +if(NOT ( + (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) + AND (NOT MINGW) + AND (NOT CMAKE_OSX_ARCHITECTURES OR (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_OSX_ARCHITECTURES)) + ) +) + message(WARNING "Google Benchmark backend is not supported for cross-compilation") + return() +endif() + +# Fetch Google Benchmark +FetchContent_Declare(benchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.9.0) + +# Disable testing and installation for Google Benchmark +set(BENCHMARK_ENABLE_TESTING OFF) +set(BENCHMARK_ENABLE_INSTALL OFF) +FetchContent_MakeAvailable(benchmark) + +# Add PcapPlusPlus benchmarks +add_subdirectory(Packet++Bench) diff --git a/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp new file mode 100644 index 0000000000..bd2ece5c9c --- /dev/null +++ b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp @@ -0,0 +1,100 @@ +#include +#include + +#include "ParserConfig.h" + +namespace pcpp_bench +{ + using namespace pcpp; + + namespace + { + namespace portmapper + { + void StaticLookupSingle(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + + size_t totalLookups = 0; + for (auto _ : state) + { + PortPair portPair(80, 443); + auto protocol = portMapper.getProtocolByPortPair(portPair); + benchmark::DoNotOptimize(protocol); + totalLookups++; + } + + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(StaticLookupSingle); + + void StaticLookupMatrix(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + + size_t totalLookups = 0; + for (auto _ : state) + { + PortPair portPair(80, 443); + auto matrix = portMapper.getProtocolMappingsMatrixForPortPair(portPair); + benchmark::DoNotOptimize(matrix); + totalLookups++; + } + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(StaticLookupMatrix); + + void DynamicLookupSingle(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + size_t totalLookups = 0; + + // Generate random port pairs for dynamic lookups + std::vector inputPorts{ + PortPair{ 80, 65440 } + }; + + for (auto _ : state) + { + // Simulate dynamic port pairs by cycling through a predefined set + PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; + + auto protocol = portMapper.getProtocolByPortPair(portPair); + benchmark::DoNotOptimize(protocol); + totalLookups++; + } + + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(DynamicLookupSingle); + + void DynamicLookupMatrix(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + size_t totalLookups = 0; + + // Generate random port pairs for dynamic lookups + std::vector inputPorts{ + PortPair{ 80, 65440 } + }; + + for (auto _ : state) + { + // Simulate dynamic port pairs by cycling through a predefined set + PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; + + auto matrix = portMapper.getProtocolMappingsMatrixForPortPair(portPair); + benchmark::DoNotOptimize(matrix); + totalLookups++; + } + + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(DynamicLookupMatrix); + } // namespace portmapper + } // namespace +} // namespace pcpp_bench diff --git a/Benchmarks/Packet++Bench/CMakeLists.txt b/Benchmarks/Packet++Bench/CMakeLists.txt new file mode 100644 index 0000000000..fe3ce1a803 --- /dev/null +++ b/Benchmarks/Packet++Bench/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.14) + +add_executable(Packet++Bench + "main.cpp" + "Benchmarks/PortMapperBench.cpp" +) + +target_link_libraries(Packet++Bench PUBLIC PcapPlusPlus::Pcap++ benchmark::benchmark) diff --git a/Benchmarks/Packet++Bench/main.cpp b/Benchmarks/Packet++Bench/main.cpp new file mode 100644 index 0000000000..cdf0678e3f --- /dev/null +++ b/Benchmarks/Packet++Bench/main.cpp @@ -0,0 +1,12 @@ + +#include + +int main(int argc, char** argv) +{ + // Initialize the benchmark library + benchmark::Initialize(&argc, argv); + + // Run all benchmarks + benchmark::RunSpecifiedBenchmarks(); + return 0; +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 13dfeefb74..9976315569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ cmake_dependent_option( OFF ) option(PCAPPP_BUILD_TESTS "Build Tests" ${PCAPPP_MAIN_PROJECT}) +option(PCAPPP_BUILD_BENCHMARK "Build Benchmark Targets" OFF) option(PCAPPP_BUILD_COVERAGE "Generate Coverage Report" OFF) option(PCAPPP_BUILD_FUZZERS "Build Fuzzers binaries" OFF) option(PCAPPP_BUILD_REPRODUCIBLE "Build a reproducible version" OFF) @@ -336,6 +337,10 @@ if(PCAPPP_BUILD_TESTS OR PCAPPP_BUILD_FUZZERS OR PCAPPP_BUILD_EXAMPLES) add_subdirectory(Tests) endif() +if(PCAPPP_BUILD_BENCHMARK) + add_subdirectory(Benchmarks) +endif() + if(PCAPPP_INSTALL) # Generate PKG-Config for non WIN32 system if(NOT WIN32) From ff1226987c3ce2c667a3125209908d0a4d009191 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 10 Aug 2025 10:37:56 +0300 Subject: [PATCH 46/52] Disabled mix of hash function. --- Packet++/header/ParserConfig.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 604709f744..7a9f2f3f0a 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -265,7 +265,8 @@ namespace pcpp { std::size_t operator()(const PortPair& portPair) const noexcept { - return static_cast(splitMix64(encodePair(portPair))); + return static_cast(encodePair(portPair)); + // return static_cast(splitMix64(encodePair(portPair))); } constexpr uint64_t encodePair(const PortPair& portPair) const noexcept From f8a3834537d31f3e836a9082048fb1f41a2c1316 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sun, 10 Aug 2025 10:38:33 +0300 Subject: [PATCH 47/52] Added second port pair to benchmark. --- Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp index bd2ece5c9c..400c071bac 100644 --- a/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp +++ b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp @@ -54,7 +54,8 @@ namespace pcpp_bench // Generate random port pairs for dynamic lookups std::vector inputPorts{ - PortPair{ 80, 65440 } + PortPair{ 80, 65440 }, + PortPair{ 64000, 64002 }, }; for (auto _ : state) @@ -79,7 +80,8 @@ namespace pcpp_bench // Generate random port pairs for dynamic lookups std::vector inputPorts{ - PortPair{ 80, 65440 } + PortPair{ 80, 65440 }, + PortPair{ 64000, 64002 }, }; for (auto _ : state) From da22e5636def44d1736832933597920275b8b2b4 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 14 Aug 2025 22:33:44 +0300 Subject: [PATCH 48/52] Renamed to getMatchMatrix. --- Packet++/header/ParserConfig.h | 8 ++++---- Packet++/src/ParserConfig.cpp | 2 +- Packet++/src/UdpLayer.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Packet++/header/ParserConfig.h b/Packet++/header/ParserConfig.h index 7a9f2f3f0a..89edf05c6c 100644 --- a/Packet++/header/ParserConfig.h +++ b/Packet++/header/ParserConfig.h @@ -233,18 +233,18 @@ namespace pcpp /// /// @param port The port pair to look up. /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. - std::array getProtocolMappingsMatrixForPortPair(PortPair port) const; + std::array getMatchMatrix(PortPair port) const; /// @brief Get the protocol mappings that correspond to a specific port pair. /// - /// See `getProtocolMappingsMatrixForPortPair(PortPair port)` for details. + /// See `getMatchMatrix(PortPair port)` for details. /// /// @param portSrc The source port number. /// @param portDst The destination port number. /// @return An array of ProtocolTypeFamily values representing the protocols associated with the port pair. - std::array getProtocolMappingsMatrixForPortPair(uint16_t portSrc, uint16_t portDst) const + std::array getMatchMatrix(uint16_t portSrc, uint16_t portDst) const { - return getProtocolMappingsMatrixForPortPair({ portSrc, portDst }); + return getMatchMatrix({ portSrc, portDst }); } /// @brief Check if a port matches a specific protocol type. diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index f3d9553075..d3209cefdb 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -163,7 +163,7 @@ namespace pcpp return UnknownProtocol; // Return UnknownProtocol if exact match not found } - std::array PortMapper::getProtocolMappingsMatrixForPortPair(PortPair port) const + std::array PortMapper::getMatchMatrix(PortPair port) const { std::array protocols = { UnknownProtocol, UnknownProtocol, UnknownProtocol }; // Check for exact match diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index a224843e1d..1a64f57576 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -104,7 +104,7 @@ namespace pcpp // Queries the port mapper for protocol mappings based on the source and destination ports // The returned array protocol family for exact match, source only match, destination only match. // The first protocol family that passes secondary validation (if any) will be used to construct the next layer. - auto const portMatrix = config.portMapper.getProtocolMappingsMatrixForPortPair(portSrc, portDst); + auto const portMatrix = config.portMapper.getMatchMatrix(portSrc, portDst); for (auto protoFamily : portMatrix) { From 6d73cca7c0d0a2f145eb751cadd4f3c21afe1d77 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 15 Aug 2025 02:40:33 +0300 Subject: [PATCH 49/52] Removed portmapper namespace. --- .../Benchmarks/PortMapperBench.cpp | 151 +++++++++--------- 1 file changed, 74 insertions(+), 77 deletions(-) diff --git a/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp index 400c071bac..a96df37f08 100644 --- a/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp +++ b/Benchmarks/Packet++Bench/Benchmarks/PortMapperBench.cpp @@ -9,94 +9,91 @@ namespace pcpp_bench namespace { - namespace portmapper + void PortMapperStaticLookupSingle(benchmark::State& state) { - void StaticLookupSingle(benchmark::State& state) + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + + size_t totalLookups = 0; + for (auto _ : state) { - ParserConfiguration& config = ParserConfiguration::getDefault(); - PortMapper& portMapper = config.portMapper; - - size_t totalLookups = 0; - for (auto _ : state) - { - PortPair portPair(80, 443); - auto protocol = portMapper.getProtocolByPortPair(portPair); - benchmark::DoNotOptimize(protocol); - totalLookups++; - } - - state.SetItemsProcessed(totalLookups); + PortPair portPair(80, 443); + auto protocol = portMapper.getProtocolByPortPair(portPair); + benchmark::DoNotOptimize(protocol); + totalLookups++; } - BENCHMARK(StaticLookupSingle); - void StaticLookupMatrix(benchmark::State& state) + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(PortMapperStaticLookupSingle); + + void PortMapperStaticLookupMatrix(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + + size_t totalLookups = 0; + for (auto _ : state) { - ParserConfiguration& config = ParserConfiguration::getDefault(); - PortMapper& portMapper = config.portMapper; - - size_t totalLookups = 0; - for (auto _ : state) - { - PortPair portPair(80, 443); - auto matrix = portMapper.getProtocolMappingsMatrixForPortPair(portPair); - benchmark::DoNotOptimize(matrix); - totalLookups++; - } - state.SetItemsProcessed(totalLookups); + PortPair portPair(80, 443); + auto matrix = portMapper.getMatchMatrix(portPair); + benchmark::DoNotOptimize(matrix); + totalLookups++; } - BENCHMARK(StaticLookupMatrix); + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(PortMapperStaticLookupMatrix); + + void PortMapperDynamicLookupSingle(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + size_t totalLookups = 0; + + // Generate random port pairs for dynamic lookups + std::vector inputPorts{ + PortPair{ 80, 65440 }, + PortPair{ 64000, 64002 }, + }; - void DynamicLookupSingle(benchmark::State& state) + for (auto _ : state) { - ParserConfiguration& config = ParserConfiguration::getDefault(); - PortMapper& portMapper = config.portMapper; - size_t totalLookups = 0; - - // Generate random port pairs for dynamic lookups - std::vector inputPorts{ - PortPair{ 80, 65440 }, - PortPair{ 64000, 64002 }, - }; - - for (auto _ : state) - { - // Simulate dynamic port pairs by cycling through a predefined set - PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; - - auto protocol = portMapper.getProtocolByPortPair(portPair); - benchmark::DoNotOptimize(protocol); - totalLookups++; - } - - state.SetItemsProcessed(totalLookups); + // Simulate dynamic port pairs by cycling through a predefined set + PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; + + auto protocol = portMapper.getProtocolByPortPair(portPair); + benchmark::DoNotOptimize(protocol); + totalLookups++; } - BENCHMARK(DynamicLookupSingle); - void DynamicLookupMatrix(benchmark::State& state) + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(PortMapperDynamicLookupSingle); + + void PortMapperDynamicLookupMatrix(benchmark::State& state) + { + ParserConfiguration& config = ParserConfiguration::getDefault(); + PortMapper& portMapper = config.portMapper; + size_t totalLookups = 0; + + // Generate random port pairs for dynamic lookups + std::vector inputPorts{ + PortPair{ 80, 65440 }, + PortPair{ 64000, 64002 }, + }; + + for (auto _ : state) { - ParserConfiguration& config = ParserConfiguration::getDefault(); - PortMapper& portMapper = config.portMapper; - size_t totalLookups = 0; - - // Generate random port pairs for dynamic lookups - std::vector inputPorts{ - PortPair{ 80, 65440 }, - PortPair{ 64000, 64002 }, - }; - - for (auto _ : state) - { - // Simulate dynamic port pairs by cycling through a predefined set - PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; - - auto matrix = portMapper.getProtocolMappingsMatrixForPortPair(portPair); - benchmark::DoNotOptimize(matrix); - totalLookups++; - } - - state.SetItemsProcessed(totalLookups); + // Simulate dynamic port pairs by cycling through a predefined set + PortPair const& portPair = inputPorts[totalLookups % inputPorts.size()]; + + auto matrix = portMapper.getMatchMatrix(portPair); + benchmark::DoNotOptimize(matrix); + totalLookups++; } - BENCHMARK(DynamicLookupMatrix); - } // namespace portmapper + + state.SetItemsProcessed(totalLookups); + } + BENCHMARK(PortMapperDynamicLookupMatrix); } // namespace } // namespace pcpp_bench From 280f6b4461c383643ce4c3fd196bfb5ed525c6d9 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 15 Aug 2025 02:41:00 +0300 Subject: [PATCH 50/52] Fixed mappings to FTPControl and FTPData. --- Packet++/src/ParserConfig.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index d3209cefdb..caa662549c 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -49,10 +49,8 @@ namespace pcpp // The specific parsing determined based on if the port is src or dst. // A port pairing (21, 21) for example is UB. mapper.addPortMapping(PortPair{ 21, 21 }, UnknownProtocol, false); // Symmetrical connection is UB - mapper.addPortMapping(PortPair::fromSrc(21), FTP, false); // FTP control - mapper.addPortMapping(PortPair::fromDst(21), FTP, false); // FTP control - // TODO: FTP data needs a separate ProtocolType - // mapper.addPortMapping(PortPair::fromDst(20), FTP, false); // FTP data + mapper.addPortMapping(PortPair::fromSrc(21), FTPControl, true); // FTP control + mapper.addPortMapping(PortPair::fromDst(20), FTPData, true); // FTP data // SomeIP port mappings mapper.addPortMapping(PortPair::fromDst(30490), SomeIP, true); // SomeIP over UDP or TCP From 15ed36f20fa91b754f34228db22b8ec56c0cbfba Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 27 Sep 2025 21:19:20 +0300 Subject: [PATCH 51/52] Converted `parseNextLayer` to static dispatch. Added protected `doParseNextLayer` to do the actual parsing. The change is necessary due to the way C++ function hiding works in derived classes. If an overload `Derived::foo(int)` is declared, it hides all overloads `Base::foo(...)`. This is also true for virtual methods. The way backwards compatibility with the old `parseNextLayer` signature is done, is that there exist 2 overloads of the method, a parameter-less overload and one that takes `ParserConfiguration`. Given that all derived `Layer` classes implement a override of `parseNextLayer(ParserConfiguration const&)`, the pattern hides the parameter less overload for all derived classes. This is undesirable as it breaks backwards compatibility of the API. The implemented solution is to split the function into two logical pieces, the API (`parseNextLayer`) and the implementation: (`doParseNextLayer`). The API part are to be public facing static functions that pipe the input to `doParseNextLayer`, while the new method does the actual parsing. An alternative solution to use `using Layer::parseNextLayer` on all derived classes was considered and discarded, due to lack of compiler enforcement. An `doParseNextLayer` will always be enforced to exist, while the compiler can not be made to require `using Layer::parseNextLayer` to be included in derived classes. --- Packet++/header/ArpLayer.h | 9 +++++---- Packet++/header/BgpLayer.h | 8 ++++---- Packet++/header/CiscoHdlcLayer.h | 7 ++++--- Packet++/header/CotpLayer.h | 7 ++++--- Packet++/header/DhcpLayer.h | 9 +++++---- Packet++/header/DhcpV6Layer.h | 9 +++++---- Packet++/header/DnsLayer.h | 8 ++++---- Packet++/header/DoIpLayer.h | 7 ++++--- Packet++/header/EthDot3Layer.h | 7 ++++--- Packet++/header/EthLayer.h | 9 +++++---- Packet++/header/FtpLayer.h | 9 +++++---- Packet++/header/GreLayer.h | 17 ++++++++-------- Packet++/header/GtpLayer.h | 14 +++++++------ Packet++/header/IPSecLayer.h | 16 ++++++++------- Packet++/header/IPv4Layer.h | 29 ++++++++++++++------------- Packet++/header/IPv6Layer.h | 25 ++++++++++++----------- Packet++/header/IcmpLayer.h | 11 +++++----- Packet++/header/IcmpV6Layer.h | 8 ++++---- Packet++/header/IgmpLayer.h | 9 +++++---- Packet++/header/LLCLayer.h | 7 ++++--- Packet++/header/Layer.h | 7 ++++++- Packet++/header/LdapLayer.h | 7 ++++--- Packet++/header/ModbusLayer.h | 9 +++++---- Packet++/header/MplsLayer.h | 7 ++++--- Packet++/header/NflogLayer.h | 9 +++++---- Packet++/header/NtpLayer.h | 9 +++++---- Packet++/header/NullLoopbackLayer.h | 15 +++++++------- Packet++/header/PPPoELayer.h | 16 ++++++++------- Packet++/header/PacketTrailerLayer.h | 9 +++++---- Packet++/header/PayloadLayer.h | 9 +++++---- Packet++/header/RadiusLayer.h | 9 +++++---- Packet++/header/S7CommLayer.h | 9 +++++---- Packet++/header/SSHLayer.h | 8 ++++---- Packet++/header/SSLLayer.h | 7 +++---- Packet++/header/SipLayer.h | 10 +++++----- Packet++/header/Sll2Layer.h | 9 +++++---- Packet++/header/SllLayer.h | 9 +++++---- Packet++/header/SmtpLayer.h | 9 +++++---- Packet++/header/SomeIpLayer.h | 6 +++--- Packet++/header/StpLayer.h | 30 ++++++++++++++++------------ Packet++/header/TcpLayer.h | 9 +++++---- Packet++/header/TelnetLayer.h | 9 +++++---- Packet++/header/TextBasedProtocol.h | 6 +++--- Packet++/header/TpktLayer.h | 7 ++++--- Packet++/header/UdpLayer.h | 9 +++++---- Packet++/header/VlanLayer.h | 9 +++++---- Packet++/header/VrrpLayer.h | 9 +++++---- Packet++/header/VxlanLayer.h | 7 ++++--- Packet++/header/WakeOnLanLayer.h | 9 +++++---- Packet++/header/WireGuardLayer.h | 9 +++++---- Packet++/src/BgpLayer.cpp | 2 +- Packet++/src/CiscoHdlcLayer.cpp | 2 +- Packet++/src/CotpLayer.cpp | 2 +- Packet++/src/DoIpLayer.cpp | 2 +- Packet++/src/EthDot3Layer.cpp | 2 +- Packet++/src/EthLayer.cpp | 2 +- Packet++/src/GreLayer.cpp | 4 ++-- Packet++/src/GtpLayer.cpp | 4 ++-- Packet++/src/IPSecLayer.cpp | 4 ++-- Packet++/src/IPv4Layer.cpp | 2 +- Packet++/src/IPv6Layer.cpp | 2 +- Packet++/src/IcmpLayer.cpp | 2 +- Packet++/src/LLCLayer.cpp | 2 +- Packet++/src/LdapLayer.cpp | 2 +- Packet++/src/MplsLayer.cpp | 2 +- Packet++/src/NflogLayer.cpp | 2 +- Packet++/src/NullLoopbackLayer.cpp | 2 +- Packet++/src/PPPoELayer.cpp | 2 +- Packet++/src/SSHLayer.cpp | 2 +- Packet++/src/SSLLayer.cpp | 2 +- Packet++/src/SipLayer.cpp | 2 +- Packet++/src/Sll2Layer.cpp | 2 +- Packet++/src/SllLayer.cpp | 2 +- Packet++/src/SomeIpLayer.cpp | 2 +- Packet++/src/StpLayer.cpp | 6 +++--- Packet++/src/TcpLayer.cpp | 2 +- Packet++/src/TextBasedProtocol.cpp | 2 +- Packet++/src/TpktLayer.cpp | 2 +- Packet++/src/UdpLayer.cpp | 4 ++-- Packet++/src/VlanLayer.cpp | 2 +- Packet++/src/VxlanLayer.cpp | 2 +- 81 files changed, 318 insertions(+), 267 deletions(-) diff --git a/Packet++/header/ArpLayer.h b/Packet++/header/ArpLayer.h index f177fb3aaa..f10a8214df 100644 --- a/Packet++/header/ArpLayer.h +++ b/Packet++/header/ArpLayer.h @@ -238,10 +238,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (ArpLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The size of @ref arphdr size_t getHeaderLen() const override { @@ -280,6 +276,11 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Does nothing for this layer (ArpLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/BgpLayer.h b/Packet++/header/BgpLayer.h index c989e91cc9..0d9cdcd652 100644 --- a/Packet++/header/BgpLayer.h +++ b/Packet++/header/BgpLayer.h @@ -82,10 +82,6 @@ namespace pcpp /// @return The size of the BGP message size_t getHeaderLen() const override; - /// Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message - /// is another BGP message. This method checks for remaining data and parses it as another BGP layer - void parseNextLayer(ParserConfiguration const& config) override; - std::string toString() const override; OsiModelLayer getOsiModelLayer() const override @@ -107,6 +103,10 @@ namespace pcpp : Layer(data, dataLen, prevLayer, packet, BGP) {} + /// Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message + /// is another BGP message. This method checks for remaining data and parses it as another BGP layer + void doParseNextLayer(ParserConfiguration const& config) override; + bgp_common_header* getBasicHeader() const { return reinterpret_cast(m_Data); diff --git a/Packet++/header/CiscoHdlcLayer.h b/Packet++/header/CiscoHdlcLayer.h index 24a70d79f6..7229cc019d 100644 --- a/Packet++/header/CiscoHdlcLayer.h +++ b/Packet++/header/CiscoHdlcLayer.h @@ -72,9 +72,6 @@ namespace pcpp /// Calculate the Next Protocol when possible void computeCalculateFields() override; - /// Parses the next layer. Currently, supports IPv4 and IPv6 - void parseNextLayer(ParserConfiguration const& config) override; - std::string toString() const override; OsiModelLayer getOsiModelLayer() const override @@ -82,6 +79,10 @@ namespace pcpp return OsiModelDataLinkLayer; } + protected: + /// Parses the next layer. Currently, supports IPv4 and IPv6 + void doParseNextLayer(ParserConfiguration const& config) override; + private: #pragma pack(push, 1) struct cisco_hdlc_header diff --git a/Packet++/header/CotpLayer.h b/Packet++/header/CotpLayer.h index 1cf027271e..dc2baaf4a9 100644 --- a/Packet++/header/CotpLayer.h +++ b/Packet++/header/CotpLayer.h @@ -75,9 +75,6 @@ namespace pcpp void computeCalculateFields() override {} - /// Currently parses the rest of the packet as a S7COMM or generic payload (PayloadLayer) - void parseNextLayer(ParserConfiguration const& config) override; - /// A static method that takes a byte array and detects whether it is a COTP /// @param[in] data A byte array /// @param[in] dataSize The byte array size (in bytes) @@ -91,6 +88,10 @@ namespace pcpp return OsiModelTransportLayer; } + protected: + /// Currently parses the rest of the packet as a S7COMM or generic payload (PayloadLayer) + void doParseNextLayer(ParserConfiguration const& config) override; + private: cotphdr* getCotpHeader() const { diff --git a/Packet++/header/DhcpLayer.h b/Packet++/header/DhcpLayer.h index c3ae79bcec..614ce65f05 100644 --- a/Packet++/header/DhcpLayer.h +++ b/Packet++/header/DhcpLayer.h @@ -732,10 +732,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (DhcpLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The size of @ref dhcp_header + size of options size_t getHeaderLen() const override { @@ -759,6 +755,11 @@ namespace pcpp return OsiModelApplicationLayer; } + protected: + /// Does nothing for this layer (DhcpLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: uint8_t* getOptionsBasePtr() const { diff --git a/Packet++/header/DhcpV6Layer.h b/Packet++/header/DhcpV6Layer.h index d954a09732..4e9fb1bc7d 100644 --- a/Packet++/header/DhcpV6Layer.h +++ b/Packet++/header/DhcpV6Layer.h @@ -348,10 +348,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (DhcpV6Layer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The size of @ref dhcpv6_header + size of options size_t getHeaderLen() const override { @@ -369,6 +365,11 @@ namespace pcpp return OsiModelApplicationLayer; } + protected: + /// Does nothing for this layer (DhcpV6Layer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: uint8_t* getOptionsBasePtr() const { diff --git a/Packet++/header/DnsLayer.h b/Packet++/header/DnsLayer.h index 04c20f5eaf..39b2edd6bb 100644 --- a/Packet++/header/DnsLayer.h +++ b/Packet++/header/DnsLayer.h @@ -349,10 +349,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (DnsLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The size of the DNS data in the packet including he DNS header and size of all queries, answers, /// authorities and additional records size_t getHeaderLen() const override @@ -388,6 +384,10 @@ namespace pcpp DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment); explicit DnsLayer(size_t offsetAdjustment); + /// Does nothing for this layer (DnsLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: IDnsResource* m_ResourceList; DnsQuery* m_FirstQuery; diff --git a/Packet++/header/DoIpLayer.h b/Packet++/header/DoIpLayer.h index da834f9ee9..0c5b380a5b 100644 --- a/Packet++/header/DoIpLayer.h +++ b/Packet++/header/DoIpLayer.h @@ -620,9 +620,6 @@ namespace pcpp // implement abstract methods - /// parse UDS layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The size of @ref doiphdr + attached fields length size_t getHeaderLen() const override { @@ -639,6 +636,10 @@ namespace pcpp return OsiModelApplicationLayer; } + protected: + /// parse UDS layer + void doParseNextLayer(ParserConfiguration const& config) override; + private: void setPayloadType(DoIpPayloadTypes payloadType); diff --git a/Packet++/header/EthDot3Layer.h b/Packet++/header/EthDot3Layer.h index 74e271af0a..f500bcef3e 100644 --- a/Packet++/header/EthDot3Layer.h +++ b/Packet++/header/EthDot3Layer.h @@ -93,9 +93,6 @@ namespace pcpp // implement abstract methods - /// Parses next layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of ether_dot3_header size_t getHeaderLen() const override { @@ -118,6 +115,10 @@ namespace pcpp /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an IEEE 802.3 Eth packet static bool isDataValid(const uint8_t* data, size_t dataLen); + + protected: + /// Parses next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/EthLayer.h b/Packet++/header/EthLayer.h index 7302b0b333..8890effc47 100644 --- a/Packet++/header/EthLayer.h +++ b/Packet++/header/EthLayer.h @@ -130,10 +130,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, - /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of ether_header size_t getHeaderLen() const override { @@ -155,6 +151,11 @@ namespace pcpp /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an Ethernet II packet static bool isDataValid(const uint8_t* data, size_t dataLen); + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, + /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/FtpLayer.h b/Packet++/header/FtpLayer.h index 5f0cb05a02..259d657adb 100644 --- a/Packet++/header/FtpLayer.h +++ b/Packet++/header/FtpLayer.h @@ -35,10 +35,6 @@ namespace pcpp // overridden methods - /// FTP is the always last so does nothing for this layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Get the size of the layer size_t getHeaderLen() const override { @@ -54,6 +50,11 @@ namespace pcpp { return OsiModelApplicationLayer; } + + protected: + /// FTP is the always last so does nothing for this layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; /// Class for representing the request messages of FTP Layer diff --git a/Packet++/header/GreLayer.h b/Packet++/header/GreLayer.h index 24768adf1d..0137db25b7 100644 --- a/Packet++/header/GreLayer.h +++ b/Packet++/header/GreLayer.h @@ -125,11 +125,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: - /// IPv4Layer, IPv6Layer, VlanLayer, MplsLayer, PPP_PPTPLayer, EthLayer, EthDot3Layer - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of GRE header (may change if optional fields are added or removed) size_t getHeaderLen() const override; @@ -156,6 +151,11 @@ namespace pcpp uint8_t* getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const; + /// Currently identifies the following next layers: + /// IPv4Layer, IPv6Layer, VlanLayer, MplsLayer, PPP_PPTPLayer, EthLayer, EthDot3Layer + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + void computeCalculateFieldsInner(); }; @@ -367,9 +367,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The size of @ref ppp_pptp_header size_t getHeaderLen() const override { @@ -389,6 +386,10 @@ namespace pcpp { return OsiModelSesionLayer; } + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; bool PPP_PPTPLayer::isDataValid(const uint8_t* data, size_t dataLen) diff --git a/Packet++/header/GtpLayer.h b/Packet++/header/GtpLayer.h index a7d9ba28af..1168ac90ed 100644 --- a/Packet++/header/GtpLayer.h +++ b/Packet++/header/GtpLayer.h @@ -390,9 +390,6 @@ namespace pcpp // implement abstract methods - /// Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The size of the GTP header. For GTP-C packets the size is determined by the value of /// gtpv1_header#messageLength and for GTP-U the size only includes the GTP header itself (meaning /// the size of gtpv1_header plus the size of the optional fields such as sequence number, N-PDU @@ -409,6 +406,10 @@ namespace pcpp { return OsiModelTransportLayer; } + + protected: + /// Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; /// @class GtpV2MessageType @@ -1098,9 +1099,6 @@ namespace pcpp // implement abstract methods - /// Identifies if the next layer is GTPv2 piggyback. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The size of the GTPv2 header including its Information Elements (IE) size_t getHeaderLen() const override; @@ -1114,6 +1112,10 @@ namespace pcpp return OsiModelTransportLayer; } + protected: + /// Identifies if the next layer is GTPv2 piggyback. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: #pragma pack(push, 1) struct gtpv2_basic_header diff --git a/Packet++/header/IPSecLayer.h b/Packet++/header/IPSecLayer.h index 52a5b40306..2fdef918b4 100644 --- a/Packet++/header/IPSecLayer.h +++ b/Packet++/header/IPSecLayer.h @@ -91,10 +91,6 @@ namespace pcpp return static_cast(4) * (getAHHeader()->payloadLen + 2); } - /// Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// Does nothing for this layer void computeCalculateFields() override {} @@ -106,6 +102,11 @@ namespace pcpp return OsiModelNetworkLayer; } + protected: + /// Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: // this layer supports parsing only AuthenticationHeaderLayer() @@ -151,9 +152,6 @@ namespace pcpp return sizeof(ipsec_esp); } - /// The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer) - void parseNextLayer(ParserConfiguration const& config) override; - /// Does nothing for this layer void computeCalculateFields() override {} @@ -165,6 +163,10 @@ namespace pcpp return OsiModelTransportLayer; } + protected: + /// The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer) + void doParseNextLayer(ParserConfiguration const& config) override; + private: // this layer supports parsing only ESPLayer() diff --git a/Packet++/header/IPv4Layer.h b/Packet++/header/IPv4Layer.h index 30cdd5a9d4..0c34856ece 100644 --- a/Packet++/header/IPv4Layer.h +++ b/Packet++/header/IPv4Layer.h @@ -563,20 +563,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: - /// - UdpLayer - /// - TcpLayer - /// - IcmpLayer - /// - IPv4Layer (IP-in-IP) - /// - IPv6Layer (IP-in-IP) - /// - GreLayer - /// - IgmpLayer - /// - AuthenticationHeaderLayer (IPSec) - /// - ESPLayer (IPSec) - /// - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of IPv4 header (including IPv4 options if exist) size_t getHeaderLen() const override { @@ -605,6 +591,21 @@ namespace pcpp /// @return True if the data is valid and can represent an IPv4 packet static inline bool isDataValid(const uint8_t* data, size_t dataLen); + protected: + /// Currently identifies the following next layers: + /// - UdpLayer + /// - TcpLayer + /// - IcmpLayer + /// - IPv4Layer (IP-in-IP) + /// - IPv6Layer (IP-in-IP) + /// - GreLayer + /// - IgmpLayer + /// - AuthenticationHeaderLayer (IPSec) + /// - ESPLayer (IPSec) + /// + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: int m_NumOfTrailingBytes; int m_TempHeaderExtension; diff --git a/Packet++/header/IPv6Layer.h b/Packet++/header/IPv6Layer.h index fb220acd96..3cabe7742d 100644 --- a/Packet++/header/IPv6Layer.h +++ b/Packet++/header/IPv6Layer.h @@ -158,18 +158,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: - /// - UdpLayer - /// - TcpLayer - /// - IPv4Layer (IP-in-IP) - /// - IPv6Layer (IP-in-IP) - /// - GreLayer - /// - AuthenticationHeaderLayer (IPSec) - /// - ESPLayer (IPSec) - /// - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of @ref ip6_hdr size_t getHeaderLen() const override { @@ -190,6 +178,19 @@ namespace pcpp return OsiModelNetworkLayer; } + protected: + /// Currently identifies the following next layers: + /// - UdpLayer + /// - TcpLayer + /// - IPv4Layer (IP-in-IP) + /// - IPv6Layer (IP-in-IP) + /// - GreLayer + /// - AuthenticationHeaderLayer (IPSec) + /// - ESPLayer (IPSec) + /// + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: void initLayer(); void parseExtensions(); diff --git a/Packet++/header/IcmpLayer.h b/Packet++/header/IcmpLayer.h index 7bba4be151..4290834a80 100644 --- a/Packet++/header/IcmpLayer.h +++ b/Packet++/header/IcmpLayer.h @@ -593,11 +593,6 @@ namespace pcpp // implement abstract methods - /// ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, - /// ICMP_PARAM_PROBLEM have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses - /// these headers as separate layers on top of the ICMP layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The ICMP header length. This length varies according to the ICMP message type. This length doesn't /// include IPv4 and L4 headers in case ICMP message type are: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, /// ICMP_TIME_EXCEEDED, ICMP_REDIRECT, ICMP_PARAM_PROBLEM @@ -612,6 +607,12 @@ namespace pcpp { return OsiModelNetworkLayer; } + + protected: + /// ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, + /// ICMP_PARAM_PROBLEM have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses + /// these headers as separate layers on top of the ICMP layer + void doParseNextLayer(ParserConfiguration const& config) override; }; // implementation of inline methods diff --git a/Packet++/header/IcmpV6Layer.h b/Packet++/header/IcmpV6Layer.h index e4a2075e5e..46f85c9ea3 100644 --- a/Packet++/header/IcmpV6Layer.h +++ b/Packet++/header/IcmpV6Layer.h @@ -165,10 +165,6 @@ namespace pcpp /// @return Get the checksum header field in host representation uint16_t getChecksum() const; - /// Does nothing for this layer. ICMPv6 is the last layer. - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The size of the ICMPv6 message size_t getHeaderLen() const override { @@ -188,6 +184,10 @@ namespace pcpp protected: IcmpV6Layer() = default; + /// Does nothing for this layer. ICMPv6 is the last layer. + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: void calculateChecksum(); icmpv6hdr* getIcmpv6Header() const diff --git a/Packet++/header/IgmpLayer.h b/Packet++/header/IgmpLayer.h index b642f7f388..3d64fb7bb0 100644 --- a/Packet++/header/IgmpLayer.h +++ b/Packet++/header/IgmpLayer.h @@ -187,10 +187,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (IGMP layer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Size of IGMP header = 8B size_t getHeaderLen() const override { @@ -203,6 +199,11 @@ namespace pcpp { return OsiModelNetworkLayer; } + + protected: + /// Does nothing for this layer (IGMP layer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; /// @class IgmpV1Layer diff --git a/Packet++/header/LLCLayer.h b/Packet++/header/LLCLayer.h index 791853829c..c00ca98c78 100644 --- a/Packet++/header/LLCLayer.h +++ b/Packet++/header/LLCLayer.h @@ -52,9 +52,6 @@ namespace pcpp // overridden methods - /// Parses the next layer. Currently only STP supported as next layer - void parseNextLayer(ParserConfiguration const& config) override; - /// Does nothing for this layer void computeCalculateFields() override {} @@ -79,6 +76,10 @@ namespace pcpp /// @param[in] dataLen The length of the byte stream /// @return True if the data is valid and can represent an LLC packet static bool isDataValid(const uint8_t* data, size_t dataLen); + + protected: + /// Parses the next layer. Currently only STP supported as next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h index 0408003164..d4cd949444 100644 --- a/Packet++/header/Layer.h +++ b/Packet++/header/Layer.h @@ -148,7 +148,10 @@ namespace pcpp parseNextLayer(ParserConfiguration::getDefault()); } - virtual void parseNextLayer(ParserConfiguration const& config) = 0; + void parseNextLayer(ParserConfiguration const& config) + { + doParseNextLayer(config); + } /// @return The header length in bytes virtual size_t getHeaderLen() const = 0; @@ -203,6 +206,8 @@ namespace pcpp return m_NextLayer != nullptr; } + virtual void doParseNextLayer(ParserConfiguration const& config) = 0; + /// Construct the next layer in the protocol stack. No validation is performed on the data. /// @tparam T The type of the layer to construct /// @tparam Args The types of the arguments to pass to the layer constructor diff --git a/Packet++/header/LdapLayer.h b/Packet++/header/LdapLayer.h index bc7227f07f..e7864ffa24 100644 --- a/Packet++/header/LdapLayer.h +++ b/Packet++/header/LdapLayer.h @@ -358,9 +358,6 @@ namespace pcpp // implement abstract methods - /// Tries to identify more LDAP messages in this packet if exist - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The size of the LDAP message size_t getHeaderLen() const override { @@ -385,6 +382,10 @@ namespace pcpp LdapLayer() = default; void init(uint16_t messageId, LdapOperationType operationType, const std::vector& messageRecords, const std::vector& controls); + + /// Tries to identify more LDAP messages in this packet if exist + void doParseNextLayer(ParserConfiguration const& config) override; + virtual std::string getExtendedInfoString() const { return ""; diff --git a/Packet++/header/ModbusLayer.h b/Packet++/header/ModbusLayer.h index bf50c4f986..7b3a8c22a1 100644 --- a/Packet++/header/ModbusLayer.h +++ b/Packet++/header/ModbusLayer.h @@ -131,10 +131,6 @@ namespace pcpp // Overridden methods - /// Does nothing for this layer (ModbusLayer is always last) - void parseNextLayer() override - {} - /// @brief Get the length of the MODBUS header /// @return Length of the MODBUS header in bytes size_t getHeaderLen() const override @@ -156,6 +152,11 @@ namespace pcpp return OsiModelApplicationLayer; } + protected: + /// Does nothing for this layer (ModbusLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: /// @return A pointer to the MODBUS header modbus_header* getModbusHeader() const; diff --git a/Packet++/header/MplsLayer.h b/Packet++/header/MplsLayer.h index c06f8a35b8..dec9114c7d 100644 --- a/Packet++/header/MplsLayer.h +++ b/Packet++/header/MplsLayer.h @@ -87,9 +87,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of MPLS header (4 bytes) size_t getHeaderLen() const override { @@ -115,6 +112,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, MplsLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/NflogLayer.h b/Packet++/header/NflogLayer.h index 6fc02303a4..a03b949a2e 100644 --- a/Packet++/header/NflogLayer.h +++ b/Packet++/header/NflogLayer.h @@ -182,10 +182,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer using address family - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of nflog_header size_t getHeaderLen() const override; @@ -205,6 +201,11 @@ namespace pcpp /// @return True if the data is valid and can represent an NFLOG packet static bool isDataValid(const uint8_t* data, size_t dataLen); + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer using address family + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: uint8_t* getTlvsBasePtr() const { diff --git a/Packet++/header/NtpLayer.h b/Packet++/header/NtpLayer.h index 5a669248c6..e5efbaf2b7 100644 --- a/Packet++/header/NtpLayer.h +++ b/Packet++/header/NtpLayer.h @@ -535,10 +535,6 @@ namespace pcpp // overridden methods - /// Parses the next layer. NTP is the always last so does nothing for this layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Get the size of the layer (Including the extension and authentication fields if exists) size_t getHeaderLen() const override { @@ -557,5 +553,10 @@ namespace pcpp /// @return Returns the protocol info as readable string std::string toString() const override; + + protected: + /// Parses the next layer. NTP is the always last so does nothing for this layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/NullLoopbackLayer.h b/Packet++/header/NullLoopbackLayer.h index 87b8ad2940..c36ad9a177 100644 --- a/Packet++/header/NullLoopbackLayer.h +++ b/Packet++/header/NullLoopbackLayer.h @@ -55,13 +55,6 @@ namespace pcpp // implement abstract methods - /// Identifies the next layers by family: - /// - for ::PCPP_BSD_AF_INET the next layer is IPv4Layer - /// - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is - /// IPv6Layer - /// - for other values the next layer in PayloadLayer (unknown protocol) - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of Null/Loopback header = 4B size_t getHeaderLen() const override { @@ -78,5 +71,13 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + protected: + /// Identifies the next layers by family: + /// - for ::PCPP_BSD_AF_INET the next layer is IPv4Layer + /// - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is + /// IPv6Layer + /// - for other values the next layer in PayloadLayer (unknown protocol) + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/PPPoELayer.h b/Packet++/header/PPPoELayer.h index 65f365068d..e4fffbedc3 100644 --- a/Packet++/header/PPPoELayer.h +++ b/Packet++/header/PPPoELayer.h @@ -148,9 +148,6 @@ namespace pcpp // abstract methods implementation - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of @ref pppoe_header size_t getHeaderLen() const override { @@ -158,6 +155,10 @@ namespace pcpp } std::string toString() const override; + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; /// @class PPPoEDiscoveryLayer @@ -349,10 +350,6 @@ namespace pcpp // abstract methods implementation - /// Does nothing for this layer (PPPoE discovery is always the last layer) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return The header length which is size of strcut pppoe_header plus the total size of tags size_t getHeaderLen() const override; @@ -361,6 +358,11 @@ namespace pcpp return "PPP-over-Ethernet Discovery (" + codeToString((PPPoELayer::PPPoECode)getPPPoEHeader()->code) + ")"; } + protected: + /// Does nothing for this layer (PPPoE discovery is always the last layer) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: TLVRecordReader m_TagReader; diff --git a/Packet++/header/PacketTrailerLayer.h b/Packet++/header/PacketTrailerLayer.h index 15e39df185..c69d8902b8 100644 --- a/Packet++/header/PacketTrailerLayer.h +++ b/Packet++/header/PacketTrailerLayer.h @@ -61,10 +61,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (PacketTrailerLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return trailer data length in bytes size_t getHeaderLen() const override { @@ -81,6 +77,11 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + protected: + /// Does nothing for this layer (PacketTrailerLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/PayloadLayer.h b/Packet++/header/PayloadLayer.h index 460e79a59a..9988a548c1 100644 --- a/Packet++/header/PayloadLayer.h +++ b/Packet++/header/PayloadLayer.h @@ -53,10 +53,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (PayloadLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Payload data length in bytes size_t getHeaderLen() const override { @@ -89,5 +85,10 @@ namespace pcpp // PayloadLayer is special as it can be empty. So, it's valid if data is nullptr and dataLen is 0. return (data == nullptr) != (dataLen != 0); // XOR }; + + protected: + /// Does nothing for this layer (PayloadLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/RadiusLayer.h b/Packet++/header/RadiusLayer.h index bf9aa53767..d00facbb41 100644 --- a/Packet++/header/RadiusLayer.h +++ b/Packet++/header/RadiusLayer.h @@ -253,10 +253,6 @@ namespace pcpp /// @return The size written in radius_header#length size_t getHeaderLen() const override; - /// Does nothing for this layer, RADIUS is always last - void parseNextLayer(ParserConfiguration const& config) override - {} - /// Calculate and store the value of radius_header#length according to the layer size void computeCalculateFields() override; @@ -266,6 +262,11 @@ namespace pcpp { return OsiModelApplicationLayer; } + + protected: + /// Does nothing for this layer, RADIUS is always last + void doParseNextLayer(ParserConfiguration const& config) override + {} }; // implementation of inline methods diff --git a/Packet++/header/S7CommLayer.h b/Packet++/header/S7CommLayer.h index 1682aa86c4..db7a983e5b 100644 --- a/Packet++/header/S7CommLayer.h +++ b/Packet++/header/S7CommLayer.h @@ -151,10 +151,6 @@ namespace pcpp void computeCalculateFields() override {} - /// Does nothing for this layer (S7CommLayer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// A static method that takes a byte array and detects whether it is a S7COMM /// @param[in] data A byte array /// @param[in] dataSize The byte array size (in bytes) @@ -168,6 +164,11 @@ namespace pcpp return OsiModelApplicationLayer; } + protected: + /// Does nothing for this layer (S7CommLayer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} + private: s7commhdr* getS7commHeader() const { diff --git a/Packet++/header/SSHLayer.h b/Packet++/header/SSHLayer.h index 3fd44e7538..3dface7081 100644 --- a/Packet++/header/SSHLayer.h +++ b/Packet++/header/SSHLayer.h @@ -96,10 +96,6 @@ namespace pcpp // implement abstract methods - /// Several SSH records can reside in a single packets. This method examins the remaining data and creates - /// additional SSH records if applicable - void parseNextLayer(ParserConfiguration const& config) override; - /// Does nothing for this layer void computeCalculateFields() override {} @@ -115,6 +111,10 @@ namespace pcpp : Layer(data, dataLen, prevLayer, packet, SSH) {} + /// Several SSH records can reside in a single packets. This method examins the remaining data and creates + /// additional SSH records if applicable + void doParseNextLayer(ParserConfiguration const& config) override; + private: // this layer supports only parsing SSHLayer(); diff --git a/Packet++/header/SSLLayer.h b/Packet++/header/SSLLayer.h index c5dea5ed5d..4789d128f4 100644 --- a/Packet++/header/SSLLayer.h +++ b/Packet++/header/SSLLayer.h @@ -239,10 +239,6 @@ namespace pcpp /// @return The record size as extracted from the record data (in ssl_tls_record_layer#length) size_t getHeaderLen() const override; - /// Several SSL/TLS records can reside in a single packets. So this method checks the remaining data and if it's - /// identified as SSL/TLS it creates another SSL/TLS record layer as the next layer - void parseNextLayer(ParserConfiguration const& config) override; - OsiModelLayer getOsiModelLayer() const override { return OsiModelPresentationLayer; @@ -253,6 +249,9 @@ namespace pcpp : Layer(data, dataLen, prevLayer, packet, SSL) {} + /// Several SSL/TLS records can reside in a single packets. So this method checks the remaining data and if it's + /// identified as SSL/TLS it creates another SSL/TLS record layer as the next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; // class SSLLayer // The graph below will break the code formatting, so it's disabled. diff --git a/Packet++/header/SipLayer.h b/Packet++/header/SipLayer.h index 042e47c514..a429c9c1bb 100644 --- a/Packet++/header/SipLayer.h +++ b/Packet++/header/SipLayer.h @@ -98,11 +98,6 @@ namespace pcpp return OsiModelSesionLayer; } - /// Currently identifies only SDP if content-length field exists and set to a value greater than zero. - /// If content-length field doesn't exist or set to zero and still there is data after this layer, a - /// PayloadLayer will be created - void parseNextLayer(ParserConfiguration const& config) override; - /// Set the content-length only if a content-length field already exists and if its current value is different /// than the total length of the next layer(s) void computeCalculateFields() override; @@ -128,6 +123,11 @@ namespace pcpp return *this; } + /// Currently identifies only SDP if content-length field exists and set to a value greater than zero. + /// If content-length field doesn't exist or set to zero and still there is data after this layer, a + /// PayloadLayer will be created + void doParseNextLayer(ParserConfiguration const& config) override; + // implementation of abstract methods char getHeaderFieldNameValueSeparator() const override { diff --git a/Packet++/header/Sll2Layer.h b/Packet++/header/Sll2Layer.h index ac2c9df67f..f3243a0b45 100644 --- a/Packet++/header/Sll2Layer.h +++ b/Packet++/header/Sll2Layer.h @@ -128,10 +128,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, - /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// Calculate the next protocol type for known protocols: IPv4, IPv6, ARP, VLAN void computeCalculateFields() override; @@ -147,6 +143,11 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, + /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/SllLayer.h b/Packet++/header/SllLayer.h index 58c3f59616..b795c21172 100644 --- a/Packet++/header/SllLayer.h +++ b/Packet++/header/SllLayer.h @@ -69,10 +69,6 @@ namespace pcpp /// @return True if address was set successfully, false if MAC address isn't valid or if set failed bool setMacAddressAsLinkLayer(const MacAddress& macAddr); - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, - /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of sll_header size_t getHeaderLen() const override { @@ -88,6 +84,11 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, + /// PPPoESessionLayer, PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/SmtpLayer.h b/Packet++/header/SmtpLayer.h index 25ff0ff0b9..5886950753 100644 --- a/Packet++/header/SmtpLayer.h +++ b/Packet++/header/SmtpLayer.h @@ -31,10 +31,6 @@ namespace pcpp // overridden methods - /// SMTP is the always last so does nothing for this layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Get the size of the layer size_t getHeaderLen() const override { @@ -50,6 +46,11 @@ namespace pcpp { return OsiModelApplicationLayer; } + + protected: + /// SMTP is the always last so does nothing for this layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; /// Class for representing the request messages of SMTP Layer diff --git a/Packet++/header/SomeIpLayer.h b/Packet++/header/SomeIpLayer.h index aabbdcef0b..4eb263b1bc 100644 --- a/Packet++/header/SomeIpLayer.h +++ b/Packet++/header/SomeIpLayer.h @@ -257,9 +257,6 @@ namespace pcpp virtual void computeCalculateFields() override {} - /// Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The string representation of the SOME/IP layer virtual std::string toString() const override; @@ -273,6 +270,9 @@ namespace pcpp SomeIpLayer() {} + /// Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: static const uint8_t SOMEIP_PROTOCOL_VERSION = 1; virtual size_t getSomeIpHeaderLen() const diff --git a/Packet++/header/StpLayer.h b/Packet++/header/StpLayer.h index b5ae529544..9e5dd08370 100644 --- a/Packet++/header/StpLayer.h +++ b/Packet++/header/StpLayer.h @@ -261,9 +261,6 @@ namespace pcpp return sizeof(stp_tcn_bpdu); } - /// Parses next layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Returns the protocol info as readable string std::string toString() const override { @@ -279,6 +276,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Parses next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; /// @class StpConfigurationBPDULayer @@ -450,9 +451,6 @@ namespace pcpp return sizeof(stp_conf_bpdu); } - /// Parses next layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Returns the protocol info as readable string std::string toString() const override { @@ -467,6 +465,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Parses next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; /// @class RapidStpLayer @@ -520,9 +522,6 @@ namespace pcpp return sizeof(rstp_conf_bpdu); } - /// Parses next layer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Returns the protocol info as readable string std::string toString() const override { @@ -537,6 +536,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Parses next layer + void doParseNextLayer(ParserConfiguration const& config) override; }; /// @class MultipleStpLayer @@ -687,10 +690,6 @@ namespace pcpp // overridden methods - /// Parses next layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Returns the protocol info as readable string std::string toString() const override { @@ -705,5 +704,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Parses next layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/TcpLayer.h b/Packet++/header/TcpLayer.h index 0a73483911..7e4cb8f983 100644 --- a/Packet++/header/TcpLayer.h +++ b/Packet++/header/TcpLayer.h @@ -557,10 +557,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets - /// PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of @ref tcphdr + all TCP options size_t getHeaderLen() const override { @@ -577,6 +573,11 @@ namespace pcpp return OsiModelTransportLayer; } + protected: + /// Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets + /// PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; + private: TLVRecordReader m_OptionReader; int m_NumOfTrailingBytes; diff --git a/Packet++/header/TelnetLayer.h b/Packet++/header/TelnetLayer.h index a81bab2688..5a0ffeb58b 100644 --- a/Packet++/header/TelnetLayer.h +++ b/Packet++/header/TelnetLayer.h @@ -289,10 +289,6 @@ namespace pcpp // overridden methods - /// Parses the next layer. Telnet is the always last so does nothing for this layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Get the size of the layer size_t getHeaderLen() const override { @@ -311,6 +307,11 @@ namespace pcpp /// @return Returns the protocol info as readable string std::string toString() const override; + + protected: + /// Parses the next layer. Telnet is the always last so does nothing for this layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/TextBasedProtocol.h b/Packet++/header/TextBasedProtocol.h index ca5fdeff7c..dc3e27419b 100644 --- a/Packet++/header/TextBasedProtocol.h +++ b/Packet++/header/TextBasedProtocol.h @@ -200,9 +200,6 @@ namespace pcpp // implement Layer's abstract methods - /// Currently set only PayloadLayer for the rest of the data - void parseNextLayer(ParserConfiguration const& config) override; - /// @return The message length size_t getHeaderLen() const override; @@ -221,6 +218,9 @@ namespace pcpp void copyDataFrom(const TextBasedProtocolMessage& other); + /// Currently set only PayloadLayer for the rest of the data + void doParseNextLayer(ParserConfiguration const& config) override; + void parseFields(); void shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift); diff --git a/Packet++/header/TpktLayer.h b/Packet++/header/TpktLayer.h index 2546770a91..8d0ab8b699 100644 --- a/Packet++/header/TpktLayer.h +++ b/Packet++/header/TpktLayer.h @@ -72,9 +72,6 @@ namespace pcpp void computeCalculateFields() override {} - /// Currently parses the rest of the packet as a COTP protocol or generic payload (PayloadLayer) - void parseNextLayer(ParserConfiguration const& config) override; - /// A static method that checks whether a source or dest port match those associated with the TPKT protocol /// @param[in] portSrc Source port number to check /// @param[in] portDst Dest port number to check @@ -100,6 +97,10 @@ namespace pcpp return OsiModelTransportLayer; } + protected: + /// Currently parses the rest of the packet as a COTP protocol or generic payload (PayloadLayer) + void doParseNextLayer(ParserConfiguration const& config) override; + private: /// Get a pointer to the TPKT header. Data can be retrieved through the /// other methods of this layer. Notice the return value points directly to the data, so every change will diff --git a/Packet++/header/UdpLayer.h b/Packet++/header/UdpLayer.h index 5557b49372..3f2d7613fe 100644 --- a/Packet++/header/UdpLayer.h +++ b/Packet++/header/UdpLayer.h @@ -72,10 +72,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, - /// SipResponseLayer, RadiusLayer. Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of @ref udphdr size_t getHeaderLen() const override { @@ -91,6 +87,11 @@ namespace pcpp { return OsiModelTransportLayer; } + + protected: + /// Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, + /// SipResponseLayer, RadiusLayer. Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; bool UdpLayer::isDataValid(const uint8_t* data, size_t dataLen) diff --git a/Packet++/header/VlanLayer.h b/Packet++/header/VlanLayer.h index ae5a771a99..482f64932e 100644 --- a/Packet++/header/VlanLayer.h +++ b/Packet++/header/VlanLayer.h @@ -92,10 +92,6 @@ namespace pcpp // implement abstract methods - /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. - /// Otherwise sets PayloadLayer - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of vlan_header size_t getHeaderLen() const override { @@ -120,5 +116,10 @@ namespace pcpp { return canReinterpretAs(data, dataLen); } + + protected: + /// Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. + /// Otherwise sets PayloadLayer + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/VrrpLayer.h b/Packet++/header/VrrpLayer.h index 33074642e1..a6a951183b 100644 --- a/Packet++/header/VrrpLayer.h +++ b/Packet++/header/VrrpLayer.h @@ -243,10 +243,6 @@ namespace pcpp // implement abstract methods - /// Does nothing for this layer (VRRP layer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// Calculate the VRRP checksum void computeCalculateFields() override; @@ -263,6 +259,11 @@ namespace pcpp { return OsiModelNetworkLayer; } + + protected: + /// Does nothing for this layer (VRRP layer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; /// @class VrrpV2Layer diff --git a/Packet++/header/VxlanLayer.h b/Packet++/header/VxlanLayer.h index 390db95798..e40debed98 100644 --- a/Packet++/header/VxlanLayer.h +++ b/Packet++/header/VxlanLayer.h @@ -114,9 +114,6 @@ namespace pcpp // implement abstract methods - /// Next layer for VXLAN is always Ethernet - void parseNextLayer(ParserConfiguration const& config) override; - /// @return Size of vxlan_header size_t getHeaderLen() const override { @@ -133,5 +130,9 @@ namespace pcpp { return OsiModelDataLinkLayer; } + + protected: + /// Next layer for VXLAN is always Ethernet + void doParseNextLayer(ParserConfiguration const& config) override; }; } // namespace pcpp diff --git a/Packet++/header/WakeOnLanLayer.h b/Packet++/header/WakeOnLanLayer.h index 103d4bdc27..78d14f22e5 100644 --- a/Packet++/header/WakeOnLanLayer.h +++ b/Packet++/header/WakeOnLanLayer.h @@ -115,10 +115,6 @@ namespace pcpp // overridden methods - /// Parses the next layer. Wake on LAN is the always last so does nothing for this layer - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Get the size of the layer size_t getHeaderLen() const override { @@ -137,5 +133,10 @@ namespace pcpp /// @return Returns the protocol info as readable string std::string toString() const override; + + protected: + /// Parses the next layer. Wake on LAN is the always last so does nothing for this layer + void doParseNextLayer(ParserConfiguration const& config) override + {} }; } // namespace pcpp diff --git a/Packet++/header/WireGuardLayer.h b/Packet++/header/WireGuardLayer.h index 0417bd4133..0e5d32f286 100644 --- a/Packet++/header/WireGuardLayer.h +++ b/Packet++/header/WireGuardLayer.h @@ -95,10 +95,6 @@ namespace pcpp /// @param reserved The reserved field to set as a An array containing the 3-byte. void setReserved(const std::array& reserved); - /// Does nothing for this layer (WireGuard layer is always last) - void parseNextLayer(ParserConfiguration const& config) override - {} - /// @return Size of the header in bytes. size_t getHeaderLen() const override; @@ -121,6 +117,11 @@ namespace pcpp { return WireGuardMessageType::Unknown; } + + protected: + /// Does nothing for this layer (WireGuard layer is always last) + void doParseNextLayer(ParserConfiguration const& config) override + {} }; /// @class WireGuardHandshakeInitiationLayer diff --git a/Packet++/src/BgpLayer.cpp b/Packet++/src/BgpLayer.cpp index 71b6d8e88b..0acdf29c6c 100644 --- a/Packet++/src/BgpLayer.cpp +++ b/Packet++/src/BgpLayer.cpp @@ -77,7 +77,7 @@ namespace pcpp } } - void BgpLayer::parseNextLayer(ParserConfiguration const& config) + void BgpLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen || headerLen == 0) diff --git a/Packet++/src/CiscoHdlcLayer.cpp b/Packet++/src/CiscoHdlcLayer.cpp index b34bc73307..9d8d9cbc70 100644 --- a/Packet++/src/CiscoHdlcLayer.cpp +++ b/Packet++/src/CiscoHdlcLayer.cpp @@ -43,7 +43,7 @@ namespace pcpp } } - void CiscoHdlcLayer::parseNextLayer(ParserConfiguration const& config) + void CiscoHdlcLayer::doParseNextLayer(ParserConfiguration const& config) { auto payload = m_Data + sizeof(cisco_hdlc_header); auto payloadLen = m_DataLen - sizeof(cisco_hdlc_header); diff --git a/Packet++/src/CotpLayer.cpp b/Packet++/src/CotpLayer.cpp index 610bd0ca14..fd75f6546b 100644 --- a/Packet++/src/CotpLayer.cpp +++ b/Packet++/src/CotpLayer.cpp @@ -63,7 +63,7 @@ namespace pcpp return data[1] == 0xf0 && data[0] == 2; } - void CotpLayer::parseNextLayer(ParserConfiguration const& config) + void CotpLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/DoIpLayer.cpp b/Packet++/src/DoIpLayer.cpp index a1238d9149..71a0018176 100644 --- a/Packet++/src/DoIpLayer.cpp +++ b/Packet++/src/DoIpLayer.cpp @@ -382,7 +382,7 @@ namespace pcpp setPayloadLength(length); } - void DoIpLayer::parseNextLayer(ParserConfiguration const& config) + void DoIpLayer::doParseNextLayer(ParserConfiguration const& config) { if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE) { diff --git a/Packet++/src/EthDot3Layer.cpp b/Packet++/src/EthDot3Layer.cpp index c4694a4f8b..17400791b8 100644 --- a/Packet++/src/EthDot3Layer.cpp +++ b/Packet++/src/EthDot3Layer.cpp @@ -21,7 +21,7 @@ namespace pcpp m_Protocol = Ethernet; } - void EthDot3Layer::parseNextLayer(ParserConfiguration const& config) + void EthDot3Layer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(ether_dot3_header)) return; diff --git a/Packet++/src/EthLayer.cpp b/Packet++/src/EthLayer.cpp index 01d6a5d341..349b0cfa1d 100644 --- a/Packet++/src/EthLayer.cpp +++ b/Packet++/src/EthLayer.cpp @@ -27,7 +27,7 @@ namespace pcpp m_Protocol = Ethernet; } - void EthLayer::parseNextLayer(ParserConfiguration const& config) + void EthLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(ether_header)) return; diff --git a/Packet++/src/GreLayer.cpp b/Packet++/src/GreLayer.cpp index 8a5742aa58..e5d4579b79 100644 --- a/Packet++/src/GreLayer.cpp +++ b/Packet++/src/GreLayer.cpp @@ -192,7 +192,7 @@ namespace pcpp return true; } - void GreLayer::parseNextLayer(ParserConfiguration const& config) + void GreLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) @@ -563,7 +563,7 @@ namespace pcpp header->control = control; } - void PPP_PPTPLayer::parseNextLayer(ParserConfiguration const& config) + void PPP_PPTPLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/GtpLayer.cpp b/Packet++/src/GtpLayer.cpp index d91fc05c31..b3523209c0 100644 --- a/Packet++/src/GtpLayer.cpp +++ b/Packet++/src/GtpLayer.cpp @@ -559,7 +559,7 @@ namespace pcpp return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE; } - void GtpV1Layer::parseNextLayer(ParserConfiguration const& config) + void GtpV1Layer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (headerLen < sizeof(gtpv1_header)) @@ -1302,7 +1302,7 @@ namespace pcpp return GtpV2InformationElement(newInfoElementPtr); } - void GtpV2Layer::parseNextLayer(ParserConfiguration const& config) + void GtpV2Layer::doParseNextLayer(ParserConfiguration const& config) { auto headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/IPSecLayer.cpp b/Packet++/src/IPSecLayer.cpp index de0b1b4b17..3341b2af96 100644 --- a/Packet++/src/IPSecLayer.cpp +++ b/Packet++/src/IPSecLayer.cpp @@ -51,7 +51,7 @@ namespace pcpp return byteArrayToHexString(bytes, getICVLength()); } - void AuthenticationHeaderLayer::parseNextLayer(ParserConfiguration const& config) + void AuthenticationHeaderLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) @@ -112,7 +112,7 @@ namespace pcpp return be32toh(getESPHeader()->sequenceNumber); } - void ESPLayer::parseNextLayer(ParserConfiguration const& config) + void ESPLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/IPv4Layer.cpp b/Packet++/src/IPv4Layer.cpp index cecedfa0cc..c83debcc4c 100644 --- a/Packet++/src/IPv4Layer.cpp +++ b/Packet++/src/IPv4Layer.cpp @@ -244,7 +244,7 @@ namespace pcpp return *this; } - void IPv4Layer::parseNextLayer(ParserConfiguration const& config) + void IPv4Layer::doParseNextLayer(ParserConfiguration const& config) { size_t hdrLen = getHeaderLen(); if (m_DataLen <= hdrLen || hdrLen == 0) diff --git a/Packet++/src/IPv6Layer.cpp b/Packet++/src/IPv6Layer.cpp index b5b7ab2a46..dc1f44f995 100644 --- a/Packet++/src/IPv6Layer.cpp +++ b/Packet++/src/IPv6Layer.cpp @@ -193,7 +193,7 @@ namespace pcpp return getExtensionOfType() != nullptr; } - void IPv6Layer::parseNextLayer(ParserConfiguration const& config) + void IPv6Layer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); diff --git a/Packet++/src/IcmpLayer.cpp b/Packet++/src/IcmpLayer.cpp index 8326ce287e..6d1554fc66 100644 --- a/Packet++/src/IcmpLayer.cpp +++ b/Packet++/src/IcmpLayer.cpp @@ -561,7 +561,7 @@ namespace pcpp return header; } - void IcmpLayer::parseNextLayer(ParserConfiguration const& config) + void IcmpLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); diff --git a/Packet++/src/LLCLayer.cpp b/Packet++/src/LLCLayer.cpp index 25d537d940..096ccda677 100644 --- a/Packet++/src/LLCLayer.cpp +++ b/Packet++/src/LLCLayer.cpp @@ -24,7 +24,7 @@ namespace pcpp header->control = control; } - void LLCLayer::parseNextLayer(ParserConfiguration const& config) + void LLCLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(llc_header)) return; diff --git a/Packet++/src/LdapLayer.cpp b/Packet++/src/LdapLayer.cpp index a19e7f6748..e112efb27c 100644 --- a/Packet++/src/LdapLayer.cpp +++ b/Packet++/src/LdapLayer.cpp @@ -360,7 +360,7 @@ namespace pcpp return LdapOperationType::fromUintValue(tagType); } - void LdapLayer::parseNextLayer(ParserConfiguration const& config) + void LdapLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen || headerLen == 0) diff --git a/Packet++/src/MplsLayer.cpp b/Packet++/src/MplsLayer.cpp index 025a9451fb..bf8be778e6 100644 --- a/Packet++/src/MplsLayer.cpp +++ b/Packet++/src/MplsLayer.cpp @@ -101,7 +101,7 @@ namespace pcpp return true; } - void MplsLayer::parseNextLayer(ParserConfiguration const& config) + void MplsLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen < headerLen + 1) diff --git a/Packet++/src/NflogLayer.cpp b/Packet++/src/NflogLayer.cpp index 011b2f6d53..9869c744b2 100644 --- a/Packet++/src/NflogLayer.cpp +++ b/Packet++/src/NflogLayer.cpp @@ -37,7 +37,7 @@ namespace pcpp return tlv; } - void NflogLayer::parseNextLayer(ParserConfiguration const& config) + void NflogLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(nflog_header)) { diff --git a/Packet++/src/NullLoopbackLayer.cpp b/Packet++/src/NullLoopbackLayer.cpp index fbb5100a38..559086d304 100644 --- a/Packet++/src/NullLoopbackLayer.cpp +++ b/Packet++/src/NullLoopbackLayer.cpp @@ -50,7 +50,7 @@ namespace pcpp *m_Data = family; } - void NullLoopbackLayer::parseNextLayer(ParserConfiguration const& config) + void NullLoopbackLayer::doParseNextLayer(ParserConfiguration const& config) { uint8_t* payload = m_Data + sizeof(uint32_t); size_t payloadLen = m_DataLen - sizeof(uint32_t); diff --git a/Packet++/src/PPPoELayer.cpp b/Packet++/src/PPPoELayer.cpp index 08325fc75b..517a9b9fc2 100644 --- a/Packet++/src/PPPoELayer.cpp +++ b/Packet++/src/PPPoELayer.cpp @@ -40,7 +40,7 @@ namespace pcpp /// PPPoESessionLayer /// ~~~~~~~~~~~~~~~~~ - void PPPoESessionLayer::parseNextLayer(ParserConfiguration const& config) + void PPPoESessionLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SSHLayer.cpp b/Packet++/src/SSHLayer.cpp index 43c8f4e3e2..7ef1db2029 100644 --- a/Packet++/src/SSHLayer.cpp +++ b/Packet++/src/SSHLayer.cpp @@ -28,7 +28,7 @@ namespace pcpp return new SSHEncryptedMessage(data, dataLen, prevLayer, packet); } - void SSHLayer::parseNextLayer(ParserConfiguration const& config) + void SSHLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SSLLayer.cpp b/Packet++/src/SSLLayer.cpp index 6113ac3369..970d2b4a0d 100644 --- a/Packet++/src/SSLLayer.cpp +++ b/Packet++/src/SSLLayer.cpp @@ -88,7 +88,7 @@ namespace pcpp return len; } - void SSLLayer::parseNextLayer(ParserConfiguration const& config) + void SSLLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/SipLayer.cpp b/Packet++/src/SipLayer.cpp index bb3ddbbea8..35b6444952 100644 --- a/Packet++/src/SipLayer.cpp +++ b/Packet++/src/SipLayer.cpp @@ -64,7 +64,7 @@ namespace pcpp return contentLengthField; } - void SipLayer::parseNextLayer(ParserConfiguration const& config) + void SipLayer::doParseNextLayer(ParserConfiguration const& config) { if (getLayerPayloadSize() == 0) return; diff --git a/Packet++/src/Sll2Layer.cpp b/Packet++/src/Sll2Layer.cpp index b5a066d80e..219746f832 100644 --- a/Packet++/src/Sll2Layer.cpp +++ b/Packet++/src/Sll2Layer.cpp @@ -56,7 +56,7 @@ namespace pcpp return setLinkLayerAddr(macAddrAsArr, 6); } - void Sll2Layer::parseNextLayer(ParserConfiguration const& config) + void Sll2Layer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(sll2_header)) return; diff --git a/Packet++/src/SllLayer.cpp b/Packet++/src/SllLayer.cpp index 7f94cd7d10..3616dca436 100644 --- a/Packet++/src/SllLayer.cpp +++ b/Packet++/src/SllLayer.cpp @@ -48,7 +48,7 @@ namespace pcpp return setLinkLayerAddr(macAddrAsArr, 6); } - void SllLayer::parseNextLayer(ParserConfiguration const& config) + void SllLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(sll_header)) return; diff --git a/Packet++/src/SomeIpLayer.cpp b/Packet++/src/SomeIpLayer.cpp index f89f5d8b5b..7cb3158026 100644 --- a/Packet++/src/SomeIpLayer.cpp +++ b/Packet++/src/SomeIpLayer.cpp @@ -255,7 +255,7 @@ namespace pcpp payloadLength); } - void SomeIpLayer::parseNextLayer(ParserConfiguration const& config) + void SomeIpLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/StpLayer.cpp b/Packet++/src/StpLayer.cpp index 19ce06be73..738b31fce3 100644 --- a/Packet++/src/StpLayer.cpp +++ b/Packet++/src/StpLayer.cpp @@ -79,7 +79,7 @@ namespace pcpp setType(0x80); } - void StpTopologyChangeBPDULayer::parseNextLayer(ParserConfiguration const& config) + void StpTopologyChangeBPDULayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(stp_tcn_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_tcn_bpdu), this, m_Packet); @@ -224,7 +224,7 @@ namespace pcpp getStpConfHeader()->forwardDelay = value; } - void StpConfigurationBPDULayer::parseNextLayer(ParserConfiguration const& config) + void StpConfigurationBPDULayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(stp_conf_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_conf_bpdu), this, m_Packet); @@ -239,7 +239,7 @@ namespace pcpp setType(0x2); } - void RapidStpLayer::parseNextLayer(ParserConfiguration const& config) + void RapidStpLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen > sizeof(rstp_conf_bpdu)) m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(rstp_conf_bpdu), this, m_Packet); diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index f3befce0f1..fe9818df88 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -356,7 +356,7 @@ namespace pcpp return *this; } - void TcpLayer::parseNextLayer(ParserConfiguration const& config) + void TcpLayer::doParseNextLayer(ParserConfiguration const& config) { const size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/TextBasedProtocol.cpp b/Packet++/src/TextBasedProtocol.cpp index b0bb03285c..5f3e764b36 100644 --- a/Packet++/src/TextBasedProtocol.cpp +++ b/Packet++/src/TextBasedProtocol.cpp @@ -403,7 +403,7 @@ namespace pcpp return result; } - void TextBasedProtocolMessage::parseNextLayer(ParserConfiguration const& config) + void TextBasedProtocolMessage::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/TpktLayer.cpp b/Packet++/src/TpktLayer.cpp index 6e61a8b87b..057a3ab57b 100644 --- a/Packet++/src/TpktLayer.cpp +++ b/Packet++/src/TpktLayer.cpp @@ -54,7 +54,7 @@ namespace pcpp return "TPKT Layer, version: " + versionStream.str() + ", length: " + lengthStream.str(); } - void TpktLayer::parseNextLayer(ParserConfiguration const& config) + void TpktLayer::doParseNextLayer(ParserConfiguration const& config) { size_t headerLen = getHeaderLen(); if (m_DataLen <= headerLen) diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index 72b35d2359..d83a111746 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -90,7 +90,7 @@ namespace pcpp return checksumRes; } - void UdpLayer::parseNextLayer(ParserConfiguration const& config) + void UdpLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(udphdr)) return; @@ -200,7 +200,7 @@ namespace pcpp m_NextLayer = DoIpLayer::parseDoIpLayer(udpData, udpDataLen, this, m_Packet); if (!m_NextLayer) constructNextLayer(udpData, udpDataLen, m_Packet); - } + } break; } case SomeIP: diff --git a/Packet++/src/VlanLayer.cpp b/Packet++/src/VlanLayer.cpp index 766abfd4f9..6c941c8bbc 100644 --- a/Packet++/src/VlanLayer.cpp +++ b/Packet++/src/VlanLayer.cpp @@ -59,7 +59,7 @@ namespace pcpp getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(7 << 13))) | ((priority & 7) << 13)); } - void VlanLayer::parseNextLayer(ParserConfiguration const& config) + void VlanLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(vlan_header)) return; diff --git a/Packet++/src/VxlanLayer.cpp b/Packet++/src/VxlanLayer.cpp index 9d6513f557..96313ea4e0 100644 --- a/Packet++/src/VxlanLayer.cpp +++ b/Packet++/src/VxlanLayer.cpp @@ -49,7 +49,7 @@ namespace pcpp return "VXLAN Layer"; } - void VxlanLayer::parseNextLayer(ParserConfiguration const& config) + void VxlanLayer::doParseNextLayer(ParserConfiguration const& config) { if (m_DataLen <= sizeof(vxlan_header)) return; From 2a5fe3950f4bd77c1c2930eeaa6327044801e461 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 27 Sep 2025 21:19:47 +0300 Subject: [PATCH 52/52] Lint. --- Packet++/src/ParserConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packet++/src/ParserConfig.cpp b/Packet++/src/ParserConfig.cpp index caa662549c..e50b82b490 100644 --- a/Packet++/src/ParserConfig.cpp +++ b/Packet++/src/ParserConfig.cpp @@ -49,7 +49,7 @@ namespace pcpp // The specific parsing determined based on if the port is src or dst. // A port pairing (21, 21) for example is UB. mapper.addPortMapping(PortPair{ 21, 21 }, UnknownProtocol, false); // Symmetrical connection is UB - mapper.addPortMapping(PortPair::fromSrc(21), FTPControl, true); // FTP control + mapper.addPortMapping(PortPair::fromSrc(21), FTPControl, true); // FTP control mapper.addPortMapping(PortPair::fromDst(20), FTPData, true); // FTP data // SomeIP port mappings