diff --git a/src/analyzer/protocol/ayiya/AYIYA.cc b/src/analyzer/protocol/ayiya/AYIYA.cc index b97a78570a..5c3812ddc6 100644 --- a/src/analyzer/protocol/ayiya/AYIYA.cc +++ b/src/analyzer/protocol/ayiya/AYIYA.cc @@ -2,9 +2,9 @@ #include "zeek/analyzer/protocol/ayiya/AYIYA.h" -#include "zeek/session/Manager.h" #include "zeek/Func.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" +#include "zeek/packet_analysis/protocol/ip/IP.h" namespace zeek::analyzer::ayiya { @@ -46,8 +46,8 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 caplen -= inner_packet_offset; inner_packet_offset = -1; - IP_Hdr* inner = nullptr; - int result = session_mgr->ParseIPPacket(len, data, next_header, inner); + std::unique_ptr inner; + int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner); if ( result == 0 ) { @@ -66,9 +66,6 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 else ProtocolViolation("AYIYA payload length", reinterpret_cast(data), len); - - if ( result != 0 ) - delete inner; } } // namespace zeek::analyzer::ayiya diff --git a/src/analyzer/protocol/gtpv1/GTPv1.cc b/src/analyzer/protocol/gtpv1/GTPv1.cc index 08d44171ee..f1c432d08d 100644 --- a/src/analyzer/protocol/gtpv1/GTPv1.cc +++ b/src/analyzer/protocol/gtpv1/GTPv1.cc @@ -2,8 +2,8 @@ #include "zeek/analyzer/protocol/gtpv1/GTPv1.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" +#include "zeek/packet_analysis/protocol/ip/IP.h" -#include "zeek/session/Manager.h" #include "zeek/analyzer/protocol/gtpv1/events.bif.h" namespace zeek::analyzer::gtpv1 { @@ -47,8 +47,8 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 caplen -= inner_packet_offset; inner_packet_offset = -1; - IP_Hdr* inner = nullptr; - int result = session_mgr->ParseIPPacket(len, data, next_header, inner); + std::unique_ptr inner = nullptr; + int result = packet_analysis::IP::ParsePacket(len, data, next_header, inner); if ( result == 0 ) { @@ -77,9 +77,6 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 else ProtocolViolation("GTPv1 payload length", reinterpret_cast(odata), olen); - - if ( result != 0 ) - delete inner; } } // namespace zeek::analyzer::gtpv1 diff --git a/src/analyzer/protocol/teredo/Teredo.cc b/src/analyzer/protocol/teredo/Teredo.cc index f697802187..f7a8982b2f 100644 --- a/src/analyzer/protocol/teredo/Teredo.cc +++ b/src/analyzer/protocol/teredo/Teredo.cc @@ -4,10 +4,10 @@ #include "zeek/Conn.h" #include "zeek/IP.h" #include "zeek/Reporter.h" -#include "zeek/session/Manager.h" #include "zeek/ZeekString.h" #include "zeek/RunState.h" #include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h" +#include "zeek/packet_analysis/protocol/ip/IP.h" #include "zeek/analyzer/protocol/teredo/events.bif.h" @@ -94,7 +94,7 @@ bool TeredoEncapsulation::DoParse(const u_char* data, int& len, return false; } -RecordValPtr TeredoEncapsulation::BuildVal(const IP_Hdr* inner) const +RecordValPtr TeredoEncapsulation::BuildVal(const std::unique_ptr& inner) const { static auto teredo_hdr_type = id::find_type("teredo_hdr"); static auto teredo_auth_type = id::find_type("teredo_auth"); @@ -164,8 +164,8 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, return; } - IP_Hdr* inner = nullptr; - int rslt = session_mgr->ParseIPPacket(len, te.InnerIP(), IPPROTO_IPV6, inner); + std::unique_ptr inner = nullptr; + int rslt = packet_analysis::IP::ParsePacket(len, te.InnerIP(), IPPROTO_IPV6, inner); if ( rslt > 0 ) { @@ -175,7 +175,6 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, Weird("Teredo_bubble_with_payload", true); else { - delete inner; ProtocolViolation("Teredo payload length", (const char*) data, len); return; } @@ -193,7 +192,6 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, else { - delete inner; ProtocolViolation("Truncated Teredo or invalid inner IP version", (const char*) data, len); return; } diff --git a/src/analyzer/protocol/teredo/Teredo.h b/src/analyzer/protocol/teredo/Teredo.h index d2d87f7319..f6f377d056 100644 --- a/src/analyzer/protocol/teredo/Teredo.h +++ b/src/analyzer/protocol/teredo/Teredo.h @@ -74,7 +74,7 @@ public: const u_char* Authentication() const { return auth; } - RecordValPtr BuildVal(const IP_Hdr* inner) const; + RecordValPtr BuildVal(const std::unique_ptr& inner) const; protected: bool DoParse(const u_char* data, int& len, bool found_orig, bool found_au); diff --git a/src/packet_analysis/protocol/ip/IP.cc b/src/packet_analysis/protocol/ip/IP.cc index 4e8f5c5766..4d05600e6a 100644 --- a/src/packet_analysis/protocol/ip/IP.cc +++ b/src/packet_analysis/protocol/ip/IP.cc @@ -10,6 +10,7 @@ #include "zeek/Frag.h" #include "zeek/Event.h" #include "zeek/TunnelEncapsulation.h" +#include "zeek/IPAddr.h" using namespace zeek::packet_analysis::IP; @@ -260,3 +261,40 @@ bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) return return_val; } + +int zeek::packet_analysis::IP::ParsePacket(int caplen, const u_char* const pkt, int proto, + std::unique_ptr& inner) + { + if ( proto == IPPROTO_IPV6 ) + { + if ( caplen < (int)sizeof(struct ip6_hdr) ) + return -1; + + const struct ip6_hdr* ip6 = (const struct ip6_hdr*) pkt; + inner = std::make_unique(ip6, false, caplen); + if ( ( ip6->ip6_ctlun.ip6_un2_vfc & 0xF0 ) != 0x60 ) + return -2; + } + + else if ( proto == IPPROTO_IPV4 ) + { + if ( caplen < (int)sizeof(struct ip) ) + return -1; + + const struct ip* ip4 = (const struct ip*) pkt; + inner = std::make_unique(ip4, false); + if ( ip4->ip_v != 4 ) + return -2; + } + + else + { + zeek::reporter->InternalWarning("Bad IP protocol version in IP::ParsePacket"); + return -1; + } + + if ( (uint32_t)caplen != inner->TotalLen() ) + return (uint32_t)caplen < inner->TotalLen() ? -1 : 1; + + return 0; + } diff --git a/src/packet_analysis/protocol/ip/IP.h b/src/packet_analysis/protocol/ip/IP.h index e24f842283..5baec822c1 100644 --- a/src/packet_analysis/protocol/ip/IP.h +++ b/src/packet_analysis/protocol/ip/IP.h @@ -32,4 +32,28 @@ private: zeek::detail::Discarder* discarder = nullptr; }; +/** + * Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4 + * or IPv6 header based on whether it's long enough to contain such a header, + * if version given in the header matches the proto argument, and also checks + * that the payload length field of that header matches the actual + * length of \a pkt given by \a caplen. + * + * @param caplen The length of \a pkt in bytes. + * @param pkt The inner IP packet data. + * @param proto Either IPPROTO_IPV6 or IPPROTO_IPV4 to indicate which IP + * protocol \a pkt corresponds to. + * @param inner The inner IP packet wrapper pointer to be allocated/assigned + * if \a pkt looks like a valid IP packet or at least long enough + * to hold an IP header. + * @return 0 If the inner IP packet appeared valid, else -1 if \a caplen + * is greater than the supposed IP packet's payload length field, -2 + * if the version of the inner header does not match proto or + * 1 if \a caplen is less than the supposed packet's payload length. + * In the -1 case, \a inner may still be non-null if \a caplen was + * long enough to be an IP header, and \a inner is always non-null + * for other return values. + */ +int ParsePacket(int caplen, const u_char* const pkt, int proto, + std::unique_ptr& inner); } diff --git a/src/packet_analysis/protocol/iptunnel/IPTunnel.cc b/src/packet_analysis/protocol/iptunnel/IPTunnel.cc index 1131b2bce7..f6b9f07b12 100644 --- a/src/packet_analysis/protocol/iptunnel/IPTunnel.cc +++ b/src/packet_analysis/protocol/iptunnel/IPTunnel.cc @@ -4,10 +4,10 @@ #include // For DLT_ constants -#include "zeek/session/Manager.h" #include "zeek/RunState.h" #include "zeek/IP.h" #include "zeek/TunnelEncapsulation.h" +#include "zeek/packet_analysis/protocol/ip/IP.h" namespace zeek::packet_analysis::IPTunnel { @@ -45,12 +45,12 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa BifEnum::Tunnel::Type tunnel_type = packet->tunnel_type; int gre_link_type = packet->gre_link_type; - IP_Hdr* inner = nullptr; + std::unique_ptr inner = nullptr; if ( gre_version != 0 ) { // Check for a valid inner packet first. - int result = session_mgr->ParseIPPacket(len, data, proto, inner); + int result = packet_analysis::IP::ParsePacket(len, data, proto, inner); if ( result == -2 ) Weird("invalid_inner_IP_version", packet); else if ( result < 0 ) @@ -59,10 +59,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa Weird("inner_IP_payload_length_mismatch", packet); if ( result != 0 ) - { - delete inner; return false; - } } // Look up to see if we've already seen this IP tunnel, identified @@ -100,7 +97,7 @@ bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* pa * Handles a packet that contains an IP header directly after the tunnel header. */ bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, - const IP_Hdr* inner, + const std::unique_ptr& inner, std::shared_ptr prev, const EncapsulatingConn& ec) { @@ -138,8 +135,6 @@ bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, // Forward the packet back to the IP analyzer. bool return_val = ForwardPacket(len, data, &p); - delete inner; - return return_val; } diff --git a/src/packet_analysis/protocol/iptunnel/IPTunnel.h b/src/packet_analysis/protocol/iptunnel/IPTunnel.h index ddc8e04466..4e8242b17d 100644 --- a/src/packet_analysis/protocol/iptunnel/IPTunnel.h +++ b/src/packet_analysis/protocol/iptunnel/IPTunnel.h @@ -40,7 +40,7 @@ public: * @param ec The most-recently found depth of encapsulation. */ bool ProcessEncapsulatedPacket(double t, const Packet *pkt, - const IP_Hdr* inner, + const std::unique_ptr& inner, std::shared_ptr prev, const EncapsulatingConn& ec); diff --git a/src/session/Manager.cc b/src/session/Manager.cc index 0076cf1305..746fd14ac0 100644 --- a/src/session/Manager.cc +++ b/src/session/Manager.cc @@ -264,43 +264,6 @@ void Manager::ProcessTransportLayer(double t, const Packet* pkt, size_t remainin } } -int Manager::ParseIPPacket(int caplen, const u_char* const pkt, int proto, - IP_Hdr*& inner) - { - if ( proto == IPPROTO_IPV6 ) - { - if ( caplen < (int)sizeof(struct ip6_hdr) ) - return -1; - - const struct ip6_hdr* ip6 = (const struct ip6_hdr*) pkt; - inner = new IP_Hdr(ip6, false, caplen); - if ( ( ip6->ip6_ctlun.ip6_un2_vfc & 0xF0 ) != 0x60 ) - return -2; - } - - else if ( proto == IPPROTO_IPV4 ) - { - if ( caplen < (int)sizeof(struct ip) ) - return -1; - - const struct ip* ip4 = (const struct ip*) pkt; - inner = new IP_Hdr(ip4, false); - if ( ip4->ip_v != 4 ) - return -2; - } - - else - { - reporter->InternalWarning("Bad IP protocol version in ParseIPPacket"); - return -1; - } - - if ( (uint32_t)caplen != inner->TotalLen() ) - return (uint32_t)caplen < inner->TotalLen() ? -1 : 1; - - return 0; - } - bool Manager::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen, const Packet* p) { diff --git a/src/session/Manager.h b/src/session/Manager.h index b65b245203..b798c7f9d4 100644 --- a/src/session/Manager.h +++ b/src/session/Manager.h @@ -106,31 +106,6 @@ public: */ void ProcessTransportLayer(double t, const Packet *pkt, size_t len); - /** - * Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4 - * or IPv6 header based on whether it's long enough to contain such a header, - * if version given in the header matches the proto argument, and also checks - * that the payload length field of that header matches the actual - * length of \a pkt given by \a caplen. - * - * @param caplen The length of \a pkt in bytes. - * @param pkt The inner IP packet data. - * @param proto Either IPPROTO_IPV6 or IPPROTO_IPV4 to indicate which IP - * protocol \a pkt corresponds to. - * @param inner The inner IP packet wrapper pointer to be allocated/assigned - * if \a pkt looks like a valid IP packet or at least long enough - * to hold an IP header. - * @return 0 If the inner IP packet appeared valid, else -1 if \a caplen - * is greater than the supposed IP packet's payload length field, -2 - * if the version of the inner header does not match proto or - * 1 if \a caplen is less than the supposed packet's payload length. - * In the -1 case, \a inner may still be non-null if \a caplen was - * long enough to be an IP header, and \a inner is always non-null - * for other return values. - */ - int ParseIPPacket(int caplen, const u_char* const pkt, int proto, - IP_Hdr*& inner); - unsigned int SessionMemoryUsage(); unsigned int SessionMemoryUsageVals();