mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
EventRegistry/zeek.bif/init-bare: Add event metadata infrastructure
Introduce a new EventMetadata module and members on EventMgr to register event metadata types.
This commit is contained in:
parent
fc96c81c70
commit
cc7dc60c1e
8 changed files with 218 additions and 1 deletions
|
@ -579,6 +579,21 @@ const io_poll_interval_live = 10 &redef;
|
||||||
## while testing, but should be used sparingly.
|
## while testing, but should be used sparingly.
|
||||||
const running_under_test: bool = F &redef;
|
const running_under_test: bool = F &redef;
|
||||||
|
|
||||||
|
module EventMetadata;
|
||||||
|
|
||||||
|
export {
|
||||||
|
## Enum type for metadata identifiers.
|
||||||
|
type ID: enum {
|
||||||
|
NETWORK_TIMESTAMP = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
## A event metadata entry.
|
||||||
|
type Entry: record {
|
||||||
|
id: EventMetadata::ID; ##< The registered :zeek:see:`EventMetadata::ID` value.
|
||||||
|
val: any; ##< The value. Its type matches what was passed to :zeek:see:`EventMetadata::register`.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
module FTP;
|
module FTP;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -751,6 +766,9 @@ module GLOBAL;
|
||||||
## directly and then remove this alias.
|
## directly and then remove this alias.
|
||||||
type EncapsulatingConnVector: vector of Tunnel::EncapsulatingConn;
|
type EncapsulatingConnVector: vector of Tunnel::EncapsulatingConn;
|
||||||
|
|
||||||
|
## A type alias for event metadata.
|
||||||
|
type event_metadata_vec: vector of EventMetadata::Entry;
|
||||||
|
|
||||||
## Statistics about a :zeek:type:`connection` endpoint.
|
## Statistics about a :zeek:type:`connection` endpoint.
|
||||||
##
|
##
|
||||||
## .. zeek:see:: connection
|
## .. zeek:see:: connection
|
||||||
|
|
16
src/Event.cc
16
src/Event.cc
|
@ -3,6 +3,7 @@
|
||||||
#include "zeek/Event.h"
|
#include "zeek/Event.h"
|
||||||
|
|
||||||
#include "zeek/Desc.h"
|
#include "zeek/Desc.h"
|
||||||
|
#include "zeek/EventRegistry.h"
|
||||||
#include "zeek/Trigger.h"
|
#include "zeek/Trigger.h"
|
||||||
#include "zeek/Val.h"
|
#include "zeek/Val.h"
|
||||||
#include "zeek/iosource/Manager.h"
|
#include "zeek/iosource/Manager.h"
|
||||||
|
@ -182,6 +183,19 @@ void EventMgr::Process() {
|
||||||
// and had the opportunity to spawn new events.
|
// and had the opportunity to spawn new events.
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventMgr::InitPostScript() { iosource_mgr->Register(this, true, false); }
|
void EventMgr::InitPostScript() {
|
||||||
|
// Check if expected types and identifiers are available.
|
||||||
|
const auto& et = zeek::id::find_type<zeek::EnumType>("EventMetadata::ID");
|
||||||
|
if ( ! et )
|
||||||
|
zeek::reporter->FatalError("Failed to find EventMetadata::ID");
|
||||||
|
|
||||||
|
const auto& net_ts_val = et->GetEnumVal(et->Lookup("EventMetadata::NETWORK_TIMESTAMP"));
|
||||||
|
if ( ! net_ts_val )
|
||||||
|
zeek::reporter->FatalError("Failed to lookup EventMetadata::NETWORK_TIMESTAMP");
|
||||||
|
|
||||||
|
if ( ! zeek::event_registry->RegisterMetadata(net_ts_val, zeek::base_type(zeek::TYPE_TIME)) )
|
||||||
|
zeek::reporter->FatalError("Failed to register NETWORK_TIMESTAMP metadata");
|
||||||
|
|
||||||
|
iosource_mgr->Register(this, true, false);
|
||||||
|
}
|
||||||
} // namespace zeek
|
} // namespace zeek
|
||||||
|
|
|
@ -3,11 +3,16 @@
|
||||||
#include "zeek/EventRegistry.h"
|
#include "zeek/EventRegistry.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include "zeek/Desc.h"
|
||||||
#include "zeek/EventHandler.h"
|
#include "zeek/EventHandler.h"
|
||||||
#include "zeek/Func.h"
|
#include "zeek/Func.h"
|
||||||
#include "zeek/RE.h"
|
#include "zeek/RE.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
|
#include "zeek/Traverse.h"
|
||||||
|
#include "zeek/TraverseTypes.h"
|
||||||
|
#include "zeek/Type.h"
|
||||||
|
|
||||||
namespace zeek {
|
namespace zeek {
|
||||||
|
|
||||||
|
@ -164,4 +169,67 @@ void EventGroup::Disable() {
|
||||||
|
|
||||||
void EventGroup::AddFunc(detail::ScriptFuncPtr f) { funcs.insert(f); }
|
void EventGroup::AddFunc(detail::ScriptFuncPtr f) { funcs.insert(f); }
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class EventMetadataTypeRejector : public detail::TraversalCallback {
|
||||||
|
public:
|
||||||
|
detail::TraversalCode PreType(const Type* t) override {
|
||||||
|
if ( visited.count(t) > 0 )
|
||||||
|
return detail::TC_ABORTSTMT;
|
||||||
|
|
||||||
|
visited.insert(t);
|
||||||
|
|
||||||
|
if ( reject.count(t->Tag()) )
|
||||||
|
rejected.push_back(t);
|
||||||
|
|
||||||
|
return detail::TC_CONTINUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<const zeek::Type*> visited;
|
||||||
|
std::vector<const zeek::Type*> rejected;
|
||||||
|
|
||||||
|
std::set<zeek::TypeTag> reject = {TYPE_ANY, TYPE_FUNC, TYPE_FILE, TYPE_OPAQUE};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool EventRegistry::RegisterMetadata(EnumValPtr id, TypePtr type) {
|
||||||
|
static const auto& metadata_id_type = id::find_type<EnumType>("EventMetadata::ID");
|
||||||
|
|
||||||
|
if ( metadata_id_type != id->GetType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto id_int = id->Get();
|
||||||
|
if ( id_int < 0 ) {
|
||||||
|
zeek::reporter->InternalError("Negative enum value %s: %" PRId64, obj_desc_short(id.get()).c_str(), id_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
zeek_uint_t id_uint = static_cast<zeek_uint_t>(id_int);
|
||||||
|
|
||||||
|
if ( auto it = event_metadata_types.find(id_uint); it != event_metadata_types.end() )
|
||||||
|
return same_type(it->second.Type(), type);
|
||||||
|
|
||||||
|
EventMetadataTypeRejector cb;
|
||||||
|
type->Traverse(&cb);
|
||||||
|
|
||||||
|
if ( cb.rejected.size() > 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
event_metadata_types.insert({id_uint, EventMetadataDescriptor{id_uint, std::move(id), std::move(type)}});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventMetadataDescriptor* EventRegistry::LookupMetadata(zeek_uint_t id) const {
|
||||||
|
const auto it = event_metadata_types.find(id);
|
||||||
|
if ( it == event_metadata_types.end() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( it->second.Id() != id ) {
|
||||||
|
zeek::reporter->InternalError("inconsistent metadata descriptor: %" PRIu64 " vs %" PRId64, it->second.Id(), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace zeek
|
} // namespace zeek
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -22,18 +23,55 @@ enum class EventGroupKind {
|
||||||
Module,
|
Module,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EnumVal;
|
||||||
class EventGroup;
|
class EventGroup;
|
||||||
class EventHandler;
|
class EventHandler;
|
||||||
class EventHandlerPtr;
|
class EventHandlerPtr;
|
||||||
class RE_Matcher;
|
class RE_Matcher;
|
||||||
|
class RecordVal;
|
||||||
|
class Type;
|
||||||
|
|
||||||
|
using EnumValPtr = IntrusivePtr<EnumVal>;
|
||||||
using EventGroupPtr = std::shared_ptr<EventGroup>;
|
using EventGroupPtr = std::shared_ptr<EventGroup>;
|
||||||
|
using RecordValPtr = IntrusivePtr<RecordVal>;
|
||||||
|
using TypePtr = IntrusivePtr<Type>;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class ScriptFunc;
|
class ScriptFunc;
|
||||||
using ScriptFuncPtr = zeek::IntrusivePtr<ScriptFunc>;
|
using ScriptFuncPtr = zeek::IntrusivePtr<ScriptFunc>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Well-known event metadata identifiers.
|
||||||
|
*/
|
||||||
|
enum class MetadataType : uint8_t {
|
||||||
|
NetworkTimestamp = 1,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Descriptor for event metadata.
|
||||||
|
*
|
||||||
|
* Event metadata is registered via @ref EventRegistry::RegisterMetadata. The descriptor
|
||||||
|
* holds the metadata identifier and registered type. For the identifier,
|
||||||
|
* *id* is the unsigned int representation, while *id_val* holds the
|
||||||
|
* script-layer zeek::EnumVal.
|
||||||
|
*/
|
||||||
|
class EventMetadataDescriptor {
|
||||||
|
public:
|
||||||
|
EventMetadataDescriptor(zeek_uint_t id, EnumValPtr id_val, TypePtr type)
|
||||||
|
: id(id), id_val(std::move(id_val)), type(std::move(type)) {}
|
||||||
|
|
||||||
|
zeek_uint_t Id() const { return id; }
|
||||||
|
const EnumValPtr& IdVal() const { return id_val; }
|
||||||
|
const TypePtr& Type() const { return type; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
zeek_uint_t id;
|
||||||
|
EnumValPtr id_val;
|
||||||
|
TypePtr type;
|
||||||
|
};
|
||||||
|
|
||||||
// The registry keeps track of all events that we provide or handle.
|
// The registry keeps track of all events that we provide or handle.
|
||||||
class EventRegistry final {
|
class EventRegistry final {
|
||||||
public:
|
public:
|
||||||
|
@ -98,6 +136,23 @@ public:
|
||||||
*/
|
*/
|
||||||
EventGroupPtr LookupGroup(EventGroupKind kind, std::string_view name);
|
EventGroupPtr LookupGroup(EventGroupKind kind, std::string_view name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a script-layer metadata identifier *id* with type *type*.
|
||||||
|
*
|
||||||
|
* @param id The script-level ``EventMetadata::ID`` enum value.
|
||||||
|
* @param type The type to expect for the given metadata identifier.
|
||||||
|
*/
|
||||||
|
bool RegisterMetadata(EnumValPtr id, TypePtr type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup the MetadataDescriptor for metadata identifier *id*
|
||||||
|
*
|
||||||
|
* @param id The metadata identifier as unsigned int.
|
||||||
|
* @return A pointer to a MetadataDescriptor or nullptr.
|
||||||
|
*/
|
||||||
|
const EventMetadataDescriptor* LookupMetadata(zeek_uint_t id) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, std::unique_ptr<EventHandler>, std::less<>> handlers;
|
std::map<std::string, std::unique_ptr<EventHandler>, std::less<>> handlers;
|
||||||
// Tracks whether a given event handler was registered in a
|
// Tracks whether a given event handler was registered in a
|
||||||
|
@ -106,6 +161,9 @@ private:
|
||||||
|
|
||||||
// Map event groups identified by kind and name to their instances.
|
// Map event groups identified by kind and name to their instances.
|
||||||
std::map<std::pair<EventGroupKind, std::string>, std::shared_ptr<EventGroup>, std::less<>> event_groups;
|
std::map<std::pair<EventGroupKind, std::string>, std::shared_ptr<EventGroup>, std::less<>> event_groups;
|
||||||
|
|
||||||
|
// Map for event metadata identifier to their descriptors types.
|
||||||
|
std::unordered_map<zeek_uint_t, EventMetadataDescriptor> event_metadata_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
27
src/zeek.bif
27
src/zeek.bif
|
@ -401,6 +401,33 @@ function current_event_time%(%): time
|
||||||
return zeek::make_intrusive<zeek::TimeVal>(zeek::event_mgr.CurrentEventTime());
|
return zeek::make_intrusive<zeek::TimeVal>(zeek::event_mgr.CurrentEventTime());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
## Register the expected Zeek type for event metadata.
|
||||||
|
##
|
||||||
|
## id: The event metadata identifier.
|
||||||
|
##
|
||||||
|
## t: A type expression or type alias. The type cannot be ``any``, ``func``,
|
||||||
|
## ``file``, ``opaque`` or a composite type containing one of these types.
|
||||||
|
##
|
||||||
|
## Returns: true if the registration was successful, false if *id* is
|
||||||
|
## registered with a different type already, or type is invalid.
|
||||||
|
##
|
||||||
|
## .. zeek:see:: EventMetadata::current EventMetadata::current_all
|
||||||
|
function EventMetadata::register%(id: EventMetadata::ID, t: any%): bool
|
||||||
|
%{
|
||||||
|
const auto& tty = t->GetType();
|
||||||
|
|
||||||
|
if ( tty->Tag() != zeek::TYPE_TYPE )
|
||||||
|
{
|
||||||
|
zeek::emit_builtin_error("register_event_metadata() expects type");
|
||||||
|
return zeek::val_mgr->False();
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumValPtr idvp = {zeek::NewRef{}, id->AsEnumVal()};
|
||||||
|
|
||||||
|
bool r = zeek::event_registry->RegisterMetadata(idvp, tty->AsTypeType()->GetType());
|
||||||
|
return zeek::val_mgr->Bool(r);
|
||||||
|
%}
|
||||||
|
|
||||||
## Returns a system environment variable.
|
## Returns a system environment variable.
|
||||||
##
|
##
|
||||||
## var: The name of the variable whose value to request.
|
## var: The name of the variable whose value to request.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
|
@ -0,0 +1 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
30
testing/btest/core/event-metadata/register-type-errors.zeek
Normal file
30
testing/btest/core/event-metadata/register-type-errors.zeek
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# @TEST-DOC: Verify rejection of certain metadata types.
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: unset ZEEK_ALLOW_INIT_ERRORS; zeek -b %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff .stdout
|
||||||
|
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr
|
||||||
|
|
||||||
|
module App;
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum EventMetadata::ID += {
|
||||||
|
MY_METADATA = 1000,
|
||||||
|
MY_TABLE = 1002,
|
||||||
|
MY_VECTOR = 1003,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type R: record {
|
||||||
|
f: file;
|
||||||
|
a: any;
|
||||||
|
l: function(x: count): bool;
|
||||||
|
};
|
||||||
|
|
||||||
|
event zeek_init()
|
||||||
|
{
|
||||||
|
assert ! EventMetadata::register(MY_METADATA, any);
|
||||||
|
assert ! EventMetadata::register(MY_METADATA, table[count] of any);
|
||||||
|
assert ! EventMetadata::register(MY_METADATA, table[count] of function(x: count): bool);
|
||||||
|
assert ! EventMetadata::register(MY_METADATA, R);
|
||||||
|
assert ! EventMetadata::register(MY_METADATA, vector of R);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue