Merge remote-tracking branch 'origin/topic/bbannier/issue-3094'

* origin/topic/bbannier/issue-3094:
  Simplify code generated for Spicy analyzer port ranges.
This commit is contained in:
Tim Wojtulewicz 2023-05-31 09:50:46 +02:00
commit 1cfe0e3ee7
8 changed files with 85 additions and 37 deletions

View file

@ -8,12 +8,15 @@ import hilti;
public type Val = __library_type("::zeek::ValPtr"); public type Val = __library_type("::zeek::ValPtr");
public type BroType = __library_type("::zeek::TypePtr"); public type BroType = __library_type("::zeek::TypePtr");
public type EventHandlerPtr = __library_type("::zeek::EventHandlerPtr"); public type EventHandlerPtr = __library_type("::zeek::EventHandlerPtr");
public type PortRange = __library_type("::zeek::spicy::rt::PortRange");
declare public PortRange make_port_range(port begin_, port end_) &cxxname="zeek::spicy::rt::make_port_range" &have_prototype;
type ZeekTypeTag = enum { type ZeekTypeTag = enum {
Addr, Any, Bool, Count, Double, Enum, Error, File, Func, Int, Interval, List, Opaque, Pattern, Port, Record, String, Subnet, Table, Time, Type, Vector, Void Addr, Any, Bool, Count, Double, Enum, Error, File, Func, Int, Interval, List, Opaque, Pattern, Port, Record, String, Subnet, Table, Time, Type, Vector, Void
} &cxxname="::zeek::spicy::rt::ZeekTypeTag"; } &cxxname="::zeek::spicy::rt::ZeekTypeTag";
declare public void register_protocol_analyzer(string name, hilti::Protocol protocol, vector<port> ports, string parser_orig, string parser_resp, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_protocol_analyzer" &have_prototype; declare public void register_protocol_analyzer(string name, hilti::Protocol protocol, vector<PortRange> ports, string parser_orig, string parser_resp, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_protocol_analyzer" &have_prototype;
declare public void register_file_analyzer(string name, vector<string> mime_types, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_file_analyzer" &have_prototype; declare public void register_file_analyzer(string name, vector<string> mime_types, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_file_analyzer" &have_prototype;
declare public void register_packet_analyzer(string name, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_packet_analyzer" &have_prototype; declare public void register_packet_analyzer(string name, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_packet_analyzer" &have_prototype;
declare public void register_type(string ns, string id, BroType t) &cxxname="zeek::spicy::rt::register_type" &have_prototype; declare public void register_type(string ns, string id, BroType t) &cxxname="zeek::spicy::rt::register_type" &have_prototype;

View file

@ -6,6 +6,7 @@
#include <glob.h> #include <glob.h>
#include <exception> #include <exception>
#include <limits>
#include <utility> #include <utility>
#include <hilti/rt/configuration.h> #include <hilti/rt/configuration.h>
@ -47,9 +48,9 @@ static std::pair<std::string, std::string> parseID(const std::string& s) {
Manager::~Manager() {} Manager::~Manager() {}
void Manager::registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto, void Manager::registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto,
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig, const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
const std::string& parser_resp, const std::string& replaces, const std::string& parser_orig, const std::string& parser_resp,
const std::string& linker_scope) { const std::string& replaces, const std::string& linker_scope) {
SPICY_DEBUG(hilti::rt::fmt("Have Spicy protocol analyzer %s", name)); SPICY_DEBUG(hilti::rt::fmt("Have Spicy protocol analyzer %s", name));
ProtocolAnalyzerInfo info; ProtocolAnalyzerInfo info;
@ -683,9 +684,19 @@ void Manager::InitPostScript() {
if ( ! tag ) if ( ! tag )
reporter->InternalError("cannot get analyzer tag for '%s'", p.name_analyzer.c_str()); reporter->InternalError("cannot get analyzer tag for '%s'", p.name_analyzer.c_str());
for ( auto port : p.ports ) { for ( const auto& ports : p.ports ) {
SPICY_DEBUG(hilti::rt::fmt(" Scheduling analyzer for port %s", port)); const auto proto = ports.begin.protocol();
analyzer_mgr->RegisterAnalyzerForPort(tag, transport_protocol(port), port.port());
// Port ranges are closed intervals.
for ( auto port = ports.begin.port(); port <= ports.end.port(); ++port ) {
const auto port_ = hilti::rt::Port(port, proto);
SPICY_DEBUG(hilti::rt::fmt(" Scheduling analyzer for port %s", port_));
analyzer_mgr->RegisterAnalyzerForPort(tag, transport_protocol(port_), port);
// Explicitly prevent overflow.
if ( port == std::numeric_limits<decltype(port)>::max() )
break;
}
} }
if ( p.parser_resp ) { if ( p.parser_resp ) {

View file

@ -17,6 +17,7 @@
#include "zeek/Tag.h" #include "zeek/Tag.h"
#include "zeek/plugin/Component.h" #include "zeek/plugin/Component.h"
#include "zeek/plugin/Plugin.h" #include "zeek/plugin/Plugin.h"
#include "zeek/spicy/port-range.h"
#include "zeek/spicy/spicyz/config.h" // include for Spicy version #include "zeek/spicy/spicyz/config.h" // include for Spicy version
// Macro helper to report Spicy debug messages. This forwards to // Macro helper to report Spicy debug messages. This forwards to
@ -81,9 +82,9 @@ public:
* registration * registration
*/ */
void registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto, void registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto,
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig, const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
const std::string& parser_resp, const std::string& replaces, const std::string& parser_orig, const std::string& parser_resp,
const std::string& linker_scope); const std::string& replaces, const std::string& linker_scope);
/** /**
* Runtime method to register a file analyzer with its Zeek-side * Runtime method to register a file analyzer with its Zeek-side
@ -325,7 +326,7 @@ private:
std::string name_parser_resp; std::string name_parser_resp;
std::string name_replaces; std::string name_replaces;
hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef; hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef;
hilti::rt::Vector<hilti::rt::Port> ports; hilti::rt::Vector<::zeek::spicy::rt::PortRange> ports;
std::string linker_scope; std::string linker_scope;
// Computed and available once the analyzer has been registered. // Computed and available once the analyzer has been registered.

32
src/spicy/port-range.h Normal file
View file

@ -0,0 +1,32 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <cassert>
#include <tuple>
#include <hilti/rt/types/port.h>
namespace zeek::spicy::rt {
/** A closed ranged of ports. */
struct PortRange {
PortRange() = default;
PortRange(hilti::rt::Port begin_, hilti::rt::Port end_) : begin(begin_), end(end_) {
assert(begin.port() <= end.port());
assert(begin.protocol() == end.protocol());
}
hilti::rt::Port begin; /**< first port in the range */
hilti::rt::Port end; /**< last port in the range */
};
inline bool operator==(const PortRange& a, const PortRange& b) {
return std::tie(a.begin, a.end) == std::tie(b.begin, b.end);
}
inline bool operator!=(const PortRange& a, const PortRange& b) { return ! (a == b); }
inline PortRange make_port_range(hilti::rt::Port begin, hilti::rt::Port end) { return PortRange(begin, end); }
} // namespace zeek::spicy::rt

View file

@ -21,9 +21,9 @@ using namespace zeek;
using namespace zeek::spicy; using namespace zeek::spicy;
void rt::register_protocol_analyzer(const std::string& name, hilti::rt::Protocol proto, void rt::register_protocol_analyzer(const std::string& name, hilti::rt::Protocol proto,
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig, const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
const std::string& parser_resp, const std::string& replaces, const std::string& parser_orig, const std::string& parser_resp,
const std::string& linker_scope) { const std::string& replaces, const std::string& linker_scope) {
auto _ = hilti::rt::profiler::start("zeek/rt/register_protocol_analyzer"); auto _ = hilti::rt::profiler::start("zeek/rt/register_protocol_analyzer");
spicy_mgr->registerProtocolAnalyzer(name, proto, ports, parser_orig, parser_resp, replaces, linker_scope); spicy_mgr->registerProtocolAnalyzer(name, proto, ports, parser_orig, parser_resp, replaces, linker_scope);
} }

View file

@ -23,6 +23,7 @@
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/spicy/cookie.h" #include "zeek/spicy/cookie.h"
#include "zeek/spicy/manager.h" #include "zeek/spicy/manager.h"
#include "zeek/spicy/port-range.h"
namespace zeek::spicy::rt { namespace zeek::spicy::rt {
@ -93,9 +94,9 @@ public:
* 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& name, hilti::rt::Protocol proto,
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig, const hilti::rt::Vector<::zeek::spicy::rt::PortRange>& ports,
const std::string& parser_resp, const std::string& replaces, const std::string& parser_orig, const std::string& parser_resp,
const std::string& linker_scope); const std::string& replaces, const std::string& linker_scope);
/** /**
* Registers a Spicy file analyzer with its EVT meta information with the * Registers a Spicy file analyzer with its EVT meta information with the

View file

@ -16,6 +16,7 @@
#include <spicy/global.h> #include <spicy/global.h>
#include "config.h" #include "config.h"
#include "zeek/spicy/port-range.h"
using namespace zeek::spicy; using namespace zeek::spicy;
@ -279,7 +280,7 @@ static hilti::rt::Port extract_port(const std::string& chunk, size_t* i) {
return {static_cast<uint16_t>(port), proto}; return {static_cast<uint16_t>(port), proto};
} }
static std::vector<hilti::rt::Port> extract_ports(const std::string& chunk, size_t* i) { static ::zeek::spicy::rt::PortRange extract_port_range(const std::string& chunk, size_t* i) {
auto start = extract_port(chunk, i); auto start = extract_port(chunk, i);
auto end = std::optional<hilti::rt::Port>(); auto end = std::optional<hilti::rt::Port>();
@ -296,16 +297,11 @@ static std::vector<hilti::rt::Port> extract_ports(const std::string& chunk, size
throw ParseError("start of port range cannot be after its end"); throw ParseError("start of port range cannot be after its end");
} }
std::vector<hilti::rt::Port> result; if ( ! end )
// EVT port ranges are a closed interval, but rt are half-closed.
end = hilti::rt::Port(start.port() + 1, start.protocol());
// Port ranges are a closed interval. return {start, *end};
for ( auto port = start.port(); ! end || port <= end->port(); ++port ) {
result.emplace_back(port, start.protocol());
if ( ! end )
break;
}
return result;
} }
void GlueCompiler::Init(Driver* driver, int zeek_version) { void GlueCompiler::Init(Driver* driver, int zeek_version) {
@ -609,8 +605,7 @@ glue::ProtocolAnalyzer GlueCompiler::parseProtocolAnalyzer(const std::string& ch
eat_token(chunk, &i, "{"); eat_token(chunk, &i, "{");
while ( true ) { while ( true ) {
auto ports = extract_ports(chunk, &i); a.ports.push_back(extract_port_range(chunk, &i));
a.ports.insert(a.ports.end(), ports.begin(), ports.end());
if ( looking_at(chunk, i, "}") ) { if ( looking_at(chunk, i, "}") ) {
eat_token(chunk, &i, "}"); eat_token(chunk, &i, "}");
@ -623,8 +618,7 @@ glue::ProtocolAnalyzer GlueCompiler::parseProtocolAnalyzer(const std::string& ch
else if ( looking_at(chunk, i, "port") ) { else if ( looking_at(chunk, i, "port") ) {
eat_token(chunk, &i, "port"); eat_token(chunk, &i, "port");
auto ports = extract_ports(chunk, &i); a.ports.push_back(extract_port_range(chunk, &i));
a.ports.insert(a.ports.end(), ports.begin(), ports.end());
} }
else if ( looking_at(chunk, i, "replaces") ) { else if ( looking_at(chunk, i, "replaces") ) {
@ -855,11 +849,16 @@ bool GlueCompiler::compile() {
default: hilti::logger().internalError("unexpected protocol"); default: hilti::logger().internalError("unexpected protocol");
} }
preinit_body.addCall("zeek_rt::register_protocol_analyzer", preinit_body.addCall(
{builder::string(a.name), builder::id(protocol), "zeek_rt::register_protocol_analyzer",
builder::vector(hilti::util::transform(a.ports, [](auto p) { return builder::port(p); })), {builder::string(a.name), builder::id(protocol),
builder::string(a.unit_name_orig), builder::string(a.unit_name_resp), builder::vector(hilti::util::transform(
builder::string(a.replaces), _linker_scope()}); a.ports,
[](const auto& p) {
return builder::call("zeek_rt::make_port_range", {builder::port(p.begin), builder::port(p.end)});
})),
builder::string(a.unit_name_orig), builder::string(a.unit_name_resp), builder::string(a.replaces),
_linker_scope()});
} }
for ( auto& a : _file_analyzers ) { for ( auto& a : _file_analyzers ) {

View file

@ -27,6 +27,7 @@
#include <spicy/ast/types/unit.h> #include <spicy/ast/types/unit.h>
#include "driver.h" #include "driver.h"
#include "zeek/spicy/port-range.h"
namespace spicy::rt { namespace spicy::rt {
struct Parser; struct Parser;
@ -42,7 +43,7 @@ struct ProtocolAnalyzer {
hilti::Location location; /**< Location where the analyzer was defined. */ hilti::Location location; /**< Location where the analyzer was defined. */
hilti::ID name; /**< Name of the analyzer. */ hilti::ID name; /**< Name of the analyzer. */
hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef; /**< The transport layer the analyzer uses. */ hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef; /**< The transport layer the analyzer uses. */
std::vector<hilti::rt::Port> ports; /**< The ports associated with the analyzer. */ std::vector<::zeek::spicy::rt::PortRange> ports; /**< The ports associated with the analyzer. */
hilti::ID unit_name_orig; /**< The fully-qualified name of the unit type to parse the originator hilti::ID unit_name_orig; /**< The fully-qualified name of the unit type to parse the originator
side. */ side. */
hilti::ID unit_name_resp; /**< The fully-qualified name of the unit type to parse the originator hilti::ID unit_name_resp; /**< The fully-qualified name of the unit type to parse the originator