// See the file "COPYING" in the main distribution directory for copyright. #pragma once #include #include "zeek/analyzer/Analyzer.h" #include "zeek/iosource/Packet.h" namespace zeek::analyzer::pia { class PIA; } namespace zeek::packet_analysis { /** * Indicator for a TapAnalyzer to determine what will happen to a packet. */ enum class PacketAction : uint8_t { Deliver, ///< Packet will be delivered to child protocol analyzers. Skip, ///< Processing of this packet will be skipped. }; /** * Reason why delivery of a packet would be skipped. */ enum class SkipReason : uint8_t { None, ///< None is used when the verdict is Deliver. Unknown, ///< Placeholder if no other value fits. BadChecksum, ///< The packet's checksum is invalid and ignore_checksums is false. BadProtoHeader, ///< Something was off with the lengths or offsets in the protocol header. SkipProcessing, ///< The session adapter's connection had skip_further_processing called on it. }; /** * A lightweight analyzer that receives all packets passing through session adapters. * * A use case of tap analyzers is to attach them during HookSetupAnalyzerTree() to * observe all raw packets of a session, including those that are invalid or corrupt * and aren't delivered to child protocol analyzers. * * The Packet class has an *is_orig* field if directionality is required. Additionally, * the Connection instance available during HookSetupAnalyzerTree() can be stored into * a custom TapAnalyzer, allowing to associate packets with a given Connection. However, * the TapAnalyzer interface itself does not provide provisions for this use case. */ class TapAnalyzer { public: virtual ~TapAnalyzer() = default; /** * Hook of a tap analyzer for receiving packet data. * * @param pkt The packet being processed. * @param action Either Deliver or Skip as determined by session analyzers. * @param skip_reason If verdict is Skip, an indication why this packet is skipped, otherwise None. */ virtual void TapPacket(const Packet& pkt, PacketAction action, SkipReason skip_reason) = 0; /** * Hook for when the script-level connection record is updated. * * This is invoked when the session's UpdateConnVal() method has invoked UpdateConnVal() * on all protocol analyzers attached to the session. * * @param conn_val The script-level connection record associated with the * Connection this TapAnalyzer is attached to. */ virtual void UpdateConnVal(RecordVal* conn_val) {} /** * Hook for initialization before tapping begins. * * This method is invoked after a tap analyzer has been added to a SessionAdapter. */ virtual void Init() {}; /** * Hook for when this analyzer is about to be removed and destructed. * * This is invoked when the session's Done() method is invoked, just before * the TapAnalyzer instance is destroyed. */ virtual void Done() {}; }; using TapAnalyzerPtr = std::unique_ptr; namespace IP { class IPBasedAnalyzer; /** * This class represents the interface between the packet analysis framework and * the session analysis framework. One of these should be implemented for each * packet analyzer that intends to forward into the session analysis. */ class SessionAdapter : public analyzer::Analyzer { public: SessionAdapter(const char* name, Connection* conn) : analyzer::Analyzer(name, conn) {} /** * Overridden from parent class. */ void Done() override; /** * Sets the parent packet analyzer for this session adapter. This can't be passed to * the constructor due to the way that SessionAdapter gets instantiated. * * @param p The parent packet analyzer to store */ void SetParent(IPBasedAnalyzer* p) { parent = p; } /** * Returns true if the analyzer determines that in fact a new connection has started * without the connection statement having terminated the previous one, i.e., the new * data is arriving at what's the analyzer for the previous instance. This is used only * for TCP. */ virtual bool IsReuse(double t, const u_char* pkt); /** * Pure virtual method to allow extra session analyzers to be added to this analyzer's * tree of children. This is used by analyzer::Manager when creating the session analyzer * tree. */ virtual void AddExtraAnalyzers(Connection* conn) = 0; /** * Associates a file with the analyzer in which to record all * analyzed input. This must only be called with derived classes that * override the method; the default implementation will abort. * * @param direction One of the CONTENTS_* constants indicating which * direction of the input stream is to be recorded. * * @param f The file to record to. * */ virtual void SetContentsFile(unsigned int direction, FilePtr f); /** * Returns an associated contents file, if any. This must only be * called with derived classes that override the method; the default * implementation will abort. * * @param direction One of the CONTENTS_* constants indicating which * direction the query is for. */ virtual FilePtr GetContentsFile(unsigned int direction) const; /** * Associates a PIA with this analyzer. A PIA takes the * transport-layer input and determine which protocol analyzer(s) to * use for parsing it. */ void SetPIA(analyzer::pia::PIA* arg_PIA) { pia = arg_PIA; } /** * Returns the associated PIA, or null of none. Does not take * ownership. */ analyzer::pia::PIA* GetPIA() const { return pia; } /** * Helper to raise a \c packet_contents event. * * @param data The data to pass to the event. * * @param len The length of \a data. */ void PacketContents(const u_char* data, int len); /** * Adds a TapAnalyzer instance to this session adapter. * * @param ta The TapAnalyzer instance to attach. */ void AddTapAnalyzer(TapAnalyzerPtr ta); /** * Remove a TapAnalyzer instance by raw pointer. * * Note that the TapAnalyzer instance \a ta is pointing at will be destroyed * during the call to RemoveTapAanalyzer() and should be discarded by the caller * immediately. If you call RemoveTapAnalyzer() from within a TapAnalyzer's member * function, ensure not accessing \a this afterwards. * * @param ta The raw pointer to the TapAnalyzer instance to remove. */ bool RemoveTapAnalyzer(const TapAnalyzer* ta); /** * Helper to forward a packet to all attached TapAnalyzer instances. * * @param pkt The packet. * @param verdict Whether the packet will be delivered or skipped. * @param skip_reason If verdict is Skip, should be an indication why this packet is skipped. */ void TapPacket(const Packet* pkt, PacketAction verdict = PacketAction::Deliver, SkipReason skip_reason = SkipReason::None) const; /** * Overridden from parent class, calling UpdateConnVal() on TapAnalyzer instances, too. */ void UpdateConnVal(RecordVal* conn_val) override; protected: IPBasedAnalyzer* parent = nullptr; analyzer::pia::PIA* pia = nullptr; std::vector tap_analyzers; }; } // namespace IP } // namespace zeek::packet_analysis