Spicy: Add functions to check if Zeek provides an analyzer of a given name.

```
## Checks if there is a Zeek analyzer of a given name.
##
## analyzer: the Zeek-side name of the analyzer to check for
## if_enabled: if true, only checks for analyzers that are enabled
##
## Returns the type of the analyzer if it exists, or ``Undef`` if it does not.
public function has_analyzer(analyzer: string, if_enabled: bool = True): bool &cxxname="zeek::spicy::rt::has_analyzer";

## Differentiates between the types of analyzers Zeek provides.
public type AnalyzerType = enum { Protocol, File, Packet, };

## Returns the type of a Zeek analyzer of a given name.
##
## analyzer: the Zeek-side name of the analyzer to check
## if_enabled: if true, only checks for analyzers that are enabled
##
## Returns the type of the analyzer if it exists, or ``Undef`` if it does not.
public function analyzer_type(analyzer: string, if_enabled: bool = True): AnalyzerType &cxxname="zeek::spicy::rt::analyzer_type";

```

Closes #4481.
This commit is contained in:
Robin Sommer 2025-06-30 13:46:51 +02:00
parent e0e62e28f6
commit 7dc5a70dc8
No known key found for this signature in database
GPG key ID: D8187293B3FFE5D0
5 changed files with 111 additions and 2 deletions

2
doc

@ -1 +1 @@
Subproject commit 1e3a30367cc36b2779be71db7076c61362e78547 Subproject commit 48f12d4f31b0d2fde43dbf64bf1235d326444d6d

View file

@ -48,6 +48,29 @@ public function number_packets(): uint64 &cxxname="zeek::spicy::rt::number_packe
## Opaque handle to a protocol analyzer. ## Opaque handle to a protocol analyzer.
public type ProtocolHandle = __library_type("zeek::spicy::rt::ProtocolHandle"); public type ProtocolHandle = __library_type("zeek::spicy::rt::ProtocolHandle");
## Differentiates between the types of analyzers Zeek provides.
public type AnalyzerType = enum {
File,
Packet,
Protocol,
}&cxxname = "zeek::spicy::rt::AnalyzerType";
## Checks if there is a Zeek analyzer of a given name.
##
## analyzer: the Zeek-side name of the analyzer to check for
## if_enabled: if true, only checks for analyzers that are enabled
##
## Returns the type of the analyzer if it exists, or ``Undef`` if it does not.
public function has_analyzer(analyzer: string, if_enabled: bool = True): bool &cxxname="zeek::spicy::rt::has_analyzer";
## Returns the type of a Zeek analyzer of a given name.
##
## analyzer: the Zeek-side name of the analyzer to check
## if_enabled: if true, only checks for analyzers that are enabled
##
## Returns the type of the analyzer if it exists, or ``Undef`` if it does not.
public function analyzer_type(analyzer: string, if_enabled: bool = True): AnalyzerType &cxxname="zeek::spicy::rt::analyzer_type";
## Adds a Zeek-side child protocol analyzer to the current connection. ## Adds a Zeek-side child protocol analyzer to the current connection.
## ##
## If the same analyzer was added previously with `protocol_handle_get_or_create` or ## If the same analyzer was added previously with `protocol_handle_get_or_create` or

View file

@ -10,12 +10,13 @@
#include <hilti/rt/types/port.h> #include <hilti/rt/types/port.h>
#include <hilti/rt/util.h> #include <hilti/rt/util.h>
#include "net_util.h"
#include "zeek/Event.h" #include "zeek/Event.h"
#include "zeek/analyzer/Manager.h" #include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h" #include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/file_analysis/File.h" #include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Manager.h" #include "zeek/file_analysis/Manager.h"
#include "zeek/net_util.h"
#include "zeek/packet_analysis/Manager.h"
#include "zeek/spicy/manager.h" #include "zeek/spicy/manager.h"
using namespace zeek; using namespace zeek;
@ -108,6 +109,17 @@ std::string hilti::rt::detail::adl::to_string(const zeek::spicy::rt::ZeekTypeTag
return type_name(zeekTypeForTag(v)); return type_name(zeekTypeForTag(v));
} }
std::string hilti::rt::detail::adl::to_string(const zeek::spicy::rt::AnalyzerType& v, detail::adl::tag /* unused */) {
switch ( v.value() ) {
case zeek::spicy::rt::AnalyzerType::File: return "AnalyzerType::File";
case zeek::spicy::rt::AnalyzerType::Packet: return "AnalyzerType::Packet";
case zeek::spicy::rt::AnalyzerType::Protocol: return "AnalyzerType::Protocol";
case zeek::spicy::rt::AnalyzerType::Undef: return "AnalyzerType::Undef";
}
hilti::rt::cannot_be_reached();
}
TypePtr rt::create_enum_type( TypePtr rt::create_enum_type(
const std::string& ns, const std::string& id, const std::string& ns, const std::string& id,
const hilti::rt::Set<std::tuple<std::optional<std::string>, std::optional<hilti::rt::integer::safe<int64_t>>>>& const hilti::rt::Set<std::tuple<std::optional<std::string>, std::optional<hilti::rt::integer::safe<int64_t>>>>&
@ -515,6 +527,25 @@ void rt::weird(const std::string& id, const std::string& addl) {
throw ValueUnavailable("none of $conn, $file, or $packet available for weird reporting"); throw ValueUnavailable("none of $conn, $file, or $packet available for weird reporting");
} }
rt::AnalyzerType rt::analyzer_type(const std::string& analyzer, const hilti::rt::Bool& if_enabled) {
if ( auto* c = file_mgr->Lookup(analyzer.c_str()) ) {
if ( (! if_enabled) || c->Enabled() )
return AnalyzerType::File;
}
if ( auto* c = packet_mgr->Lookup(analyzer.c_str()) ) {
if ( (! if_enabled) || c->Enabled() )
return AnalyzerType::Packet;
}
if ( auto* c = analyzer_mgr->Lookup(analyzer.c_str()) ) {
if ( (! if_enabled) || c->Enabled() )
return AnalyzerType::Protocol;
}
return AnalyzerType::Undef;
}
void rt::protocol_begin(const std::optional<std::string>& analyzer, const ::hilti::rt::Protocol& proto) { void rt::protocol_begin(const std::optional<std::string>& analyzer, const ::hilti::rt::Protocol& proto) {
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_begin"); auto _ = hilti::rt::profiler::start("zeek/rt/protocol_begin");

View file

@ -170,6 +170,8 @@ enum class ZeekTypeTag : uint8_t {
Void, Void,
}; };
HILTI_RT_ENUM(AnalyzerType, Undef, File, Packet, Protocol);
extern TypePtr create_base_type(ZeekTypeTag tag); extern TypePtr create_base_type(ZeekTypeTag tag);
extern TypePtr create_enum_type( extern TypePtr create_enum_type(
@ -344,6 +346,26 @@ private:
::hilti::rt::Protocol _proto = ::hilti::rt::Protocol::Undef; ::hilti::rt::Protocol _proto = ::hilti::rt::Protocol::Undef;
}; };
/**
* Returns the Zeek-side type of an analyzer of a given name.
*
* @param analyzer the Zeek-side name of the analyzer to check for
* @param if_enabled if true, only checks for analyzers that are enabled
* @return the type of the analyzer if it exists, or `AnalyzerType::Undef` if it does not.
*/
AnalyzerType analyzer_type(const std::string& analyzer, const hilti::rt::Bool& if_enabled);
/**
* Checks if there is an analyzer of a given name in Zeek.
*
* @param analyzer the Zeek-side name of the analyzer to check for
* @param if_enabled if true, only checks for analyzers that are enabled
* @return true if there is such an analyzer
*/
inline hilti::rt::Bool has_analyzer(const std::string& analyzer, const hilti::rt::Bool& if_enabled) {
return analyzer_type(analyzer, if_enabled) != AnalyzerType::Undef;
}
/** /**
* Adds a Zeek-side child protocol analyzer to the current connection. * Adds a Zeek-side child protocol analyzer to the current connection.
* *
@ -828,5 +850,6 @@ inline std::string to_string(const zeek::spicy::rt::ValVectorPtr& v, detail::adl
} }
extern std::string to_string(const zeek::spicy::rt::ZeekTypeTag& v, detail::adl::tag /* unused */); extern std::string to_string(const zeek::spicy::rt::ZeekTypeTag& v, detail::adl::tag /* unused */);
extern std::string to_string(const zeek::spicy::rt::AnalyzerType& x, adl::tag /*unused*/);
} // namespace hilti::rt::detail::adl } // namespace hilti::rt::detail::adl

View file

@ -0,0 +1,32 @@
# @TEST-REQUIRES: have-spicy
#
# @TEST-EXEC: spicyz -d -o test.hlto %INPUT disable_ssh.cc
# @TEST-EXEC: zeek test.hlto
module Test;
import zeek;
assert zeek::has_analyzer("HTTP");
assert ! zeek::has_analyzer("XXX");
assert zeek::analyzer_type("HTTP") == zeek::AnalyzerType::Protocol;
assert zeek::analyzer_type("SHA1") == zeek::AnalyzerType::File;
assert zeek::analyzer_type("VLAN") == zeek::AnalyzerType::Packet;
assert ! zeek::analyzer_type("XXX");
# Disable the SSH analyzer and check that we pay attention to its state.
public function disable_ssh() &cxxname="disable_ssh";
disable_ssh();
assert ! zeek::has_analyzer("SSH", True);
assert zeek::has_analyzer("SSH", False);
# @TEST-START-FILE disable_ssh.cc
#include "zeek/analyzer/Manager.h"
void disable_ssh() {
zeek::analyzer_mgr->Lookup("SSH")->SetEnabled(false);
}