From 2bbce6b15f9bddd55f8f1c3b494413d81532989b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 4 Apr 2013 18:36:44 -0700 Subject: [PATCH] Documenting Analyzer API, plus some cleanup. --- src/AYIYA.h | 1 - src/GTPv1.h | 1 - src/Syslog-binpac.h | 1 - src/TCP.cc | 6 - src/Teredo.h | 1 - src/analyzer/Analyzer.cc | 31 ++ src/analyzer/Analyzer.h | 809 ++++++++++++++++++++++++++++--------- src/protocols/http/HTTP.cc | 2 +- 8 files changed, 646 insertions(+), 206 deletions(-) diff --git a/src/AYIYA.h b/src/AYIYA.h index 563cf86613..c0897d84ff 100644 --- a/src/AYIYA.h +++ b/src/AYIYA.h @@ -16,7 +16,6 @@ public: { return new AYIYA_Analyzer(conn); } protected: - friend class AnalyzerTimer; void ExpireTimer(double t); binpac::AYIYA::AYIYA_Conn* interp; diff --git a/src/GTPv1.h b/src/GTPv1.h index 89befa04bf..2e4a405878 100644 --- a/src/GTPv1.h +++ b/src/GTPv1.h @@ -16,7 +16,6 @@ public: { return new GTPv1_Analyzer(conn); } protected: - friend class AnalyzerTimer; void ExpireTimer(double t); binpac::GTPv1::GTPv1_Conn* interp; diff --git a/src/Syslog-binpac.h b/src/Syslog-binpac.h index e6d05df356..176f2d5b70 100644 --- a/src/Syslog-binpac.h +++ b/src/Syslog-binpac.h @@ -19,7 +19,6 @@ public: { return new Syslog_Analyzer_binpac(conn); } protected: - friend class AnalyzerTimer; void ExpireTimer(double t); int did_session_done; diff --git a/src/TCP.cc b/src/TCP.cc index 058e6608ca..004deb2edd 100644 --- a/src/TCP.cc +++ b/src/TCP.cc @@ -1556,12 +1556,6 @@ void TCP_Analyzer::ConnDeleteTimer(double t) Conn()->DeleteTimer(t); } -// The following need to be consistent with bro.init. -#define CONTENTS_NONE 0 -#define CONTENTS_ORIG 1 -#define CONTENTS_RESP 2 -#define CONTENTS_BOTH 3 - void TCP_Analyzer::SetContentsFile(unsigned int direction, BroFile* f) { if ( direction == CONTENTS_NONE ) diff --git a/src/Teredo.h b/src/Teredo.h index 4f38b29947..f8cc0a15d7 100644 --- a/src/Teredo.h +++ b/src/Teredo.h @@ -47,7 +47,6 @@ public: } protected: - friend class AnalyzerTimer; void ExpireTimer(double t); bool valid_orig; diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index ff02e83f18..0bc8d28c8f 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -7,8 +7,39 @@ #include "../PIA.h" #include "../Event.h" +namespace analyzer { + + +class AnalyzerTimer : public Timer { +public: + AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer, + double arg_t, int arg_do_expire, TimerType arg_type); + + virtual ~AnalyzerTimer(); + + void Dispatch(double t, int is_expire); + +protected: + AnalyzerTimer() {} + + void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire); + + Analyzer* analyzer; + analyzer_timer_func timer; + int do_expire; +}; + +} + using namespace analyzer; +AnalyzerTimer::AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer, + double arg_t, int arg_do_expire, TimerType arg_type) + : Timer(arg_t, arg_type) + { + Init(arg_analyzer, arg_timer, arg_do_expire); + } + AnalyzerTimer::~AnalyzerTimer() { analyzer->RemoveTimer(this); diff --git a/src/analyzer/Analyzer.h b/src/analyzer/Analyzer.h index 704c131bca..07e5d5acf4 100644 --- a/src/analyzer/Analyzer.h +++ b/src/analyzer/Analyzer.h @@ -17,270 +17,556 @@ class PIA; class IP_Hdr; class TCP_ApplicationAnalyzer; -namespace analyzer { class Analyzer; } - namespace analyzer { -typedef list analyzer_list; - -typedef uint32 ID; - -typedef void (Analyzer::*analyzer_timer_func)(double t); - -// FIXME: This is a copy of ConnectionTimer, which we may eventually be -// able to get rid of. -class AnalyzerTimer : public Timer { -public: - AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer, - double arg_t, int arg_do_expire, TimerType arg_type) - : Timer(arg_t, arg_type) - { Init(arg_analyzer, arg_timer, arg_do_expire); } - virtual ~AnalyzerTimer(); - - void Dispatch(double t, int is_expire); - -protected: - AnalyzerTimer() {} - - void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire); - - Analyzer* analyzer; - analyzer_timer_func timer; - int do_expire; -}; - - -// Main analyzer interface. -// -// Each analyzer is part of a tree, having a parent analyzer and an -// arbitrary number of child analyzers. Each analyzer also has a list of -// *suppport analyzers*. All its input first passes through this list of -// support analyzers, which can perform arbitrary preprocessing. Support -// analyzers share the same interface as regular analyzers, except that -// they are unidirectional, i.e., they see only one side of a connection. -// -// When overiding any of these methods, always make sure to call the -// base-class version first. - +class Analyzer; +class AnalyzerTimer; class SupportAnalyzer; class OutputHandler; +typedef list analyzer_list; +typedef uint32 ID; +typedef void (Analyzer::*analyzer_timer_func)(double t); + + /** + * XXX + */ +class OutputHandler { +public: + virtual ~OutputHandler() { } + + virtual void DeliverPacket(int len, const u_char* data, + bool orig, int seq, + const IP_Hdr* ip, int caplen) + { } + virtual void DeliverStream(int len, const u_char* data, + bool orig) { } + virtual void Undelivered(int seq, int len, bool orig) { } +}; + + +/** + * Main analyzer interface. + * + * Each analyzer is part of a tree, having a parent analyzer and an arbitrary + * number of child analyzers. Each analyzer also has a list of + * SupportAnalyzer. All analyzer input first passes through this list of + * support analyzers, which can perform arbitrary preprocessing. + * + * When overiding any of the class' methods, always make sure to call the + * base-class version first. + */ class Analyzer { public: - // "name" must match the one used in + /** + * Constructor. + * + * @param name A name for the protocol the analyzer is parsing. The + * name must match the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + */ Analyzer(const char* name, Connection* conn); + + /** + * Destructor. + */ virtual ~Analyzer(); + /** + * Initializes the analyzer before input processing starts. + */ virtual void Init(); + + /** + * Finishes the analyzer's operation after all input has been parsed. + */ virtual void Done(); - // Pass data to the analyzer (it's automatically passed through its - // support analyzers first). We have packet-wise and stream-wise - // interfaces. For the packet-interface, some analyzers may require - // more information than others, so IP/caplen and seq may or may - // not be set. - void NextPacket(int len, const u_char* data, bool orig, + /** + * Passes packet input to the analyzer for processing. The analyzer + * will process the input with any support analyzers first and then + * forward the data to DeliverStream(), which derived classes can + * override. + * + * Note that there is a separate method for stream input, + * NextStream(). + * + * @param len The number of bytes passed in. + * + * @param data Pointer the input to process. + * + * @param is_orig True if this is originator-side input. + * + * @param seq Current sequence number, if available (only supported + * if the data is coming from the TCP analyzer. + * + * @param ip An IP packet header associated with the data, if + * available. + * + * @param caplen The packet's capture length, if available. + */ + void NextPacket(int len, const u_char* data, bool is_orig, int seq = -1, const IP_Hdr* ip = 0, int caplen = 0); + + /** + * Passes stream input to the analyzer for processing. The analyzer + * will process the input with any support analyzers first and then + * forward the data to DeliverStream(), which derived classes can + * override. + * + * Note that there is a separate method for packet input, + * NextPacket(). + * + * @param len The number of bytes passed in. + * + * @param data Pointer the input to process. + * + * @param is_orig True if this is originator-side input. + */ void NextStream(int len, const u_char* data, bool is_orig); - // Used for data that can't be delivered (e.g., due to a previous - // sequence hole/gap). + /** + * Informs the analyzer about a gap in the TCP stream, i.e., data + * that can't be delivered. This method triggers Undelivered(), which + * derived classes can override. + * + * @param seq The sequence number of the first byte of gap. + * + * @param len The length of the gap. + * + * @param is_orig True if this is about originator-side input. + */ void NextUndelivered(int seq, int len, bool is_orig); - // Report message boundary. (See EndOfData() below.) - void NextEndOfData(bool orig); + /** + * Reports a message boundary. This is a generic method that can be + * used by an Analyzer if all data of a PDU has been delivered, e.g., + * to report that HTTP body has been delivered completely by the HTTP + * analyzer before it starts with the next body. A final EndOfData() + * is automatically generated by the analyzer's Done() method. This + * method triggers EndOfData(), which derived classes can override. + * + * @param is_orig True if this is about originator-side input. + */ + void NextEndOfData(bool is_orig); - // Pass data on to all child analyzer(s). For SupportAnalyzers (see - // below), this is overridden to pass it on to the next sibling (or - // finally to the parent, if it's the last support analyzer). - // - // If we have an associated OutputHandler (see below), the data is - // additionally passed to that, too. For SupportAnalyzers, it is *only* - // delivered to the OutputHandler. + /** + * Forwards packet input on to all child analyzers. If the analyzer + * has an associated OutputHandlers, that one receives the input as + * well. + * + * Parameters are the same as for NextPacket(). + */ virtual void ForwardPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); + + /** + * Forwards stream input on to all child analyzers. If the analyzer + * has an associated OutputHandlers, that one receives the input as + * well. + * + * Parameters are the same as for NextStream(). + */ virtual void ForwardStream(int len, const u_char* data, bool orig); + + /** + * Forwards a sequence gap on to all child analyzers. + * + * Parameters are the same as for NextUndelivered(). + */ virtual void ForwardUndelivered(int seq, int len, bool orig); - // Report a message boundary to all child analyzers + /** + * Forwards an end-of-data notification on to all child analyzers. + * + * Parameters are the same as for NextPacket(). + */ virtual void ForwardEndOfData(bool orig); - ID GetID() const { return id; } - Connection* Conn() const { return conn; } - - // An OutputHandler can be used to get access to data extracted by this - // analyzer (i.e., all data which is passed to - // Forward{Packet,Stream,Undelivered}). We take the ownership of - // the handler. - class OutputHandler { - public: - virtual ~OutputHandler() { } - - virtual void DeliverPacket(int len, const u_char* data, - bool orig, int seq, - const IP_Hdr* ip, int caplen) - { } - virtual void DeliverStream(int len, const u_char* data, - bool orig) { } - virtual void Undelivered(int seq, int len, bool orig) { } - }; - - OutputHandler* GetOutputHandler() const { return output_handler; } - void SetOutputHandler(OutputHandler* handler) - { output_handler = handler; } - - // If an analyzer was triggered by a signature match, this returns the - // name of the signature; nil if not. - const Rule* Signature() const { return signature; } - void SetSignature(const Rule* sig) { signature = sig; } - - void SetSkip(bool do_skip) { skip = do_skip; } - bool Skipping() const { return skip; } - - bool IsFinished() const { return finished; } - - Tag GetAnalyzerTag() const { return tag; } - const string& GetAnalyzerName() const; - bool IsAnalyzer(const char* name); - - // Management of the tree. - // - // We immediately discard an added analyzer if there's already a child - // of the same type. - void AddChildAnalyzer(Analyzer* analyzer) - { AddChildAnalyzer(analyzer, true); } - Analyzer* AddChildAnalyzer(Tag tag); - - void RemoveChildAnalyzer(Analyzer* analyzer); - void RemoveChildAnalyzer(ID id); - - bool HasChildAnalyzer(Tag tag); - - // Recursive; returns nil if not found. - Analyzer* FindChild(ID id); - - // Recursive; returns first found, or nil. - Analyzer* FindChild(Tag tag); - - // Recursive; returns first found, or nil. - Analyzer* FindChild(const string& name); - - const analyzer_list& GetChildren() { return children; } - - Analyzer* Parent() const { return parent; } - void SetParent(Analyzer* p) { parent = p; } - - // Remove this child analyzer from the parent's list. - void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); } - - // Management of support analyzers. Support analyzers are associated - // with a direction, and will only see data in the corresponding flow. - // - // We immediately discard an added analyzer if there's already a child - // of the same type for the same direction. - - // Adds to tail of list. - void AddSupportAnalyzer(SupportAnalyzer* analyzer); - - void RemoveSupportAnalyzer(SupportAnalyzer* analyzer); - - // These are the methods where the analyzer actually gets its input. - // Each analyzer has only to implement the schemes it supports. - - // Packet-wise (or more generally chunk-wise) input. "data" points - // to the payload that the analyzer is supposed to examine. If it's - // part of a full packet, "ip" points to its IP header. An analyzer - // may or may not require to be given the full packet (and its caplen) - // as well. + /** + * Hook for accessing packet input for parsing. This is called by + * NextDeliverPacket() and can be overridden by derived classes. + * Parameters are the same. + */ virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); - // Stream-wise payload input. + /** + * Hook for accessing stream input for parsing. This is called by + * NextDeliverStream() and can be overridden by derived classes. + * Parameters are the same. + */ virtual void DeliverStream(int len, const u_char* data, bool orig); - // If a parent analyzer can't turn a sequence of packets into a stream - // (e.g., due to holes), it can pass the remaining data through this - // method to the child. + /** + * Hook for accessing input gap during parsing. This is called by + * NextUndelivered() and can be overridden by derived classes. + * Parameters are the same. + */ virtual void Undelivered(int seq, int len, bool orig); - // Report a message boundary. This is a generic method that can be used - // by specific Analyzers if all data of a message has been delivered, - // e.g., to report that HTTP body has been delivered completely by the - // HTTP analyzer before it starts with the next body. EndOfData() is - // automatically generated by the analyzer's Done() method. + /** + * Hook for accessing end-of-data notifications. This is called by + * NextEndOfData() and can be overridden by derived classes. + * Parameters are the same. + */ virtual void EndOfData(bool is_orig); - // Occasionally we may find during analysis that we got the direction - // of the connection wrong. In these cases, this method is called - // to swap state if necessary. This will not happen after payload - // has already been passed on, so most analyzers don't need to care. + /** + * Signals the analyzer that its associated connection had its + * endpoint flipped. This can happen if during analysis it turns out + * that we got the direction of the connection wrong. In these + * cases, this method is called to swap state if necessary. This + * will not happen after payload has already been passed on, so most + * analyzers don't need to care. + */ virtual void FlipRoles(); - // Feedback about protocol conformance, to be called by the - // analyzer's processing. The methods raise the correspondiong - // protocol_confirmation and protocol_violation events. + /** + * Returns the analyzer instance's internal ID. These IDs are unique + * across all analyzer instantiated and can thus be used to indentify + * a specific instance. + */ + ID GetID() const { return id; } - // Report that we believe we're parsing the right protocol. This - // should be called as early as possible during a connection's - // life-time. The protocol_confirmed event is only raised once per - // analyzer, even if the method is called multiple times. - virtual void ProtocolConfirmation(); + /** + * Returns the connection that the analyzer is associated with. + */ + Connection* Conn() const { return conn; } - // Return whether the analyzer previously called ProtocolConfirmation() - // at least once before. - bool ProtocolConfirmed() const - { return protocol_confirmed; } + /** + * Returns the OutputHandler associated with the connection, or null + * if none. + */ + OutputHandler* GetOutputHandler() const { return output_handler; } - // Report that we found a significant protocol violation which might - // indicate that the analyzed data is in fact not the expected - // protocol. The protocol_violation event is raised once per call to - // this method so that the script-level may build up some notion of - // how "severely" protocol semantics are violated. + /** + * Associates an OutputHandler with the connnection. + * + * @param handler The handler. + */ + void SetOutputHandler(OutputHandler* handler) + { output_handler = handler; } + + /** + * If this analyzer was activated by a signature match, this returns + * the signature that did so. Returns null otherwise. + */ + const Rule* Signature() const { return signature; } + + /** + * Sets the signature that activated this analyzer, if any. + * + * @param sig The signature. + */ + void SetSignature(const Rule* sig) { signature = sig; } + + /** + * Signals the analyzer to skip all further input processsing. The \a + * Next*() methods check this flag and discard the input if its set. + * + * @param do_skipe If true, further processing will be skipped. + */ + void SetSkip(bool do_skip) { skip = do_skip; } + + /** + * Returns true if the analyzer has been told to skip processing all + * further input. + */ + bool Skipping() const { return skip; } + + /** + * Returns true if Done() has been called. + */ + bool IsFinished() const { return finished; } + + /** + * Returns the tag associated with the analyzer's type. + */ + Tag GetAnalyzerTag() const { return tag; } + + /** + * Returns a textual description of the analyzer's type. This is + * what's passed to the constructor and usally corresponds to the + * protocol name, e.g., "HTTP". + */ + const string& 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); + + /** + * Adds a new child analyzer to the analyzer tree. If an analyzer of + * the same type already exists, the one passes in is silenty + * discarded. + * + * @param analyzer The ananlyzer to add. Takes ownership. + */ + void AddChildAnalyzer(Analyzer* analyzer) + { AddChildAnalyzer(analyzer, true); } + + /** + * Adds a new child analyzer to the analyzer tree. If an analyzer of + * the same type already exists, the one passes in is silenty + * discarded. + * + * @param tag The type of analyzer to add. + */ + Analyzer* AddChildAnalyzer(Tag tag); + + /** + * Removes a child analyzer. It's ok for the analyzer to not to be a + * child, in which case the method does nothing. + * + * @param analyzer The analyzer to remove. + */ + void RemoveChildAnalyzer(Analyzer* analyzer); + + /** + * Removes a child analyzer. It's ok for the analyzer to not to be a + * child, in which case the method does nothing. + * + * @param tag The type of analyzer to remove. + */ + void RemoveChildAnalyzer(ID id); + + /** + * Returns true if analyzer has a direct child of a given type. + * + * @param tag The type of analyzer to check for. + */ + bool HasChildAnalyzer(Tag tag); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer with a specific ID. + * + * @param id The analyzer id to search. This is the ID that GetID() + * returns. + * + * @return The analyzer, or null if not found. + */ + Analyzer* FindChild(ID id); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer of a given type. + * + * @param tag The analyzer type to search. + * + * @return The first analyzer of the given type found, or null if + * none. + */ + Analyzer* FindChild(Tag tag); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer of a given type. + * + * @param name The naem of the analyzer type to search (e.g., + * "HTTP"). + * + * @return The first analyzer of the given type found, or null if + * none. + */ + Analyzer* FindChild(const string& name); + + /** + * Returns a list of all direct child analyzers. + */ + const analyzer_list& GetChildren() { return children; } + + /** + * Returns a pointer to the parent analyzer, or null if this instance + * has not yet been added to an analyzer tree. + */ + Analyzer* Parent() const { return parent; } + + /** + * Sets the parent analyzer. + * + * @param p The new parent. + */ + void SetParent(Analyzer* p) { parent = p; } + + /** + * Remove the analyzer form its parent. The analyzer must have a + * parent associated with it. + */ + void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); } + + /** + * Appends a support analyzer to the current list. + * + * @param analyzer The support analyzer to add. + */ + void AddSupportAnalyzer(SupportAnalyzer* analyzer); + + /** + * Remove a support analyzer. + * + * @param analyzer The analyzer to remove. The function is a no-op if + * that analyzer is not part of the list of support analyzer. + */ + void RemoveSupportAnalyzer(SupportAnalyzer* analyzer); + + /** + * Signals Bro's protocol detection that the analyzer has recognized + * the input to indeed conform to the expected protocol. This should + * be called as early as possible during a connection's life-time. It + * may turn into \c protocol_confirmed event at the script-layer (but + * only once per analyzer for each connection, even if the method is + * called multiple times). + */ + virtual void ProtocolConfirmation(); + + /** + * Signals Bro's protocol detection that the analyzer has found a + * severe protocol violation that could indicate that it's not + * parsing the expected protocol. This turns into \c + * protocol_violation events at the script-layer (one such event is + * raised for each call to this method so that the script-layer can + * built up a notion of how prevalent protocol violations are; the + * more, the less likely it's the right protocol). + * + * @param reason A textual description of the error encountered. + * + * @param data An optional pointer to the malformed data. + * + * @param len If \a data is given, the length of it. + */ virtual void ProtocolViolation(const char* reason, const char* data = 0, int len = 0); - virtual unsigned int MemoryAllocation() const; + /** + * Returns true if ProtocolConfirmation() has been called at least + * once. + */ + bool ProtocolConfirmed() const + { return protocol_confirmed; } - // Called whenever the connection value needs to be updated. Per - // default, this method will be called for each analyzer in the tree. - // Analyzers can use this method to attach additional data to the - // connections. A call to BuildConnVal will in turn trigger a call to - // UpdateConnVal. + /** + * Called whenever the connection value is updated. Per default, this + * method will be called for each analyzer in the tree. Analyzers can + * use this method to attach additional data to the connections. A + * call to BuildConnVal() will in turn trigger a call to + * UpdateConnVal(). + * + * @param conn_val The connenction value being updated. + */ virtual void UpdateConnVal(RecordVal *conn_val); - // The following methods are proxies: calls are directly forwarded - // to the connection instance. These are for convenience only, - // allowing us to reuse more of the old analyzer code unchanged. + /** + * Convinience function that forwards directly to + * Connection::BuildConnVal(). + */ RecordVal* BuildConnVal(); + + /** + * Convinience function that forwards directly to the corresponding + * Connection::Event(). + */ void Event(EventHandlerPtr f, const char* name = 0); + + /** + * Convinience function that forwards directly to the corresponding + * Connection::Event(). + */ void Event(EventHandlerPtr f, Val* v1, Val* v2 = 0); + + /** + * Convinience function that forwards directly to + * Connection::ConnectionEvent(). + */ void ConnectionEvent(EventHandlerPtr f, val_list* vl); + + /** + * Convinience function that forwards directly to the corresponding + * Connection::Weird(). + */ void Weird(const char* name, const char* addl = ""); + /** + * Internal method. + */ + virtual unsigned int MemoryAllocation() const; + protected: friend class AnalyzerTimer; friend class Manager; friend class ::Connection; friend class ::TCP_ApplicationAnalyzer; - // Associates a connection with this analyzer. Must be called if - // we're using the default ctor. + /** + * Associates a connection with this analyzer. Must be called if + * using the default ctor. + * + * @param c The connection. + */ void SetConnection(Connection* c) { conn = c; } - // Creates the given timer to expire at time t. If do_expire - // is true, then the timer is also evaluated when Bro terminates, - // otherwise not. + /** + * Instantiates a new timer associated with the analyzer. + * + * @param timer The callback function to execute when the timer + * fires. + * + * @param t The absolute time when the timer will fire. + * + * @param do_expire If true, the timer will also fire when Bro + * terminates even if \a t has not been reache yet. + * + * @param type The timer's type. + */ void AddTimer(analyzer_timer_func timer, double t, int do_expire, TimerType type); - void RemoveTimer(Timer* t); + /** + * Cancels all timers added previously via AddTimer(). + */ void CancelTimers(); + /** + * Removes a given timer. This is an internal method and shouldn't be + * used by derived class. It does not cancel the timer. + */ + void RemoveTimer(Timer* t); + + /** + * Returnsn true if the analyzer has associated an SupportAnalyzer of a given type. + * + * @param tag The type to check for. + * + * @param orig True if asking about the originator side. + */ bool HasSupportAnalyzer(Tag tag, bool orig); + /** + * Adds a a new child analyzer with the option whether to intialize + * it. This is an internal method. + * + * @param analyzer The analyzer to add. Takes ownership. + * + * @param init If true, Init() will be calle.d + */ void AddChildAnalyzer(Analyzer* analyzer, bool init); + + /** + * Inits all child analyzers. This is an internal method. + */ void InitChildren(); + + /** + * Reorganizes the child data structure. This is an internal method. + */ void AppendNewChildren(); private: @@ -313,39 +599,109 @@ private: static ID id_counter; }; +/** + * Convenience macro to add a new timer. + */ #define ADD_ANALYZER_TIMER(timer, t, do_expire, type) \ AddTimer(analyzer::analyzer_timer_func(timer), (t), (do_expire), (type)) +/** + * Internal convenience macro to iterate over the list of child analyzers. + */ #define LOOP_OVER_CHILDREN(var) \ for ( analyzer::analyzer_list::iterator var = children.begin(); \ var != children.end(); var++ ) +/** + * Internal convenience macro to iterate over the constant list of child + * analyzers. + */ #define LOOP_OVER_CONST_CHILDREN(var) \ for ( analyzer::analyzer_list::const_iterator var = children.begin(); \ var != children.end(); var++ ) +/** + * Convenience macro to iterate over a given list of child analyzers. + */ #define LOOP_OVER_GIVEN_CHILDREN(var, the_kids) \ for ( analyzer::analyzer_list::iterator var = the_kids.begin(); \ var != the_kids.end(); var++ ) +/** + * Convenience macro to iterate over a given constant list of child + * analyzers. + */ #define LOOP_OVER_GIVEN_CONST_CHILDREN(var, the_kids) \ for ( analyzer::analyzer_list::const_iterator var = the_kids.begin(); \ var != the_kids.end(); var++ ) +/** + * Support analyzer preprocess input before it reaches an analyzer's main + * processing. They share the input interface with of an Analyzer but they + * are uni-directional: they receive data only from one side of a connection. + * + */ class SupportAnalyzer : public Analyzer { public: + /** + * Constructor. + * + * @param name A name for the protocol the analyzer is parsing. The + * name must match the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + * + * @param arg_orig: If true, this is a support analyzer for the + * connection originator side, and otherwise for the responder side. + */ SupportAnalyzer(const char* name, Connection* conn, bool arg_orig) : Analyzer(name, conn) { orig = arg_orig; sibling = 0; } + /** + * Destructor. + */ virtual ~SupportAnalyzer() {} + /** + * Returns true if this is a support analyzer for the connection's + * originator side. + */ bool IsOrig() const { return orig; } + /** + * Passes packet input to the next sibling SupportAnalyzer if any, or + * on to the associated main analyzer if none. If however there's an + * output handler associated with this support analyzer, the data is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardPacket. + */ virtual void ForwardPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); + + /** + * Passes stream input to the next sibling SupportAnalyzer if any, or + * on to the associated main analyzer if none. If however there's an + * output handler associated with this support analyzer, the data is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardStream. + */ virtual void ForwardStream(int len, const u_char* data, bool orig); + + /** + * Passes gap information to the next sibling SupportAnalyzer if any, + * or on to the associated main analyzer if none. If however there's + * an output handler associated with this support analyzer, the gap is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardPacket. + */ virtual void ForwardUndelivered(int seq, int len, bool orig); + /** + * Returns the analyzer next sibling, or null if none. + */ SupportAnalyzer* Sibling() const { return sibling; } protected: @@ -359,22 +715,85 @@ private: SupportAnalyzer* sibling; }; +// The following need to be consistent with bro.init. +#define CONTENTS_NONE 0 +#define CONTENTS_ORIG 1 +#define CONTENTS_RESP 2 +#define CONTENTS_BOTH 3 +/** + * Base class for analyzers parsing transport-layer protocols. + */ class TransportLayerAnalyzer : public Analyzer { public: + /** + * Constructor. + * + * @param name A name for the protocol the analyzer is parsing. The + * name must match the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + */ TransportLayerAnalyzer(const char* name, Connection* conn) : Analyzer(name, conn) { pia = 0; } + /** + * Overridden from parent class. + */ virtual void Done(); + + /** + * 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) = 0; + /** + * Associates a file with the analyzer in which to record all + * analyzed input. This must only be called with derived classes that + * overide 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, BroFile* f); + + /** + * Returns an associated contents file, if any. This must only be + * called with derived classes that overide the method; the default + * implementation will abort. + * + * @param direction One of the CONTENTS_* constants indicating which + * direction the query is for. + */ virtual BroFile* 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(PIA* arg_PIA) { pia = arg_PIA; } + + /** + * Returns the associated PIA, or null of none. Does not take + * ownership. + */ PIA* GetPIA() const { return pia; } - // Raises packet_contents event. + /** + * Helper to raise a \c packet_contents event. + * + * @param data The dass to pass to the event. + * + * @param len The length of \a data. + */ void PacketContents(const u_char* data, int len); private: diff --git a/src/protocols/http/HTTP.cc b/src/protocols/http/HTTP.cc index d5d911bbc6..a58d5a6bf3 100644 --- a/src/protocols/http/HTTP.cc +++ b/src/protocols/http/HTTP.cc @@ -170,7 +170,7 @@ void HTTP_Entity::Deliver(int len, const char* data, int trailing_CRLF) DeliverBody(len, data, trailing_CRLF); } -class HTTP_Entity::UncompressedOutput : public analyzer::Analyzer::OutputHandler { +class HTTP_Entity::UncompressedOutput : public analyzer::OutputHandler { public: UncompressedOutput(HTTP_Entity* e) { entity = e; } virtual ~UncompressedOutput() { }