// 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 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(""); } 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(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(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& 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(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 loc, const char* msg) { if ( loc ) reporter->RuntimeError(loc->Loc(), "%s", msg); else fprintf(stderr, ": %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 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 loc, const char* msg) { ODesc d; loc->Loc()->Describe(&d); reporter->Warning("%s: %s", d.Description(), msg); } } // namespace zeek::detail