mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Spicy: Prepare for supporting forwarding to protocols other than TCP.
So far the Spicy runtime supported forwarding data into other analyzers only for TCP analyzers. This puts branching logic in place that let the relevant runtime functions dispatch differently based on the target transport-layer protocol. We don't implement anything else than TCP yet; that will come next. Along with the internal changes, this also updates the user-visible runtime function to pass protocol information in. For now, this likewise remains limited to TCP. The function signatures are chosen so that they stay backwards-compatible to previous Spicy version. In particular, they default to TCP where not otherwise specified.
This commit is contained in:
parent
9c1ecd205c
commit
8dd3debeae
3 changed files with 286 additions and 129 deletions
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
module zeek;
|
module zeek;
|
||||||
|
|
||||||
|
import spicy;
|
||||||
|
|
||||||
# Note: Retain the formatting here, doc/scripts/autogen-spicy-lib is picking up on that.
|
# Note: Retain the formatting here, doc/scripts/autogen-spicy-lib is picking up on that.
|
||||||
|
|
||||||
%cxx-include = "zeek/spicy/runtime-support.h";
|
%cxx-include = "zeek/spicy/runtime-support.h";
|
||||||
|
@ -48,46 +50,82 @@ public type ProtocolHandle = __library_type("zeek::spicy::rt::ProtocolHandle");
|
||||||
|
|
||||||
## 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
|
||||||
## protocol_begin with same argument, and not closed with protocol_handle_close
|
## `protocol_begin` with same argument, and not closed with `protocol_handle_close`
|
||||||
## or protocol_end, no new analyzer will be added.
|
## or `protocol_end`, no new analyzer will be added.
|
||||||
##
|
##
|
||||||
## See `protocol_handle_get_or_create` for the error semantics of this function.
|
## See `protocol_handle_get_or_create` for the error semantics of this function.
|
||||||
##
|
##
|
||||||
## analyzer: type of analyzer to instantiate, specified through its Zeek-side
|
## analyzer: type of analyzer to instantiate, specified through its Zeek-side
|
||||||
## name (similar to what Zeek's signature action `enable` takes); if not
|
## name (similar to what Zeek's signature action `enable` takes)
|
||||||
## specified, Zeek will perform its usual dynamic protocol detection to figure
|
##
|
||||||
## out how to parse the data (the latter will work only for TCP protocols, though.)
|
## protocol: the transport-layer protocol that the analyzer uses; only TCP is
|
||||||
public function protocol_begin(analyzer: optional<string> = Null) : void &cxxname="zeek::spicy::rt::protocol_begin";
|
## currently supported here
|
||||||
|
##
|
||||||
|
## Note: For backwards compatibility, the analyzer argument can be left unset to add
|
||||||
|
## a DPD analyzer. This use is deprecated, though; use the single-argument version of
|
||||||
|
## `protocol_begin` for that instead.
|
||||||
|
public function protocol_begin(analyzer: optional<string>, protocol: spicy::Protocol = spicy::Protocol::TCP) : void &cxxname="zeek::spicy::rt::protocol_begin";
|
||||||
|
|
||||||
|
## Adds a Zeek-side DPD child protocol analyzer performing dynamic protocol detection
|
||||||
|
## on subsequently provided data.
|
||||||
|
##
|
||||||
|
## If the same DPD analyzer was added previously with `protocol_handle_get_or_create` or
|
||||||
|
## `protocol_begin` with same argument, and not closed with `protocol_handle_close`
|
||||||
|
## or `protocol_end`, no new analyzer will be added.
|
||||||
|
##
|
||||||
|
## See `protocol_handle_get_or_create` for the error semantics of this function.
|
||||||
|
##
|
||||||
|
## protocol: the transport-layer protocol on which to perform protocol detection;
|
||||||
|
## only TCP is currently supported here
|
||||||
|
public function protocol_begin(protocol: spicy::Protocol = spicy::Protocol::TCP) : void &cxxname="zeek::spicy::rt::protocol_begin";
|
||||||
|
|
||||||
## Gets a handle to a Zeek-side child protocol analyzer for the current connection.
|
## Gets a handle to a Zeek-side child protocol analyzer for the current connection.
|
||||||
##
|
##
|
||||||
## If no such child exists it will be added; otherwise a handle to the
|
## If no such child exists yet it will be added; otherwise a handle to the
|
||||||
## existing child protocol analyzer will be returned.
|
## existing child protocol analyzer will be returned.
|
||||||
##
|
##
|
||||||
## This function will return an error
|
## This function will return an error if:
|
||||||
##
|
##
|
||||||
## - if not called from a protocol analyzer, or
|
## - not called from a protocol analyzer, or
|
||||||
## - the requested child protocol analyzer is unknown, or
|
## - the requested child protocol analyzer is of unknown type or not support by the requested transport protocol, or
|
||||||
## - creation of a child analyzer of the requested type was prevented by a
|
## - creation of a child analyzer of the requested type was prevented by a
|
||||||
## previous call of `disable_analyzer` with `prevent=T`
|
## previous call of `disable_analyzer` with `prevent=T`
|
||||||
##
|
##
|
||||||
## analyzer: type of analyzer to instantiate, specified through its Zeek-side
|
## analyzer: type of analyzer to get or instantiate, specified through its Zeek-side
|
||||||
## name (similar to what Zeek's signature action `enable` takes).
|
## name (similar to what Zeek's signature action `enable` takes).
|
||||||
public function protocol_handle_get_or_create(analyzer: string) : ProtocolHandle &cxxname="zeek::spicy::rt::protocol_handle_get_or_create";
|
##
|
||||||
|
## protocol: the transport-layer protocol that the analyser uses; only TCP is
|
||||||
|
## currently supported here
|
||||||
|
##
|
||||||
|
public function protocol_handle_get_or_create(analyzer: string, protocol: spicy::Protocol = spicy::Protocol::TCP) : ProtocolHandle &cxxname="zeek::spicy::rt::protocol_handle_get_or_create";
|
||||||
|
|
||||||
## Forwards protocol data to all previously instantiated Zeek-side child protocol analyzers.
|
## Forwards protocol data to all previously instantiated Zeek-side child protocol analyzers of a given transport-layer.
|
||||||
##
|
##
|
||||||
## is_orig: true to feed the data to the child's originator side, false for the responder
|
## is_orig: true to feed the data to the child's originator side, false for the responder
|
||||||
|
##
|
||||||
## data: chunk of data to forward to child analyzer
|
## data: chunk of data to forward to child analyzer
|
||||||
## h: optional handle to the child analyzer to forward data into, else forward to all child analyzers
|
##
|
||||||
public function protocol_data_in(is_orig: bool, data: bytes, h: optional<ProtocolHandle> = Null) : void &cxxname="zeek::spicy::rt::protocol_data_in";
|
## protocol: the transport-layer protocol of the children to forward to; only TCP is currently supported here
|
||||||
|
public function protocol_data_in(is_orig: bool, data: bytes, protocol: spicy::Protocol = spicy::Protocol::TCP) : void &cxxname="zeek::spicy::rt::protocol_data_in";
|
||||||
|
|
||||||
|
## Forwards protocol data to a specific previously instantiated Zeek-side child analyzer.
|
||||||
|
##
|
||||||
|
## is_orig: true to feed the data to the child's originator side, false for the responder
|
||||||
|
##
|
||||||
|
## data: chunk of data to forward to child analyzer
|
||||||
|
##
|
||||||
|
## h: handle to the child analyzer to forward data into
|
||||||
|
public function protocol_data_in(is_orig: bool, data: bytes, h: ProtocolHandle) : void &cxxname="zeek::spicy::rt::protocol_data_in";
|
||||||
|
|
||||||
## Signals a gap in input data to all previously instantiated Zeek-side child protocol analyzers.
|
## Signals a gap in input data to all previously instantiated Zeek-side child protocol analyzers.
|
||||||
##
|
##
|
||||||
## is_orig: true to signal gap to the child's originator side, false for the responder
|
## is_orig: true to signal gap to the child's originator side, false for the responder
|
||||||
|
##
|
||||||
## offset: start offset of gap in input stream
|
## offset: start offset of gap in input stream
|
||||||
|
##
|
||||||
## len: size of gap
|
## len: size of gap
|
||||||
|
##
|
||||||
## h: optional handle to the child analyzer signal a gap to, else signal to all child analyzers
|
## h: optional handle to the child analyzer signal a gap to, else signal to all child analyzers
|
||||||
public function protocol_gap(is_orig: bool, offset: uint64, len: uint64, h: optional<ProtocolHandle> = Null) : void &cxxname="zeek::spicy::rt::protocol_gap";
|
public function protocol_gap(is_orig: bool, offset: uint64, len: uint64, h: optional<ProtocolHandle> = Null) : void &cxxname="zeek::spicy::rt::protocol_gap";
|
||||||
|
|
||||||
|
|
|
@ -485,15 +485,16 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
void rt::protocol_begin(const std::optional<std::string>& analyzer) {
|
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");
|
||||||
|
|
||||||
if ( analyzer ) {
|
if ( analyzer ) {
|
||||||
protocol_handle_get_or_create(*analyzer);
|
protocol_handle_get_or_create(*analyzer, proto);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate a DPD analyzer.
|
// Instantiate a DPD analyzer.
|
||||||
|
|
||||||
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
assert(cookie);
|
assert(cookie);
|
||||||
|
|
||||||
|
@ -501,43 +502,11 @@ void rt::protocol_begin(const std::optional<std::string>& analyzer) {
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
throw ValueUnavailable("no current connection available");
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
// Use a Zeek PIA stream analyzer performing DPD.
|
switch ( proto.value() ) {
|
||||||
|
case ::hilti::rt::Protocol::TCP: {
|
||||||
auto pia_tcp = std::make_unique<analyzer::pia::PIA_TCP>(c->analyzer->Conn());
|
auto pia_tcp = std::make_unique<analyzer::pia::PIA_TCP>(c->analyzer->Conn());
|
||||||
|
pia_tcp->FirstPacket(true, nullptr);
|
||||||
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
pia_tcp->FirstPacket(false, nullptr);
|
||||||
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
|
||||||
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), false);
|
|
||||||
|
|
||||||
// Direct child of this type already exists. We ignore this silently
|
|
||||||
// because that makes usage nicer if either side of the connection
|
|
||||||
// might end up creating the analyzer; this way the user doesn't
|
|
||||||
// need to track what the other side already did.
|
|
||||||
//
|
|
||||||
// We inspect the children directly to work around zeek/zeek#2899.
|
|
||||||
const auto& children = c->analyzer->GetChildren();
|
|
||||||
if ( auto it = std::find_if(children.begin(), children.end(),
|
|
||||||
[&](const auto& it) {
|
|
||||||
return ! it->Removing() && ! it->IsFinished() &&
|
|
||||||
it->GetAnalyzerTag() == pia_tcp->GetAnalyzerTag();
|
|
||||||
});
|
|
||||||
it != children.end() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto child = pia_tcp.release();
|
|
||||||
c->analyzer->AddChildAnalyzer(child);
|
|
||||||
|
|
||||||
child->FirstPacket(true, nullptr);
|
|
||||||
child->FirstPacket(false, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
rt::ProtocolHandle rt::protocol_handle_get_or_create(const std::string& analyzer) {
|
|
||||||
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_handle_get_or_create");
|
|
||||||
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
|
||||||
assert(cookie);
|
|
||||||
|
|
||||||
auto c = cookie->protocol;
|
|
||||||
if ( ! c )
|
|
||||||
throw ValueUnavailable("no current connection available");
|
|
||||||
|
|
||||||
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
||||||
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
||||||
|
@ -549,10 +518,55 @@ rt::ProtocolHandle rt::protocol_handle_get_or_create(const std::string& analyzer
|
||||||
const auto& children = c->analyzer->GetChildren();
|
const auto& children = c->analyzer->GetChildren();
|
||||||
if ( auto it = std::find_if(children.begin(), children.end(),
|
if ( auto it = std::find_if(children.begin(), children.end(),
|
||||||
[&](const auto& it) {
|
[&](const auto& it) {
|
||||||
return ! it->Removing() && ! it->IsFinished() && it->GetAnalyzerName() == analyzer;
|
return ! it->Removing() && ! it->IsFinished() &&
|
||||||
|
it->GetAnalyzerName() == pia_tcp->GetAnalyzerTag();
|
||||||
});
|
});
|
||||||
it != children.end() )
|
it != children.end() )
|
||||||
return rt::ProtocolHandle((*it)->GetID());
|
return;
|
||||||
|
|
||||||
|
auto child = pia_tcp.release();
|
||||||
|
c->analyzer->AddChildAnalyzer(child);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::UDP: throw Unsupported("protocol_begin: UDPnot supported for DPD");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::ICMP: throw Unsupported("protocol_begin: ICMP not supported for DPD");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::Undef: throw InvalidValue("protocol_begin: no protocol specified for DPD");
|
||||||
|
|
||||||
|
default: throw InvalidValue("protocol_begin: unknown protocol for DPD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_begin(const ::hilti::rt::Protocol& proto) { return protocol_begin(std::nullopt, proto); }
|
||||||
|
|
||||||
|
rt::ProtocolHandle rt::protocol_handle_get_or_create(const std::string& analyzer, const ::hilti::rt::Protocol& proto) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_handle_get_or_create");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
switch ( proto.value() ) {
|
||||||
|
case ::hilti::rt::Protocol::TCP: {
|
||||||
|
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), false);
|
||||||
|
|
||||||
|
// If the child already exists, do not add it again so this function is idempotent.
|
||||||
|
//
|
||||||
|
// We inspect the children directly to work around zeek/zeek#2899.
|
||||||
|
const auto& children = c->analyzer->GetChildren();
|
||||||
|
if ( auto it = std::find_if(children.begin(), children.end(),
|
||||||
|
[&](const auto& it) {
|
||||||
|
return ! it->Removing() && ! it->IsFinished() &&
|
||||||
|
it->GetAnalyzerName() == analyzer;
|
||||||
|
});
|
||||||
|
it != children.end() )
|
||||||
|
return rt::ProtocolHandle((*it)->GetID(), proto);
|
||||||
|
|
||||||
auto child = analyzer_mgr->InstantiateAnalyzer(analyzer.c_str(), c->analyzer->Conn());
|
auto child = analyzer_mgr->InstantiateAnalyzer(analyzer.c_str(), c->analyzer->Conn());
|
||||||
if ( ! child )
|
if ( ! child )
|
||||||
|
@ -584,10 +598,24 @@ rt::ProtocolHandle rt::protocol_handle_get_or_create(const std::string& analyzer
|
||||||
if ( c->fake_tcp )
|
if ( c->fake_tcp )
|
||||||
child_as_tcp->SetTCP(c->fake_tcp.get());
|
child_as_tcp->SetTCP(c->fake_tcp.get());
|
||||||
|
|
||||||
return rt::ProtocolHandle(child->GetID());
|
return rt::ProtocolHandle(child->GetID(), proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
case ::hilti::rt::Protocol::UDP: {
|
||||||
|
throw Unsupported("protocol_handle_get_or_create: UDP not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::ICMP: throw Unsupported("protocol_handle_get_or_create: ICMP not supported");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::Undef: throw InvalidValue("protocol_handle_get_or_create: no protocol specified");
|
||||||
|
|
||||||
|
default: throw InvalidValue("protocol_handle_get_or_create: unknown protocol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
static void protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
||||||
|
const std::optional<::hilti::rt::Protocol>& proto,
|
||||||
const std::optional<rt::ProtocolHandle>& h) {
|
const std::optional<rt::ProtocolHandle>& h) {
|
||||||
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_data_in");
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_data_in");
|
||||||
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
@ -597,6 +625,22 @@ void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
throw ValueUnavailable("no current connection available");
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
::hilti::rt::Protocol protocol_to_use = ::hilti::rt::Protocol::Undef;
|
||||||
|
|
||||||
|
if ( proto ) {
|
||||||
|
if ( h && h->protocol() != *proto )
|
||||||
|
throw InvalidValue("protocol_data_in: protocol mismatches with analyzer handle");
|
||||||
|
|
||||||
|
protocol_to_use = *proto;
|
||||||
|
}
|
||||||
|
else if ( h )
|
||||||
|
protocol_to_use = h->protocol();
|
||||||
|
|
||||||
|
if ( protocol_to_use == ::hilti::rt::Protocol::Undef )
|
||||||
|
throw InvalidValue("protocol_data_in: cannot determine protocol to use");
|
||||||
|
|
||||||
|
switch ( protocol_to_use.value() ) {
|
||||||
|
case ::hilti::rt::Protocol::TCP: {
|
||||||
auto len = data.size();
|
auto len = data.size();
|
||||||
auto* data_ = reinterpret_cast<const u_char*>(data.data());
|
auto* data_ = reinterpret_cast<const u_char*>(data.data());
|
||||||
|
|
||||||
|
@ -616,6 +660,30 @@ void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes
|
||||||
|
|
||||||
else
|
else
|
||||||
c->analyzer->ForwardStream(len, data_, is_orig);
|
c->analyzer->ForwardStream(len, data_, is_orig);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::UDP: {
|
||||||
|
throw Unsupported("protocol_data_in: UDP not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::ICMP: throw Unsupported("protocol_data_in: ICMP not supported");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::Undef: hilti::rt::cannot_be_reached();
|
||||||
|
|
||||||
|
default: throw InvalidValue("protocol_data_in: unknown protocol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace zeek::spicy::rt
|
||||||
|
|
||||||
|
void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
||||||
|
const ::hilti::rt::Protocol& proto) {
|
||||||
|
protocol_data_in(is_orig, data, proto, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data, const rt::ProtocolHandle& h) {
|
||||||
|
protocol_data_in(is_orig, data, {}, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rt::protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::safe<uint64_t>& offset,
|
void rt::protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::safe<uint64_t>& offset,
|
||||||
|
@ -628,6 +696,8 @@ void rt::protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
throw ValueUnavailable("no current connection available");
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
switch ( h->protocol().value() ) {
|
||||||
|
case ::hilti::rt::Protocol::TCP: {
|
||||||
if ( h ) {
|
if ( h ) {
|
||||||
if ( auto* output_handler = c->analyzer->GetOutputHandler() )
|
if ( auto* output_handler = c->analyzer->GetOutputHandler() )
|
||||||
output_handler->Undelivered(offset, len, is_orig);
|
output_handler->Undelivered(offset, len, is_orig);
|
||||||
|
@ -644,6 +714,20 @@ void rt::protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::
|
||||||
|
|
||||||
else
|
else
|
||||||
c->analyzer->ForwardUndelivered(offset, len, is_orig);
|
c->analyzer->ForwardUndelivered(offset, len, is_orig);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::UDP: {
|
||||||
|
throw Unsupported("protocol_gap: UDP not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::ICMP: throw Unsupported("protocol_gap: ICMP not supported");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::Undef: throw InvalidValue("protocol_gap: no protocol specified");
|
||||||
|
|
||||||
|
default: throw InvalidValue("protocol_gap: unknown protocol");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rt::protocol_end() {
|
void rt::protocol_end() {
|
||||||
|
@ -668,6 +752,8 @@ void rt::protocol_handle_close(const ProtocolHandle& handle) {
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
throw ValueUnavailable("no current connection available");
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
switch ( handle.protocol().value() ) {
|
||||||
|
case ::hilti::rt::Protocol::TCP: {
|
||||||
auto child = c->analyzer->FindChild(handle.id());
|
auto child = c->analyzer->FindChild(handle.id());
|
||||||
if ( ! child )
|
if ( ! child )
|
||||||
throw ValueUnavailable(hilti::rt::fmt("unknown child analyzer %s", handle));
|
throw ValueUnavailable(hilti::rt::fmt("unknown child analyzer %s", handle));
|
||||||
|
@ -679,6 +765,19 @@ void rt::protocol_handle_close(const ProtocolHandle& handle) {
|
||||||
child->NextEndOfData(false);
|
child->NextEndOfData(false);
|
||||||
|
|
||||||
c->analyzer->RemoveChildAnalyzer(handle.id());
|
c->analyzer->RemoveChildAnalyzer(handle.id());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::UDP: {
|
||||||
|
throw Unsupported("protocol_handle_close: UDP not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::ICMP: throw Unsupported("protocol_handle_close: ICMP not supported");
|
||||||
|
|
||||||
|
case ::hilti::rt::Protocol::Undef: throw InvalidValue("protocol_handle_close: no protocol specified");
|
||||||
|
|
||||||
|
default: throw InvalidValue("protocol_handle_close: unknown protocol");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rt::cookie::FileState* rt::cookie::FileStateStack::push(std::optional<std::string> fid_provided) {
|
rt::cookie::FileState* rt::cookie::FileStateStack::push(std::optional<std::string> fid_provided) {
|
||||||
|
|
|
@ -294,7 +294,7 @@ void reject_protocol(const std::string& reason = "protocol rejected");
|
||||||
class ProtocolHandle {
|
class ProtocolHandle {
|
||||||
public:
|
public:
|
||||||
ProtocolHandle() {}
|
ProtocolHandle() {}
|
||||||
explicit ProtocolHandle(uint64_t id) : _id(id) {}
|
explicit ProtocolHandle(uint64_t id, ::hilti::rt::Protocol proto) : _id(id), _proto(proto) {}
|
||||||
|
|
||||||
uint64_t id() const {
|
uint64_t id() const {
|
||||||
if ( ! _id )
|
if ( ! _id )
|
||||||
|
@ -303,6 +303,8 @@ public:
|
||||||
return *_id;
|
return *_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& protocol() const { return _proto; }
|
||||||
|
|
||||||
friend std::string to_string(const ProtocolHandle& h, ::hilti::rt::detail::adl::tag) {
|
friend std::string to_string(const ProtocolHandle& h, ::hilti::rt::detail::adl::tag) {
|
||||||
if ( ! h._id )
|
if ( ! h._id )
|
||||||
return "(uninitialized protocol handle)";
|
return "(uninitialized protocol handle)";
|
||||||
|
@ -316,38 +318,56 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<uint64_t> _id;
|
std::optional<uint64_t> _id;
|
||||||
|
::hilti::rt::Protocol _proto = ::hilti::rt::Protocol::Undef;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Zeek-side child protocol analyzer to the current connection.
|
* Adds a Zeek-side child protocol analyzer to the current connection.
|
||||||
*
|
*
|
||||||
* @param analyzer if given, the Zeek-side name of the analyzer to instantiate;
|
* @param analyzer the Zeek-side name of the analyzer to instantiate; can be left unset to add a DPD analyzer
|
||||||
* if not given, DPD will be used
|
|
||||||
*/
|
*/
|
||||||
void protocol_begin(const std::optional<std::string>& analyzer);
|
void protocol_begin(const std::optional<std::string>& analyzer, const ::hilti::rt::Protocol& proto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a Zeek-side DPD child analyzer to the current connection.
|
||||||
|
*
|
||||||
|
* @param proto the transport-layer protocol of the desired DPD analyzer; must be TCP or UDP
|
||||||
|
*/
|
||||||
|
void protocol_begin(const ::hilti::rt::Protocol& proto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a handle to a child analyzer of a given type. If a child of that type
|
* Gets a handle to a child analyzer of a given type. If a child of that type
|
||||||
* does not yet exist it will be created.
|
* does not yet exist it will be created.
|
||||||
*
|
*
|
||||||
* @param analyzer the Zeek-side name of the analyzer to get (e.g., `HTTP`)
|
* @param analyzer the Zeek-side name of the analyzer to get (e.g., `HTTP`)
|
||||||
|
* @param proto the transport-layer protocol of the analyzer, which must match
|
||||||
|
* the type of the child analyzer that *analyzer* refers to
|
||||||
*
|
*
|
||||||
* @return a handle to the child analyzer. When done, the handle should be
|
* @return a handle to the child analyzer. When done, the handle should be
|
||||||
* closed, either explicitly with protocol_handle_close or implicitly with
|
* closed, either explicitly with protocol_handle_close or implicitly with
|
||||||
* protocol_end.
|
* protocol_end.
|
||||||
*/
|
*/
|
||||||
ProtocolHandle protocol_handle_get_or_create(const std::string& analyzer);
|
rt::ProtocolHandle protocol_handle_get_or_create(const std::string& analyzer, const ::hilti::rt::Protocol& proto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forwards data to all previously instantiated Zeek-side child protocol
|
* Forwards data to all previously instantiated Zeek-side child protocol
|
||||||
* analyzers.
|
* analyzers of a given transport-layer protocol.
|
||||||
*
|
*
|
||||||
* @param is_orig true to feed data to originator side, false for responder
|
* @param is_orig true to feed data to originator side, false for responder
|
||||||
* @param data next chunk of stream data for child analyzer to process
|
* @param data next chunk of stream data for child analyzer to process
|
||||||
* @param h optional handle to the child analyzer to stream data into
|
* @param h optional handle to pass data to a specific child analyzer only
|
||||||
*/
|
*/
|
||||||
void protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
void protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data, const ::hilti::rt::Protocol& proto);
|
||||||
const std::optional<ProtocolHandle>& h = {});
|
|
||||||
|
/**
|
||||||
|
* Forwards data to a specific previously instantiated Zeek-side child protocol
|
||||||
|
* analyzer.
|
||||||
|
*
|
||||||
|
* @param is_orig true to feed data to originator side, false for responder
|
||||||
|
* @param data next chunk of stream data for child analyzer to process
|
||||||
|
* @param h handle identifying the specific child analyzer only
|
||||||
|
*/
|
||||||
|
void protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data, const ProtocolHandle& h);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals a gap in input data to all previously instantiated Zeek-side child
|
* Signals a gap in input data to all previously instantiated Zeek-side child
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue