zeek/src/analyzer/Manager.h
2013-11-26 11:22:23 -08:00

402 lines
11 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
/**
* The central management unit for registering and instantiating analyzers.
*
* For each protocol that Bro supports, there's one class derived from
* analyzer::Analyzer. Once we have decided that a connection's payload is to
* be parsed as a given protocol, we instantiate the corresponding
* analyzer-derived class and add the new instance as a child node into the
* connection's analyzer tree.
*
* In addition to the analyzer-derived class itself, for each protocol
* there's also "meta-class" derived from analyzer::Component that describes
* the analyzer, including status information on if that particular protocol
* analysis is currently enabled.
*
* To identify an analyzer (or to be precise: a component), the manager
* maintains mappings of (1) analyzer::Tag to component, and (2)
* human-readable analyzer name to component.
*/
#ifndef ANALYZER_MANAGER_H
#define ANALYZER_MANAGER_H
#include <queue>
#include "Analyzer.h"
#include "Component.h"
#include "Tag.h"
#include "plugin/ComponentManager.h"
#include "../Dict.h"
#include "../net_util.h"
#include "../IP.h"
#include "analyzer/analyzer.bif.h"
namespace analyzer {
/**
* Class maintaining and scheduling available protocol analyzers.
*
* The manager maintains a registry of all available protocol analyzers,
* including a mapping between their textual names and analyzer::Tag. It
* instantantiates new analyzers on demand. For new connections, the manager
* sets up their initial analyzer tree, including adding the right \c PIA,
* respecting well-known ports, and tracking any analyzers specifically
* scheduled for individidual connections.
*
* Note that we keep the public interface of this class free of std::*
* classes. This allows to external analyzer code to potentially use a
* different C++ standard library.
*/
class Manager : public plugin::ComponentManager<Tag, Component> {
public:
/**
* Constructor.
*/
Manager();
/**
* Destructor.
*/
~Manager();
/**
* First-stage initializion of the manager. This is called early on
* during Bro's initialization, before any scripts are processed.
*/
void InitPreScript();
/**
* Second-stage initialization of the manager. This is called late
* during Bro's initialization after any scripts are processed.
*/
void InitPostScript();
/**
* Finished the manager's operations.
*/
void Done();
/**
* Dumps out the state of all registered analyzers to the \c analyzer
* debug stream. Should be called only after any \c bro_init events
* have executed to ensure that any of their changes are applied.
*/
void DumpDebug(); // Called after bro_init() events.
/**
* Enables an analyzer type. Only enabled analyzers will be
* instantiated for new connections.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(Tag tag);
/**
* Enables an analyzer type. Only enabled analyzers will be
* instantiated for new connections.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*
* @return True if successful.
*/
bool EnableAnalyzer(EnumVal* tag);
/**
* Enables an analyzer type. Disabled analyzers will not be
* instantiated for new connections.
*
* @param tag The analyzer's tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(Tag tag);
/**
* Enables an analyzer type. Disabled analyzers will not be
* instantiated for new connections.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*
* @return True if successful.
*/
bool DisableAnalyzer(EnumVal* tag);
/**
* Disables all currently registered analyzers.
*/
void DisableAllAnalyzers();
/**
* Returns the tag associated with an analyer name, or the tag
* associated with an error if no such analyzer exists.
*
* @param name The canonical analyzer name to check.
*/
Tag GetAnalyzerTag(const char* name);
/**
* Returns true if an analyzer is enabled.
*
* @param tag The analyzer's tag.
*/
bool IsEnabled(Tag tag);
/**
* Returns true if an analyzer is enabled.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*/
bool IsEnabled(EnumVal* tag);
/**
* Registers a well-known port for an analyzer. Once registered,
* connection on that port will start with a corresponding analyzer
* assigned.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*
* @param port The well-known port.
*
* @return True if successful.
*/
bool RegisterAnalyzerForPort(EnumVal* tag, PortVal* port);
/**
* Registers a well-known port for an analyzer. Once registered,
* connection on that port will start with a corresponding analyzer
* assigned.
*
* @param tag The analyzer's tag.
*
* @param proto The port's protocol.
*
* @param port The port's number.
*
* @return True if successful.
*/
bool RegisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port);
/**
* Unregisters a well-known port for an anlyzers.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*
* @param port The well-known port.
*
* @return True if successful (incl. when the port wasn't actually
* registered for the analyzer).
*
*/
bool UnregisterAnalyzerForPort(EnumVal* tag, PortVal* port);
/**
* Unregisters a well-known port for an anlyzers.
*
* @param tag The analyzer's tag.
*
* @param proto The port's protocol.
*
* @param port The port's number.
*
* @param tag The analyzer's tag as an enum of script type \c
* Analyzer::Tag.
*/
bool UnregisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port);
/**
* Instantiates a new analyzer instance for a connection.
*
* @param tag The analyzer's tag.
*
* @param conn The connection the analyzer is to be associated with.
*
* @return The new analyzer instance. Note that the analyzer will not
* have been added to the connection's analyzer tree yet. Returns
* null if tag is invalid, the requested analyzer is disabled, or the
* analyzer can't be instantiated.
*/
Analyzer* InstantiateAnalyzer(Tag tag, Connection* c);
/**
* Instantiates a new analyzer instance for a connection.
*
* @param name The name of the analyzer.
*
* @param conn The connection the analyzer is to be associated with.
*
* @return The new analyzer instance. Note that the analyzer will not
* have been added to the connection's analyzer tree yet. Returns
* null if the name is not known or if the requested analyzer that is
* disabled.
*/
Analyzer* InstantiateAnalyzer(const char* name, Connection* c);
/**
* Given the first packet of a connection, builds its initial
* analyzer tree.
*
* @param conn The connection to add the initial set of analyzers to.
*
* @return False if the tree cannot be build; that's usually an
* internally error.
*/
bool BuildInitialAnalyzerTree(Connection* conn);
/**
* Schedules a particular analyzer for an upcoming connection. Once
* the connection is seen, BuildInitAnalyzerTree() will add the
* specified analyzer to its tree.
*
* @param orig The connection's anticipated originator address.
* 0.0.0.0 can be used as a wildcard matching any originator.
*
* @param resp The connection's anticipated responder address (no
* wilcard).
*
* @param resp_p The connection's anticipated responder port.
*
* @param proto The connection's anticipated transport protocol.
*
* @param analyzer The analyzer to use once the connection is seen.
*
* @param timeout An interval after which to timeout the request to
* schedule this analyzer. Must be non-zero.
*/
void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, uint16 resp_p,
TransportProto proto, Tag analyzer, double timeout);
/**
* Schedules a particular analyzer for an upcoming connection. Once
* the connection is seen, BuildInitAnalyzerTree() will add the
* specified analyzer to its tree.
*
* @param orig The connection's anticipated originator address. 0 can
* be used as a wildcard matching any originator.
*
* @param resp The The connection's anticipated responder address (no
* wilcard).
*
* @param resp_p The connection's anticipated responder port.
*
* @param proto The connection's anticipated transport protocol.
*
* @param analyzer The name of the analyzer to use once the
* connection is seen.
*
* @param timeout An interval after which to timeout the request to
* schedule this analyzer. Must be non-zero.
*/
void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, uint16 resp_p,
TransportProto proto, const char* analyzer,
double timeout);
/**
* Schedules a particular analyzer for an upcoming connection. Once
* the connection is seen, BuildInitAnalyzerTree() will add the
* specified analyzer to its tree.
*
* @param orig The connection's anticipated originator address. 0 can
* be used as a wildcard matching any originator.
*
* @param resp The connection's anticipated responder address (no
* wilcard).
*
* @param resp_p The connection's anticipated responder port.
*
* @param analyzer The analyzer to use once the connection is seen as
* an enum value of script-type \c Analyzer::Tag.
*
* @param timeout An interval after which to timeout the request to
* schedule this analyzer. Must be non-zero.
*/
void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, PortVal* resp_p,
Val* analyzer, double timeout);
private:
typedef set<Tag> tag_set;
typedef map<uint32, tag_set*> analyzer_map_by_port;
tag_set* LookupPort(PortVal* val, bool add_if_not_found);
tag_set* LookupPort(TransportProto proto, uint32 port, bool add_if_not_found);
tag_set GetScheduled(const Connection* conn);
void ExpireScheduledAnalyzers();
analyzer_map_by_port analyzers_by_port_tcp;
analyzer_map_by_port analyzers_by_port_udp;
Tag analyzer_backdoor;
Tag analyzer_connsize;
Tag analyzer_interconn;
Tag analyzer_stepping;
Tag analyzer_tcpstats;
//// Data structures to track analyzed scheduled for future connections.
// The index for a scheduled connection.
struct ConnIndex {
IPAddr orig;
IPAddr resp;
uint16 resp_p;
uint16 proto;
ConnIndex(const IPAddr& _orig, const IPAddr& _resp,
uint16 _resp_p, uint16 _proto);
ConnIndex();
bool operator<(const ConnIndex& other) const;
};
// Information associated with a scheduled connection.
struct ScheduledAnalyzer {
ConnIndex conn;
Tag analyzer;
double timeout;
struct Comparator {
bool operator() (ScheduledAnalyzer* a, ScheduledAnalyzer* b) {
return a->timeout > b->timeout;
}
};
};
typedef std::multimap<ConnIndex, ScheduledAnalyzer*> conns_map;
typedef std::priority_queue<ScheduledAnalyzer*,
vector<ScheduledAnalyzer*>,
ScheduledAnalyzer::Comparator> conns_queue;
conns_map conns;
conns_queue conns_by_timeout;
};
}
extern analyzer::Manager* analyzer_mgr;
// Macros for anayzer debug logging which include the connection id into the
// message.
#ifdef DEBUG
# define DBG_ANALYZER(conn, txt) \
DBG_LOG(DBG_ANALYZER, "%s " txt, \
fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \
conn->RespAddr(), ntohs(conn->RespPort())));
# define DBG_ANALYZER_ARGS(conn, fmt, args...) \
DBG_LOG(DBG_ANALYZER, "%s " fmt, \
fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \
conn->RespAddr(), ntohs(conn->RespPort())), ##args);
#else
# define DBG_ANALYZER(conn, txt)
# define DBG_ANALYZER_ARGS(conn, fmt, args...)
#endif
#endif