zeek/src/script_opt/ZAM/Support.cc

250 lines
7.4 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
// Low-level support utilities/globals for ZAM compilation.
#include "zeek/script_opt/ZAM/Support.h"
#include "zeek/Desc.h"
#include "zeek/Reporter.h"
#include "zeek/ScriptValidation.h"
#include "zeek/ZeekString.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/conn-size/ConnSize.h"
#include "zeek/broker/Manager.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/file_analysis/file_analysis.bif.h"
#include "zeek/logging/Manager.h"
#include "zeek/packet_analysis/Manager.h"
#include "zeek/script_opt/ProfileFunc.h"
#include "zeek/session/Manager.h"
namespace zeek::detail {
namespace ZAM {
std::string curr_func;
std::shared_ptr<ZAMLocInfo> curr_loc;
TypePtr log_ID_enum_type;
TypePtr any_base_type = base_type(TYPE_ANY);
bool log_mgr_write(zeek::EnumVal* v, zeek::RecordVal* r) { return zeek::log_mgr->Write(v, r); }
size_t broker_mgr_flush_log_buffers() { return zeek::broker_mgr->FlushLogBuffers(); }
zeek::Connection* session_mgr_find_connection(zeek::Val* cid) { return zeek::session_mgr->FindConnection(cid); }
zeek::StringVal* analyzer_name(zeek::EnumVal* val) {
plugin::Component* component = zeek::analyzer_mgr->Lookup(val, false);
if ( ! component )
component = zeek::packet_mgr->Lookup(val, false);
if ( ! component )
component = zeek::file_mgr->Lookup(val, false);
if ( component )
return new StringVal(component->CanonicalName());
return new StringVal("<error>");
}
zeek::plugin::Component* analyzer_mgr_lookup(zeek::EnumVal* v) { return zeek::analyzer_mgr->Lookup(v); }
zeek_uint_t conn_size_get_bytes_threshold(Val* cid, bool is_orig) {
if ( auto* a = analyzer::conn_size::GetConnsizeAnalyzer(cid) )
return static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->GetByteAndPacketThreshold(true, is_orig);
return 0;
}
bool conn_size_set_bytes_threshold(zeek_uint_t threshold, Val* cid, bool is_orig) {
if ( auto* a = analyzer::conn_size::GetConnsizeAnalyzer(cid) ) {
static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->SetByteAndPacketThreshold(threshold, true, is_orig);
return true;
}
return false;
}
// File analysis wrappers
void file_mgr_set_handle(StringVal* h) { zeek::file_mgr->SetHandle(h->ToStdString()); }
bool file_mgr_add_analyzer(StringVal* file_id, EnumVal* tag, RecordVal* args) {
const auto& tag_ = zeek::file_mgr->GetComponentTag(tag);
if ( ! tag_ )
return false;
using zeek::BifType::Record::Files::AnalyzerArgs;
auto rv = args->CoerceTo(AnalyzerArgs);
return zeek::file_mgr->AddAnalyzer(file_id->CheckString(), tag_, std::move(rv));
}
bool file_mgr_remove_analyzer(StringVal* file_id, EnumVal* tag, RecordVal* args) {
const auto& tag_ = zeek::file_mgr->GetComponentTag(tag);
if ( ! tag_ )
return false;
using zeek::BifType::Record::Files::AnalyzerArgs;
auto rv = args->CoerceTo(AnalyzerArgs);
return zeek::file_mgr->RemoveAnalyzer(file_id->CheckString(), tag_, std::move(rv));
}
bool file_mgr_analyzer_enabled(zeek::EnumVal* v) {
auto c = zeek::file_mgr->Lookup(v->AsEnumVal());
return c && c->Enabled();
}
zeek::StringVal* file_mgr_analyzer_name(EnumVal* v) {
// to be placed into a ZVal
return file_mgr->GetComponentNameVal({NewRef{}, v}).release();
}
bool file_mgr_enable_reassembly(StringVal* file_id) {
std::string fid = file_id->CheckString();
return zeek::file_mgr->EnableReassembly(fid);
}
bool file_mgr_disable_reassembly(StringVal* file_id) {
std::string fid = file_id->CheckString();
return zeek::file_mgr->DisableReassembly(fid);
}
bool file_mgr_set_reassembly_buffer(StringVal* file_id, uint64_t max) {
std::string fid = file_id->CheckString();
return zeek::file_mgr->SetReassemblyBuffer(fid, max);
}
} // namespace ZAM
bool ZAM_error = false;
bool is_ZAM_compilable(const ProfileFunc* pf, const char** reason) {
auto func = pf->ProfiledFunc(); // can be nil for lambdas
if ( func ) {
auto& scope_id = pf->ProfiledScope()->GetID();
if ( scope_id && scope_id->GetAttr(ATTR_NO_ZAM_OPT) ) {
if ( reason )
*reason = "&no_ZAM_opt attribute";
return false;
}
}
if ( has_AST_node_unknown_to_script_opt(pf, true) ) {
if ( reason )
*reason = "unknown AST node type";
return false;
}
auto b = pf->ProfiledBody();
auto is_hook = pf->ProfiledFunc()->Flavor() == FUNC_FLAVOR_HOOK;
if ( b && ! script_is_valid(b, is_hook) ) {
if ( reason )
*reason = "invalid script body";
return false;
}
return true;
}
bool IsAny(const Type* t) { return t->Tag() == TYPE_ANY; }
bool CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, const std::shared_ptr<ZAMLocInfo>& loc) {
if ( IsAny(expected_type) )
return true;
if ( ! same_type(any_type, expected_type, false, false) ) {
auto at = any_type->Tag();
auto et = expected_type->Tag();
if ( at == TYPE_RECORD && et == TYPE_RECORD ) {
auto at_r = any_type->AsRecordType();
auto et_r = expected_type->AsRecordType();
if ( record_promotion_compatible(et_r, at_r) )
return true;
}
char buf[8192];
snprintf(buf, sizeof buf, "run-time type clash (%s/%s)", type_name(at), type_name(et));
reporter->RuntimeError(loc->Loc(), "%s", buf);
return false;
}
return true;
}
StringVal* ZAM_to_lower(const StringVal* sv) {
auto bs = sv->AsString();
const u_char* s = bs->Bytes();
int n = bs->Len();
u_char* lower_s = new u_char[n + 1];
u_char* ls = lower_s;
for ( int i = 0; i < n; ++i ) {
if ( isascii(s[i]) && isupper(s[i]) )
*ls++ = tolower(s[i]);
else
*ls++ = s[i];
}
*ls++ = '\0';
return new StringVal(new String(true, lower_s, n));
}
StringVal* ZAM_sub_bytes(const StringVal* s, zeek_uint_t start, zeek_int_t n) {
if ( start > 0 )
--start; // make it 0-based
auto ss = s->AsString()->GetSubstring(start, n);
return new StringVal(ss ? ss : new String(""));
}
StringValPtr ZAM_val_cat(const ValPtr& v) {
// Quite similar to cat(), but for only one value.
zeek::ODesc d;
d.SetStyle(RAW_STYLE);
v->Describe(&d);
String* s = new String(true, d.TakeBytes(), d.Size());
s->SetUseFreeToDelete(true);
return make_intrusive<StringVal>(s);
}
void ZAM_run_time_error(const char* msg) {
fprintf(stderr, "%s\n", msg);
ZAM_error = true;
}
void ZAM_run_time_error(std::shared_ptr<ZAMLocInfo> loc, const char* msg) {
if ( loc )
reporter->RuntimeError(loc->Loc(), "%s", msg);
else
fprintf(stderr, "<no location in optimized code>: %s\n", msg);
ZAM_error = true;
}
void ZAM_run_time_error(const char* msg, const Obj* o) {
fprintf(stderr, "%s: %s\n", msg, obj_desc(o).c_str());
ZAM_error = true;
}
void ZAM_run_time_error(std::shared_ptr<ZAMLocInfo> loc, const char* msg, const Obj* o) {
if ( loc )
reporter->RuntimeError(loc->Loc(), "%s (%s)", msg, obj_desc(o).c_str());
else
ZAM_run_time_error(msg, o);
ZAM_error = true;
}
void ZAM_run_time_warning(std::shared_ptr<ZAMLocInfo> loc, const char* msg) {
ODesc d;
loc->Loc()->Describe(&d);
reporter->Warning("%s: %s", d.Description(), msg);
}
} // namespace zeek::detail