// See the file "COPYING" in the main distribution directory for copyright. #pragma once #include "zeek/iosource/Packet.h" #include "zeek/packet_analysis/Manager.h" #include "zeek/packet_analysis/Tag.h" namespace zeek::packet_analysis { /** * Main packet analyzer interface. */ class Analyzer { public: /** * Constructor. * * @param name The name for the type of analyzer. The name must match * the one the corresponding Component registers. * @param report_unknown_protocols Flag for whether to report unknown * protocols during packet forwarding. This should generally always be * set to true. */ explicit Analyzer(std::string name, bool report_unknown_protocols = true); /** * Constructor. * * @param tag The tag for the type of analyzer. The tag must map to * the name the corresponding Component registers. */ explicit Analyzer(const Tag& tag); /** * Destructor. */ virtual ~Analyzer() = default; /** * Initialize the analyzer. This method is called after the configuration * was read. Derived classes can override this method to implement custom * initialization. * When overriding this methods, always make sure to call the base-class * version to ensure proper initialization. */ virtual void Initialize(); /** * Returns the tag associated with the analyzer's type. */ const Tag GetAnalyzerTag() const; /** * Returns a textual description of the analyzer's type. This is * what's passed to the constructor and usually corresponds to the * protocol name, e.g., "ARP". */ const char* GetAnalyzerName() const; /** * Returns true if this analyzer's type matches the name passes in. * This is shortcut for comparing GetAnalyzerName() with the given * name. * * @param name The name to check. */ bool IsAnalyzer(const char* name); /** * Analyzes the given packet. A common case is that the analyzed protocol * encapsulates another protocol, which can be determined by an identifier * in the header. In this case, derived classes may use ForwardPacket() to * forward the payload to the corresponding analyzer. * * @param len The number of bytes passed in. As we move along the chain of * analyzers, this is the number of bytes we have left of the packet to * process. * @param data Pointer to the input to process. * @param packet Object that maintains the packet's meta data. * * @return false if the analysis failed, else true. */ virtual bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) = 0; /** * Dumps out debug information to the \c analyzer debug stream. */ void DumpDebug() const; /** * Adds a protocol to this analyzer's dispatcher. * * @param idenfitier The identifier for the protocol being added. * @param child The analyzer that will be called for the new protocol during * forwarding. */ void RegisterProtocol(uint32_t identifier, AnalyzerPtr child); protected: friend class Manager; /** * Looks up the analyzer for the encapsulated protocol based on the given * identifier. * * @param identifier Identifier for the encapsulated protocol. * @return The analyzer registered for the given identifier. Returns a * nullptr if no analyzer is registered. */ AnalyzerPtr Lookup(uint32_t identifier) const; /** * Returns an analyzer based on a script-land definition. * * @param name The script-land identifier for a PacketAnalyzer::Tag value. * @return The defined analyzer if available, else nullptr. */ AnalyzerPtr LoadAnalyzer(const std::string& name); /** * Returns the module name corresponding to the analyzer, i.e. its script-land * namespace. Configuration values for the analyzer are expected in this module. * @return Analyzer's module name. */ std::string GetModuleName() const { return util::fmt("PacketAnalyzer::%s::", GetAnalyzerName()); }; /** * Triggers analysis of the encapsulated packet. The encapsulated protocol * is determined using the given identifier. * * @param packet The packet to analyze. * @param data Reference to the payload pointer into the raw packet. * @param identifier The identifier of the encapsulated protocol. * * @return false if the analysis failed, else true. */ bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet, uint32_t identifier) const; /** * Triggers default analysis of the encapsulated packet if the default analyzer * is set. * * @param packet The packet to analyze. * @param data Reference to the payload pointer into the raw packet. * * @return false if the analysis failed, else true. */ bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const; /** * Reports a Weird with the analyzer's name included in the addl field. * * @param name The name of the weird. * @param packet An optional pointer to a packet to be used for additional * information in the weird output. * @param addl An optional string containing additional information about * the weird. If this is passed, the analyzer's name will be prepended to * it before output. */ void Weird(const char* name, Packet* packet = nullptr, const char* addl = "") const; private: Tag tag; Dispatcher dispatcher; AnalyzerPtr default_analyzer = nullptr; /** * Flag for whether to report unknown protocols in ForwardPacket. */ bool report_unknown_protocols = true; void Init(const Tag& tag); }; using AnalyzerPtr = std::shared_ptr; }