mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Spicy: Provide runtime API to access Zeek-side globals.
This allows to read Zeek global variables from inside Spicy code. The main challenge here is supporting all of Zeek's data type in a type-safe manner. The most straight-forward API is a set of functions `get_<type>(<id>)`, where `<type>` is the Zeek-side type name (e.g., `count`, `string`, `bool`) and `<id>` is the fully scoped name of the Zeek-side global (e.g., `MyModule::Boolean`). These functions then return the corresponding Zeek value, converted in an appropriate Spicy type. Example: Zeek: module Foo; const x: count = 42; const y: string = "xxx"; Spicy: import zeek; assert zeek::get_count("Foo::x") == 42; assert zeek::get_string("Foo::y") == b"xxx"; # returns bytes(!) For container types, the `get_*` function returns an opaque types that can be used to access the containers' values. An additional set of functions `as_<type>` allows converting opaque values of atomic types to Spicy equivalents. Example: Zeek: module Foo; const s: set[count] = { 1, 2 }; const t: table[count] of string = { [1] = "One", [2] = "Two" } Spicy: # Check set membership. local set_ = zeek::get_set("Foo::s"); assert zeek::set_contains(set_, 1) == True # Look up table element. local table_ = zeek::get_table("Foo::t"); local value = zeek::table_lookup(t, 1); assert zeek::as_string(value) == b"One" There are also functions for accessing elements of Zeek-side vectors and records. If any of these `zeek::*` conversion functions fails (e.g., due to a global of that name not existing), it will throw an exception. Design considerations: - We support only reading Zeek variables, not writing. This is both to simplify the API, and also conceptually to avoid offering backdoors into Zeek state that could end up with a very tight coupling of Spicy and Zeek code. - We accept that a single access might be relatively slow due to name lookup and data conversion. This is primarily meant for configuration-style data, not for transferring lots of dynamic state over. - In that spirit, we don't support deep-copying complex data types from Zeek over to Spicy. This is (1) to avoid performance problems when accidentally copying large containers over, potentially even at every access; and (2) to avoid the two sides getting out of sync if one ends up modifying a container without the other being able to see it.
This commit is contained in:
parent
93dd9d6797
commit
4fc57294f1
5 changed files with 750 additions and 9 deletions
|
@ -199,3 +199,312 @@ public function forward_packet(identifier: uint32): void &cxxname="zeek::spicy::
|
||||||
## Gets the network time from Zeek.
|
## Gets the network time from Zeek.
|
||||||
public function network_time(): time &cxxname="zeek::spicy::rt::network_time";
|
public function network_time(): time &cxxname="zeek::spicy::rt::network_time";
|
||||||
|
|
||||||
|
## Opaque handle for a Zeek-side value.
|
||||||
|
public type ZeekVal = __library_type("::zeek::ValPtr");
|
||||||
|
|
||||||
|
## Opaque handle for a Zeek-side record value.
|
||||||
|
public type ZeekRecord = __library_type("::zeek::spicy::rt::ValRecordPtr");
|
||||||
|
|
||||||
|
## Opaque handle for a Zeek-side set value.
|
||||||
|
public type ZeekSet = __library_type("::zeek::spicy::rt::ValSetPtr");
|
||||||
|
|
||||||
|
## Opaque handle for a Zeek-side table value.
|
||||||
|
public type ZeekTable = __library_type("::zeek::spicy::rt::ValTablePtr");
|
||||||
|
|
||||||
|
## Opaque handle for a Zeek-side vector value.
|
||||||
|
public type ZeekVector = __library_type("::zeek::spicy::rt::ValVectorPtr");
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``addr``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_address(id: string): addr &cxxname="zeek::spicy::rt::get_address";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``bool``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_bool(id: string): bool &cxxname="zeek::spicy::rt::get_bool";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``count``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_count(id: string): uint64 &cxxname="zeek::spicy::rt::get_count";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``double``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_double(id: string): real &cxxname="zeek::spicy::rt::get_double";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``enum``.
|
||||||
|
## The value is returned as a string containing the enum's label name, without
|
||||||
|
## any scope. Throws an exception if there's no such Zeek of that name, or if
|
||||||
|
## it's not of the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_enum(id: string): string &cxxname="zeek::spicy::rt::get_enum";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``int``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_int(id: string): int64 &cxxname="zeek::spicy::rt::get_int";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type
|
||||||
|
## ``interval``. Throws an exception if there's no such Zeek of that name, or
|
||||||
|
## if it's not of the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_interval(id: string): interval &cxxname="zeek::spicy::rt::get_interval";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``port``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_port(id: string): port &cxxname="zeek::spicy::rt::get_port";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``record``.
|
||||||
|
## The value is returned as an opaque handle to the record, which can be used
|
||||||
|
## with the ``zeek::record_*()`` functions to access the record's fields.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_record(id: string): ZeekRecord &cxxname="zeek::spicy::rt::get_record";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``set``. The
|
||||||
|
## value is returned as an opaque handle to the set, which can be used with the
|
||||||
|
## ``zeek::set_*()`` functions to access the set's content. Throws an exception
|
||||||
|
## if there's no such Zeek of that name, or if it's not of the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_set(id: string): ZeekSet &cxxname="zeek::spicy::rt::get_set";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``string``.
|
||||||
|
## The string's value is returned as a Spicy ``bytes`` value. Throws an
|
||||||
|
## exception if there's no such Zeek of that name, or if it's not of the
|
||||||
|
## expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_string(id: string): bytes &cxxname="zeek::spicy::rt::get_string";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``subnet``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_subnet(id: string): network &cxxname="zeek::spicy::rt::get_subnet";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``table``.
|
||||||
|
## The value is returned as an opaque handle to the set, which can be used with
|
||||||
|
## the ``zeek::set_*()`` functions to access the set's content. Throws an
|
||||||
|
## exception if there's no such Zeek of that name, or if it's not of the
|
||||||
|
## expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_table(id: string): ZeekTable &cxxname="zeek::spicy::rt::get_table";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``time``.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_time(id: string): time &cxxname="zeek::spicy::rt::get_time";
|
||||||
|
|
||||||
|
## Returns the value of a global Zeek script variable of Zeek type ``vector``.
|
||||||
|
## The value is returned as an opaque handle to the vector, which can be used
|
||||||
|
## with the ``zeek::vector_*()`` functions to access the vector's content.
|
||||||
|
## Throws an exception if there's no such Zeek of that name, or if it's not of
|
||||||
|
## the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek variable to retrieve
|
||||||
|
public function get_vector(id: string): ZeekVector &cxxname="zeek::spicy::rt::get_vector";
|
||||||
|
|
||||||
|
## Returns an opaque handle to a global Zeek script variable. The handle can be
|
||||||
|
## used with the ``zeek::as_*()`` functions to access the variable's value.
|
||||||
|
## Throws an exception if there's no Zeek variable of that name.
|
||||||
|
public function get_value(id: string): ZeekVal &cxxname="zeek::spicy::rt::get_value";
|
||||||
|
|
||||||
|
## Returns a Zeek ``addr`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_address(v: ZeekVal): addr &cxxname="zeek::spicy::rt::as_address";
|
||||||
|
|
||||||
|
## Returns a Zeek ``bool`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_bool(v: ZeekVal): bool &cxxname="zeek::spicy::rt::as_bool";
|
||||||
|
|
||||||
|
## Returns a Zeek ``count`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_count(v: ZeekVal): uint64 &cxxname="zeek::spicy::rt::as_count";
|
||||||
|
|
||||||
|
## Returns a Zeek ``double`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_double(v: ZeekVal): real &cxxname="zeek::spicy::rt::as_double";
|
||||||
|
|
||||||
|
## Returns a Zeek ``enum`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_enum(v: ZeekVal): string &cxxname="zeek::spicy::rt::as_enum";
|
||||||
|
|
||||||
|
## Returns a Zeek ``int`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_int(v: ZeekVal): int64 &cxxname="zeek::spicy::rt::as_int";
|
||||||
|
|
||||||
|
## Returns a Zeek ``interval`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_interval(v: ZeekVal): interval &cxxname="zeek::spicy::rt::as_interval";
|
||||||
|
|
||||||
|
## Returns a Zeek ``port`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_port(v: ZeekVal): port &cxxname="zeek::spicy::rt::as_port";
|
||||||
|
|
||||||
|
## Returns a Zeek ``record`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_record(v: ZeekVal): ZeekRecord &cxxname="zeek::spicy::rt::as_record";
|
||||||
|
|
||||||
|
## Returns a Zeek ``set`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_set(v: ZeekVal): ZeekSet &cxxname="zeek::spicy::rt::as_set";
|
||||||
|
|
||||||
|
## Returns a Zeek ``string`` value refereced by an opaque handle. The string's
|
||||||
|
## value is returned as a Spicy ``bytes`` value. Throws an exception if the
|
||||||
|
## referenced value is not of the expected type.
|
||||||
|
public function as_string(v: ZeekVal): bytes &cxxname="zeek::spicy::rt::as_string";
|
||||||
|
|
||||||
|
## Returns a Zeek ``subnet`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_subnet(v: ZeekVal): network &cxxname="zeek::spicy::rt::as_subnet";
|
||||||
|
|
||||||
|
## Returns a Zeek ``table`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_table(v: ZeekVal): ZeekTable &cxxname="zeek::spicy::rt::as_table";
|
||||||
|
|
||||||
|
## Returns a Zeek ``time`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_time(v: ZeekVal): time &cxxname="zeek::spicy::rt::as_time";
|
||||||
|
|
||||||
|
## Returns a Zeek ``vector`` value refereced by an opaque handle. Throws an
|
||||||
|
## exception if the referenced value is not of the expected type.
|
||||||
|
public function as_vector(v: ZeekVal): ZeekVector &cxxname="zeek::spicy::rt::as_vector";
|
||||||
|
|
||||||
|
## Returns true if a Zeek set contains a given value. Throws an exception if
|
||||||
|
## the given ID does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek set to check
|
||||||
|
## v: value to check for, which must be of the Spicy-side equivalent of the set's key type
|
||||||
|
public function set_contains(id: string, v: any): bool &cxxname="zeek::spicy::rt::set_contains";
|
||||||
|
|
||||||
|
## Returns true if a Zeek set contains a given value. Throws an exception if
|
||||||
|
## the set does not have the expected type.
|
||||||
|
##
|
||||||
|
## s: opaque handle to the Zeek set, as returned by other functions
|
||||||
|
## v: value to check for, which must be of the Spicy-side equivalent of the set's key type
|
||||||
|
public function set_contains(s: ZeekSet, v: any): bool &cxxname="zeek::spicy::rt::set_contains";
|
||||||
|
|
||||||
|
## Returns true if a Zeek table contains a given value. Throws an exception if
|
||||||
|
## the given ID does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek table to check
|
||||||
|
## v: value to check for, which must be of the Spicy-side equivalent of the table's key type
|
||||||
|
public function table_contains(id: string, v: any): bool &cxxname="zeek::spicy::rt::table_contains";
|
||||||
|
|
||||||
|
## Returns true if a Zeek table contains a given value. Throws an exception if
|
||||||
|
## the given ID does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## t: opaque handle to the Zeek table, as returned by other functions
|
||||||
|
## v: value to check for, which must be of the Spicy-side equivalent of the table's key type
|
||||||
|
public function table_contains(t: ZeekTable, v: any): bool &cxxname="zeek::spicy::rt::table_contains";
|
||||||
|
|
||||||
|
## Returns the value associated with a key in a Zeek table. Returns an error
|
||||||
|
## result if the key does not exist in the table. Throws an exception if the
|
||||||
|
## given table ID does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek table to check
|
||||||
|
## v: value to lookup, which must be of the Spicy-side equivalent of the table's key type
|
||||||
|
public function table_lookup(id: string, v: any): optional<ZeekVal> &cxxname="zeek::spicy::rt::table_lookup";
|
||||||
|
|
||||||
|
## Returns the value associated with a key in a Zeek table. Returns an error
|
||||||
|
## result if the key does not exist in the table. Throws an exception if the
|
||||||
|
## given table ID does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## t: opaque handle to the Zeek table, as returned by other functions
|
||||||
|
## v: value to lookup, which must be of the Spicy-side equivalent of the table's key type
|
||||||
|
public function table_lookup(t: ZeekTable, v: any): optional<ZeekVal> &cxxname="zeek::spicy::rt::table_lookup";
|
||||||
|
|
||||||
|
## Returns true if a Zeek record provides a value for a given field. This
|
||||||
|
## includes fields with `&default` values. Throws an exception if the given ID
|
||||||
|
## does not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek record to check field: name of
|
||||||
|
## the field to check
|
||||||
|
public function record_has_value(id: string, field: string): bool &cxxname="zeek::spicy::rt::record_has_field";
|
||||||
|
|
||||||
|
## Returns true if a Zeek record provides a value for a given field.
|
||||||
|
## This includes fields with `&default` values.
|
||||||
|
##
|
||||||
|
## r: opaque handle to the Zeek record, as returned by other functions
|
||||||
|
## field: name of the field to check
|
||||||
|
public function record_has_value(r: ZeekRecord, field: string): bool &cxxname="zeek::spicy::rt::record_has_field";
|
||||||
|
|
||||||
|
## Returns true if the type of a Zeek record has a field of a given name.
|
||||||
|
## Throws an exception if the given ID does not exist, or does not have the
|
||||||
|
## expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek record to check
|
||||||
|
## field: name of the field to check
|
||||||
|
public function record_has_field(id: string, field: string): bool &cxxname="zeek::spicy::rt::record_has_field";
|
||||||
|
|
||||||
|
## Returns true if the type of a Zeek record has a field of a given name.
|
||||||
|
##
|
||||||
|
## r: opaque handle to the Zeek record, as returned by other functions
|
||||||
|
## field: name of the field to check
|
||||||
|
public function record_has_field(r: ZeekRecord, field: string): bool &cxxname="zeek::spicy::rt::record_has_field";
|
||||||
|
|
||||||
|
## Returns a field's value from a Zeek record. Throws an exception if the given
|
||||||
|
## ID does not exist, or does not have the expected type; or if there's no such
|
||||||
|
## field in the record type, or if the field does not have a value.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek record to check
|
||||||
|
## field: name of the field to retrieve
|
||||||
|
public function record_field(id: string, field: string): ZeekVal &cxxname="zeek::spicy::rt::record_field";
|
||||||
|
|
||||||
|
## Returns a field's value from a Zeek record. Throws an exception if the given
|
||||||
|
## record does not have such a field, or if the field does not have a value.
|
||||||
|
##
|
||||||
|
## r: opaque handle to the Zeek record, as returned by other functions
|
||||||
|
## field: name of the field to retrieve
|
||||||
|
public function record_field(r: ZeekRecord, field: string): ZeekVal &cxxname="zeek::spicy::rt::record_field";
|
||||||
|
|
||||||
|
## Returns the value of an index in a Zeek vector. Throws an exception if the
|
||||||
|
## given ID does not exist, or does not have the expected type; or if the index
|
||||||
|
## is out of bounds.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek vector to check
|
||||||
|
## index: index of the element to retrieve
|
||||||
|
public function vector_index(id: string, index: uint64): ZeekVal &cxxname="zeek::spicy::rt::vector_index";
|
||||||
|
|
||||||
|
## Returns the value of an index in a Zeek vector. Throws an exception if the
|
||||||
|
## index is out of bounds.
|
||||||
|
##
|
||||||
|
## v: opaque handle to the Zeek vector, as returned by other functions
|
||||||
|
## index: index of the element to retrieve
|
||||||
|
public function vector_index(v: ZeekVector, index: uint64): ZeekVal &cxxname="zeek::spicy::rt::vector_index";
|
||||||
|
|
||||||
|
## Returns the size of a Zeek vector. Throws an exception if the given ID does
|
||||||
|
## not exist, or does not have the expected type.
|
||||||
|
##
|
||||||
|
## id: fully-qualified name of the global Zeek vector to check
|
||||||
|
public function vector_size(id: string): uint64 &cxxname="zeek::spicy::rt::vector_size";
|
||||||
|
|
||||||
|
## Returns the size of a Zeek vector.
|
||||||
|
##
|
||||||
|
## v: opaque handle to the Zeek vector, as returned by other functions
|
||||||
|
public function vector_size(v: ZeekVector): uint64 &cxxname="zeek::spicy::rt::vector_size";
|
||||||
|
|
||||||
|
|
|
@ -133,15 +133,15 @@ TypePtr rt::create_record_type(const std::string& ns, const std::string& id,
|
||||||
auto decls = std::make_unique<type_decl_list>();
|
auto decls = std::make_unique<type_decl_list>();
|
||||||
|
|
||||||
for ( const auto& f : fields ) {
|
for ( const auto& f : fields ) {
|
||||||
auto attrs = make_intrusive<detail::Attributes>(nullptr, true, false);
|
auto attrs = make_intrusive<::zeek::detail::Attributes>(nullptr, true, false);
|
||||||
|
|
||||||
if ( f.is_optional ) {
|
if ( f.is_optional ) {
|
||||||
auto optional_ = make_intrusive<detail::Attr>(detail::ATTR_OPTIONAL);
|
auto optional_ = make_intrusive<::zeek::detail::Attr>(::zeek::detail::ATTR_OPTIONAL);
|
||||||
attrs->AddAttr(std::move(optional_));
|
attrs->AddAttr(std::move(optional_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( f.is_log ) {
|
if ( f.is_log ) {
|
||||||
auto log_ = make_intrusive<detail::Attr>(detail::ATTR_LOG);
|
auto log_ = make_intrusive<::zeek::detail::Attr>(::zeek::detail::ATTR_LOG);
|
||||||
attrs->AddAttr(std::move(log_));
|
attrs->AddAttr(std::move(log_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
#include <hilti/rt/extension-points.h>
|
#include <hilti/rt/extension-points.h>
|
||||||
#include <hilti/rt/fmt.h>
|
#include <hilti/rt/fmt.h>
|
||||||
#include <hilti/rt/types/all.h>
|
#include <hilti/rt/types/all.h>
|
||||||
|
#include <hilti/rt/util.h>
|
||||||
|
|
||||||
|
#include "IntrusivePtr.h"
|
||||||
|
#include "Type.h"
|
||||||
#include "zeek/Desc.h"
|
#include "zeek/Desc.h"
|
||||||
#include "zeek/Val.h"
|
#include "zeek/Val.h"
|
||||||
#include "zeek/spicy/cookie.h"
|
#include "zeek/spicy/cookie.h"
|
||||||
|
@ -71,9 +74,9 @@ class TypeMismatch : public UsageError {
|
||||||
*/
|
*/
|
||||||
class ParameterMismatch : public TypeMismatch {
|
class ParameterMismatch : public TypeMismatch {
|
||||||
public:
|
public:
|
||||||
ParameterMismatch(const std::string_view& msg, std::string_view location = "")
|
ParameterMismatch(std::string_view msg, std::string_view location = "")
|
||||||
: TypeMismatch(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {}
|
: TypeMismatch(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {}
|
||||||
ParameterMismatch(const std::string_view& have, const TypePtr& want, std::string_view location = "")
|
ParameterMismatch(std::string_view have, const TypePtr& want, std::string_view location = "")
|
||||||
: ParameterMismatch(_fmt(have, want)) {}
|
: ParameterMismatch(_fmt(have, want)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -97,13 +100,13 @@ public:
|
||||||
* Begins registration of a Spicy EVT module. All subsequent, other `register_*()`
|
* Begins registration of a Spicy EVT module. All subsequent, other `register_*()`
|
||||||
* function call will be associated with this module for documentation purposes.
|
* function call will be associated with this module for documentation purposes.
|
||||||
*/
|
*/
|
||||||
void register_spicy_module_begin(const std::string& name, const std::string& description);
|
void register_spicy_module_begin(const std::string& id, const std::string& description);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a Spicy protocol analyzer with its EVT meta information with the
|
* Registers a Spicy protocol analyzer with its EVT meta information with the
|
||||||
* plugin's runtime.
|
* plugin's runtime.
|
||||||
*/
|
*/
|
||||||
void register_protocol_analyzer(const std::string& name, hilti::rt::Protocol proto,
|
void register_protocol_analyzer(const std::string& id, hilti::rt::Protocol proto,
|
||||||
const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
|
const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
|
||||||
const std::string& parser_orig, const std::string& parser_resp,
|
const std::string& parser_orig, const std::string& parser_resp,
|
||||||
const std::string& replaces, const std::string& linker_scope);
|
const std::string& replaces, const std::string& linker_scope);
|
||||||
|
@ -112,7 +115,7 @@ void register_protocol_analyzer(const std::string& name, hilti::rt::Protocol pro
|
||||||
* Registers a Spicy file analyzer with its EVT meta information with the
|
* Registers a Spicy file analyzer with its EVT meta information with the
|
||||||
* plugin's runtime.
|
* plugin's runtime.
|
||||||
*/
|
*/
|
||||||
void register_file_analyzer(const std::string& name, const hilti::rt::Vector<std::string>& mime_types,
|
void register_file_analyzer(const std::string& id, const hilti::rt::Vector<std::string>& mime_types,
|
||||||
const std::string& parser, const std::string& replaces, const std::string& linker_scope);
|
const std::string& parser, const std::string& replaces, const std::string& linker_scope);
|
||||||
|
|
||||||
/** Reports a Zeek-side "weird". */
|
/** Reports a Zeek-side "weird". */
|
||||||
|
@ -122,7 +125,7 @@ void weird(const std::string& id, const std::string& addl);
|
||||||
* Registers a Spicy packet analyzer with its EVT meta information with the
|
* Registers a Spicy packet analyzer with its EVT meta information with the
|
||||||
* plugin's runtime.
|
* plugin's runtime.
|
||||||
*/
|
*/
|
||||||
void register_packet_analyzer(const std::string& name, const std::string& parser, const std::string& replaces,
|
void register_packet_analyzer(const std::string& id, const std::string& parser, const std::string& replaces,
|
||||||
const std::string& linker_scope);
|
const std::string& linker_scope);
|
||||||
|
|
||||||
/** Registers a Spicy-generated type to make it available inside Zeek. */
|
/** Registers a Spicy-generated type to make it available inside Zeek. */
|
||||||
|
@ -991,4 +994,328 @@ inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
return target->AsEnumType()->GetEnumVal(bt);
|
return target->AsEnumType()->GetEnumVal(bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Zeek value associated with a global Zeek-side ID. Throws if the
|
||||||
|
* ID does not exist.
|
||||||
|
*/
|
||||||
|
inline ValPtr get_value(const std::string& name) {
|
||||||
|
if ( auto id = zeek::detail::global_scope()->Find(name) )
|
||||||
|
return id->GetVal();
|
||||||
|
else
|
||||||
|
throw InvalidValue(util::fmt("no such Zeek variable: '%s'", name.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
/** Helper to raise a ``TypeMismatch`` exception. */
|
||||||
|
inline auto type_mismatch(const ValPtr& v, const char* expected) {
|
||||||
|
throw TypeMismatch(util::fmt("type mismatch in Zeek value: expected %s, but got %s", expected,
|
||||||
|
::zeek::type_name(v->GetType()->Tag())));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to check the type of Zeek value against an expected type tag, raising
|
||||||
|
* a ``TypeMismatch`` exception on mismatch.
|
||||||
|
*/
|
||||||
|
inline auto check_type(const ValPtr& v, ::zeek::TypeTag type_tag, const char* expected) {
|
||||||
|
if ( v->GetType()->Tag() != type_tag )
|
||||||
|
type_mismatch(v, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/** Type for a Zeek record value. */
|
||||||
|
using ValRecordPtr = ::zeek::IntrusivePtr<::zeek::RecordVal>;
|
||||||
|
|
||||||
|
/** Type for a Zeek set value. */
|
||||||
|
using ValSetPtr = ::zeek::IntrusivePtr<::zeek::TableVal>;
|
||||||
|
|
||||||
|
/** Type for a Zeek table value. */
|
||||||
|
using ValTablePtr = ::zeek::IntrusivePtr<::zeek::TableVal>;
|
||||||
|
|
||||||
|
/** Type for a Zeek vector value. */
|
||||||
|
using ValVectorPtr = ::zeek::IntrusivePtr<::zeek::VectorVal>;
|
||||||
|
|
||||||
|
/** Converts a Zeek `addr` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Address as_address(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_ADDR, "address");
|
||||||
|
return ::hilti::rt::Address(v->AsAddr());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `bool` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Bool as_bool(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_BOOL, "bool");
|
||||||
|
return ::hilti::rt::Bool(v->AsBool());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `count` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline hilti::rt::integer::safe<uint64_t> as_count(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_COUNT, "count");
|
||||||
|
return v->AsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `double` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline double as_double(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_DOUBLE, "double");
|
||||||
|
return v->AsDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Zeek `enum` value to a string containing the (unscoped) label
|
||||||
|
* name. Throws on error.
|
||||||
|
*/
|
||||||
|
inline std::string as_enum(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_ENUM, "enum");
|
||||||
|
// Zeek returns the name as "<module>::<enum>", we just want the enum name.
|
||||||
|
return hilti::rt::rsplit1(v->GetType()->AsEnumType()->Lookup(v->AsEnum()), "::").second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `int` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline hilti::rt::integer::safe<int64_t> as_int(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_INT, "int");
|
||||||
|
return v->AsInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `interval` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Interval as_interval(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_INTERVAL, "interval");
|
||||||
|
return ::hilti::rt::Interval(v->AsInterval(), hilti::rt::Interval::SecondTag{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `port` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Port as_port(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_PORT, "port");
|
||||||
|
auto p = v->AsPortVal();
|
||||||
|
// Wrap port number into safe integer to catch any overflows (Zeek returns
|
||||||
|
// an uint32, while HILTI wants an uint16).
|
||||||
|
return ::hilti::rt::Port(hilti::rt::integer::safe<uint16_t>(p->Port()), p->PortType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `record` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ValRecordPtr as_record(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_RECORD, "record");
|
||||||
|
return ::zeek::cast_intrusive<::zeek::RecordVal>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `set` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ValSetPtr as_set(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_TABLE, "set");
|
||||||
|
|
||||||
|
if ( ! v->AsTableVal()->GetType()->IsSet() )
|
||||||
|
detail::type_mismatch(v, "set");
|
||||||
|
|
||||||
|
return ::zeek::cast_intrusive<::zeek::TableVal>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `string` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline hilti::rt::Bytes as_string(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_STRING, "string");
|
||||||
|
auto str = v->AsString();
|
||||||
|
return hilti::rt::Bytes(reinterpret_cast<const char*>(str->Bytes()), str->Len());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `subnet` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Network as_subnet(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_SUBNET, "subnet");
|
||||||
|
auto subnet = v->AsSubNet();
|
||||||
|
return ::hilti::rt::Network(subnet.Prefix(), subnet.Length());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `table` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ValTablePtr as_table(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_TABLE, "table");
|
||||||
|
|
||||||
|
if ( v->AsTableVal()->GetType()->IsSet() )
|
||||||
|
detail::type_mismatch(v, "table");
|
||||||
|
|
||||||
|
return ::zeek::cast_intrusive<::zeek::TableVal>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `time` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ::hilti::rt::Time as_time(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_TIME, "time");
|
||||||
|
return ::hilti::rt::Time(v->AsTime(), hilti::rt::Time::SecondTag{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts a Zeek `vector` value to its Spicy equivalent. Throws on error. */
|
||||||
|
inline ValVectorPtr as_vector(const ValPtr& v) {
|
||||||
|
detail::check_type(v, TYPE_VECTOR, "vector");
|
||||||
|
return ::zeek::cast_intrusive<::zeek::VectorVal>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `addr`. Throws on error. */
|
||||||
|
inline hilti::rt::Address get_address(const std::string& name) { return as_address(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `bool`. Throws on error. */
|
||||||
|
inline hilti::rt::Bool get_bool(const std::string& name) { return as_bool(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `count`. Throws on error. */
|
||||||
|
inline hilti::rt::integer::safe<uint64_t> get_count(const std::string& name) { return as_count(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `double`. Throws on error. */
|
||||||
|
inline double get_double(const std::string& name) { return as_double(get_value(name)); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a global Zeek variable of assumed type `enum` as a string
|
||||||
|
* containing the (unscoped) label name. Throws on error.
|
||||||
|
*/
|
||||||
|
inline std::string get_enum(const std::string& name) { return as_enum(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `int`. Throws on error. */
|
||||||
|
inline hilti::rt::integer::safe<int64_t> get_int(const std::string& name) { return as_int(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `interval`. Throws on error. */
|
||||||
|
inline hilti::rt::Interval get_interval(const std::string& name) { return as_interval(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `port`. Throws on error. */
|
||||||
|
inline hilti::rt::Port get_port(const std::string& name) { return as_port(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `record`. Throws on error. */
|
||||||
|
inline ValRecordPtr get_record(const std::string& name) { return as_record(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `set`. Throws on error. */
|
||||||
|
inline ValSetPtr get_set(const std::string& name) { return as_set(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `string`. Throws on error. */
|
||||||
|
inline hilti::rt::Bytes get_string(const std::string& name) { return as_string(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `subnet`. Throws on error. */
|
||||||
|
inline hilti::rt::Network get_subnet(const std::string& name) { return as_subnet(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `table`. Throws on error. */
|
||||||
|
inline ValTablePtr get_table(const std::string& name) { return as_table(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `time`. Throws on error. */
|
||||||
|
inline hilti::rt::Time get_time(const std::string& name) { return as_time(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves a global Zeek variable of assumed type `vector`. Throws on error. */
|
||||||
|
inline ValVectorPtr get_vector(const std::string& name) { return as_vector(get_value(name)); }
|
||||||
|
|
||||||
|
/** Retrieves the value of Zeek record field. Throws on error. */
|
||||||
|
inline ::zeek::ValPtr record_field(const zeek::spicy::rt::ValRecordPtr& v, const std::string& field) {
|
||||||
|
auto index = v->GetType()->AsRecordType()->FieldOffset(field.c_str());
|
||||||
|
if ( index < 0 )
|
||||||
|
throw InvalidValue(util::fmt("no such record field: %s", field.c_str()));
|
||||||
|
|
||||||
|
if ( auto x = v->GetFieldOrDefault(index) )
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
throw InvalidValue(util::fmt("record field is not set: %s", field.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieves the value of Zeek record field. Throws on error. */
|
||||||
|
inline ::zeek::ValPtr record_field(const std::string& name, const std::string& index) {
|
||||||
|
return record_field(get_record(name), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if a Zeek record has a field's value set. Throws on errors. */
|
||||||
|
inline hilti::rt::Bool record_has_value(const zeek::spicy::rt::ValRecordPtr& v, const std::string& field) {
|
||||||
|
auto index = v->GetType()->AsRecordType()->FieldOffset(field.c_str());
|
||||||
|
if ( index < 0 )
|
||||||
|
throw InvalidValue(util::fmt("no such field in record type: %s", field.c_str()));
|
||||||
|
|
||||||
|
return v->HasField(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a Zeek record has a field's value set. Throws on errors. */
|
||||||
|
inline hilti::rt::Bool record_has_value(const std::string& name, const std::string& index) {
|
||||||
|
return record_has_value(get_record(name), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if a Zeek record type has a field of a give name. Throws on errors. */
|
||||||
|
inline hilti::rt::Bool record_has_field(const zeek::spicy::rt::ValRecordPtr& v, const std::string& field) {
|
||||||
|
return v->GetType()->AsRecordType()->FieldOffset(field.c_str()) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if a Zeek record type has a field of a give name. Throws on errors. */
|
||||||
|
inline hilti::rt::Bool record_has_field(const std::string& name, const std::string& index) {
|
||||||
|
return record_has_value(get_record(name), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a Zeek set contains a given element. Throws on errors. */
|
||||||
|
template<typename T>
|
||||||
|
::hilti::rt::Bool set_contains(const ValSetPtr& v, const T& key) {
|
||||||
|
auto index = v->GetType()->AsTableType()->GetIndexTypes()[0];
|
||||||
|
return (v->Find(to_val(key, index)) != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a Zeek set contains a given element. Throws on errors. */
|
||||||
|
template<typename T>
|
||||||
|
::hilti::rt::Bool set_contains(const std::string& name, const T& key) {
|
||||||
|
return set_contains(get_set(name), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a Zeek table contains a given element. Throws on errors. */
|
||||||
|
template<typename T>
|
||||||
|
::hilti::rt::Bool table_contains(const ValTablePtr& v, const T& key) {
|
||||||
|
auto index = v->GetType()->AsTableType()->GetIndexTypes()[0];
|
||||||
|
return (v->Find(to_val(key, index)) != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if a Zeek table contains a given element. Throws on errors. */
|
||||||
|
template<typename T>
|
||||||
|
::hilti::rt::Bool table_contains(const std::string& name, const T& key) {
|
||||||
|
return table_contains(get_table(name), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a value from a Zeek table. Returns an error value if the key does
|
||||||
|
* not exist. Throws on other errors.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
std::optional<::zeek::ValPtr> table_lookup(const zeek::spicy::rt::ValTablePtr& v, const T& key) {
|
||||||
|
auto index = v->GetType()->AsTableType()->GetIndexTypes()[0];
|
||||||
|
if ( auto x = v->FindOrDefault(to_val(key, index)) )
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a value from a Zeek table. Returns an error value if the key does
|
||||||
|
* not exist. Throws on other errors.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
std::optional<::zeek::ValPtr> table_lookup(const std::string& name, const T& key) {
|
||||||
|
return table_lookup(get_table(name), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a Zeek vector element. Throws on errors. */
|
||||||
|
inline ::zeek::ValPtr vector_index(const zeek::spicy::rt::ValVectorPtr& v,
|
||||||
|
const hilti::rt::integer::safe<uint64_t>& index) {
|
||||||
|
if ( index >= v->Size() )
|
||||||
|
throw InvalidValue(util::fmt("vector index out of bounds: %" PRIu64, index.Ref()));
|
||||||
|
|
||||||
|
return v->ValAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a Zeek vector element. Throws on errors. */
|
||||||
|
inline ::zeek::ValPtr vector_index(const std::string& name, const hilti::rt::integer::safe<uint64_t>& index) {
|
||||||
|
return vector_index(get_vector(name), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the size of a Zeek vector. Throws on errors. */
|
||||||
|
inline hilti::rt::integer::safe<uint64_t> vector_size(const zeek::spicy::rt::ValVectorPtr& v) { return v->Size(); }
|
||||||
|
|
||||||
|
/** Returns the size of a Zeek vector. Throws on errors. */
|
||||||
|
inline hilti::rt::integer::safe<uint64_t> vector_size(const std::string& name) { return vector_size(get_vector(name)); }
|
||||||
|
|
||||||
} // namespace zeek::spicy::rt
|
} // namespace zeek::spicy::rt
|
||||||
|
|
||||||
|
namespace hilti::rt::detail::adl {
|
||||||
|
// Stringification for opaque type handles.
|
||||||
|
inline std::string to_string(const zeek::ValPtr& v, detail::adl::tag /* unused */) { return "<Zeek value>"; }
|
||||||
|
|
||||||
|
inline std::string to_string(const zeek::spicy::rt::ValRecordPtr& v, detail::adl::tag /* unused */) {
|
||||||
|
return "<Zeek record>";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string to_string(const zeek::spicy::rt::ValTablePtr& v, detail::adl::tag /* unused */) {
|
||||||
|
return "<Zeek set/table>";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string to_string(const zeek::spicy::rt::ValVectorPtr& v, detail::adl::tag /* unused */) {
|
||||||
|
return "<Zeek vector>";
|
||||||
|
}
|
||||||
|
} // namespace hilti::rt::detail::adl
|
||||||
|
|
6
testing/btest/Baseline/spicy.get-values/output
Normal file
6
testing/btest/Baseline/spicy.get-values/output
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
<Zeek value>
|
||||||
|
<Zeek record>
|
||||||
|
<Zeek set/table>
|
||||||
|
<Zeek set/table>
|
||||||
|
<Zeek vector>
|
99
testing/btest/spicy/get-values.spicy
Normal file
99
testing/btest/spicy/get-values.spicy
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
# @TEST-REQUIRES: have-spicy
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: spicyz -d -o test.hlto %INPUT
|
||||||
|
# @TEST-EXEC: zeek globals.zeek test.hlto Spicy::enable_print=T >output
|
||||||
|
# @TEST-EXEC: btest-diff output
|
||||||
|
#
|
||||||
|
# @TEST-DOC: Test access to Zeek-side globals.
|
||||||
|
|
||||||
|
module Foo;
|
||||||
|
|
||||||
|
import zeek;
|
||||||
|
|
||||||
|
assert zeek::get_address("Bar::address_") == 1.2.3.4;
|
||||||
|
assert zeek::get_bool("Bar::bool_") == True;
|
||||||
|
assert zeek::get_count("Bar::count_") == 42;
|
||||||
|
assert zeek::get_double("Bar::double_") == 42.0;
|
||||||
|
assert zeek::get_enum("Bar::enum_") == "Foo";
|
||||||
|
assert zeek::get_int("Bar::int_") == 42;
|
||||||
|
assert zeek::get_interval("Bar::interval_") == interval(42);
|
||||||
|
assert zeek::get_port("Bar::port_") == 42/tcp;
|
||||||
|
assert zeek::get_string("Bar::string_") == b"xxx";
|
||||||
|
assert zeek::get_subnet("Bar::subnet_") == 1.2.3.4/16;
|
||||||
|
assert zeek::get_time("Bar::time_") == time(42.0);
|
||||||
|
|
||||||
|
assert zeek::as_address(zeek::get_value("Bar::address_")) == 1.2.3.4;
|
||||||
|
assert zeek::as_bool(zeek::get_value("Bar::bool_")) == True;
|
||||||
|
assert zeek::as_count(zeek::get_value("Bar::count_")) == 42;
|
||||||
|
assert zeek::as_double(zeek::get_value("Bar::double_")) == 42.0;
|
||||||
|
assert zeek::as_enum(zeek::get_value("Bar::enum_")) == "Foo";
|
||||||
|
assert zeek::as_int(zeek::get_value("Bar::int_")) == 42;
|
||||||
|
assert zeek::as_interval(zeek::get_value("Bar::interval_")) == interval(42);
|
||||||
|
assert zeek::as_port(zeek::get_value("Bar::port_")) == 42/tcp;
|
||||||
|
assert zeek::as_string(zeek::get_value("Bar::string_")) == b"xxx";
|
||||||
|
assert zeek::as_subnet(zeek::get_value("Bar::subnet_")) == 1.2.3.4/16;
|
||||||
|
assert zeek::as_time(zeek::get_value("Bar::time_")) == time(42.0);
|
||||||
|
|
||||||
|
assert zeek::as_string(zeek::record_field("Bar::record_", "x")) == b"foo";
|
||||||
|
assert zeek::as_int(zeek::record_field("Bar::record_", "y")) == 42;
|
||||||
|
assert zeek::as_int(zeek::record_field(zeek::get_record("Bar::record_"), "y")) == 42;
|
||||||
|
assert zeek::record_has_value("Bar::record_", "x");
|
||||||
|
assert zeek::record_has_value(zeek::get_record("Bar::record_"), "y");
|
||||||
|
assert zeek::record_has_value("Bar::record_", "y");
|
||||||
|
assert ! zeek::record_has_value("Bar::record_", "z");
|
||||||
|
assert zeek::record_has_field("Bar::record_", "x");
|
||||||
|
assert ! zeek::record_has_field("Bar::record_", "z");
|
||||||
|
assert-exception zeek::record_field("Bar::record_", "z"); # not set
|
||||||
|
|
||||||
|
assert zeek::set_contains("Bar::set_", "foo");
|
||||||
|
assert ! zeek::set_contains("Bar::set_", "xxx");
|
||||||
|
assert zeek::set_contains(zeek::get_set("Bar::set_"), "foo");
|
||||||
|
|
||||||
|
assert zeek::table_contains("Bar::table_", "foo");
|
||||||
|
assert ! zeek::table_contains("Bar::table_", "xxx");
|
||||||
|
assert zeek::table_contains(zeek::get_table("Bar::table_"), "foo");
|
||||||
|
assert zeek::as_string(*zeek::table_lookup("Bar::table_", "foo")) == b"bar";
|
||||||
|
assert zeek::as_string(*zeek::table_lookup(zeek::get_table("Bar::table_"), "foo")) == b"bar";
|
||||||
|
assert ! zeek::table_lookup("Bar::table_", "does-not-exist");
|
||||||
|
|
||||||
|
assert zeek::as_count(zeek::vector_index("Bar::vector_", 2)) == 2;
|
||||||
|
assert zeek::as_count(zeek::vector_index(zeek::get_vector("Bar::vector_"), 2)) == 2;
|
||||||
|
|
||||||
|
assert-exception zeek::get_bool("Bar::does_not_exist");
|
||||||
|
assert-exception zeek::get_bool("Bar::string_");
|
||||||
|
|
||||||
|
# Test stringifcation.
|
||||||
|
print zeek::get_value("Bar::bool_");
|
||||||
|
print zeek::get_record("Bar::record_");
|
||||||
|
print zeek::get_set("Bar::set_");
|
||||||
|
print zeek::get_table("Bar::table_");
|
||||||
|
print zeek::get_vector("Bar::vector_");
|
||||||
|
|
||||||
|
# @TEST-START-FILE globals.zeek
|
||||||
|
module Bar;
|
||||||
|
|
||||||
|
type Record: record {
|
||||||
|
x: string;
|
||||||
|
y: int &default=42;
|
||||||
|
z: bool &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Enum: enum { Foo, Bar };
|
||||||
|
|
||||||
|
const address_: addr = 1.2.3.4;
|
||||||
|
const bool_: bool = T;
|
||||||
|
const count_: count = 42;
|
||||||
|
const double_: double = 42.0;
|
||||||
|
const enum_: Enum = Foo;
|
||||||
|
const int_: int = 42;
|
||||||
|
const interval_: interval = 42sec;
|
||||||
|
const port_: port = 42/tcp;
|
||||||
|
const record_: Record = [$x="foo"];
|
||||||
|
const set_: set[string] = set("foo", "bar");
|
||||||
|
const string_: string = "xxx";
|
||||||
|
const subnet_: subnet = 1.2.3.4/16;
|
||||||
|
const table_: table[string] of string = table(["foo"] = "bar");
|
||||||
|
const time_: time = double_to_time(42.0);
|
||||||
|
const vector_: vector of count = vector(0, 1, 2);
|
||||||
|
|
||||||
|
# @TEST-END-FILE
|
Loading…
Add table
Add a link
Reference in a new issue