mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
rewrite of ZAM optimization of BiFs and script functions/idioms
This commit is contained in:
parent
263093af78
commit
9cddf16800
8 changed files with 1300 additions and 409 deletions
|
@ -248,6 +248,10 @@ extern void clear_script_analysis();
|
||||||
// Called when Zeek is terminating.
|
// Called when Zeek is terminating.
|
||||||
extern void finish_script_execution();
|
extern void finish_script_execution();
|
||||||
|
|
||||||
|
// Returns true if the given call has a specialized ZAM equivalent when
|
||||||
|
// used in a conditional.
|
||||||
|
extern bool IsZAM_BuiltInCond(const CallExpr* c);
|
||||||
|
|
||||||
// Used for C++-compiled scripts to signal their presence, by setting this
|
// Used for C++-compiled scripts to signal their presence, by setting this
|
||||||
// to a non-empty value.
|
// to a non-empty value.
|
||||||
extern void (*CPP_init_hook)();
|
extern void (*CPP_init_hook)();
|
||||||
|
|
|
@ -3,196 +3,142 @@
|
||||||
// ZAM methods associated with instructions that replace calls to
|
// ZAM methods associated with instructions that replace calls to
|
||||||
// built-in functions.
|
// built-in functions.
|
||||||
|
|
||||||
|
#include "zeek/script_opt/ZAM/BuiltIn.h"
|
||||||
|
|
||||||
#include "zeek/Func.h"
|
#include "zeek/Func.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
#include "zeek/script_opt/ZAM/Compile.h"
|
#include "zeek/script_opt/ZAM/Compile.h"
|
||||||
|
|
||||||
namespace zeek::detail {
|
namespace zeek::detail {
|
||||||
|
|
||||||
bool ZAMCompiler::IsZAM_BuiltIn(const Expr* e) {
|
// Maps BiF names to their associated ZBI class.
|
||||||
// The expression e is either directly a call (in which case there's
|
std::unordered_map<std::string, const ZAMBuiltIn*> builtins;
|
||||||
// no return value), or an assignment to a call.
|
|
||||||
const CallExpr* c;
|
|
||||||
|
|
||||||
if ( e->Tag() == EXPR_CALL )
|
ZAMBuiltIn::ZAMBuiltIn(std::string name, bool _ret_val_matters) : ret_val_matters(_ret_val_matters) {
|
||||||
c = e->AsCallExpr();
|
builtins[name] = this;
|
||||||
else
|
|
||||||
c = e->GetOp2()->AsCallExpr();
|
|
||||||
|
|
||||||
auto func_expr = c->Func();
|
|
||||||
if ( func_expr->Tag() != EXPR_NAME )
|
|
||||||
// An indirect call.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto func_val = func_expr->AsNameExpr()->Id()->GetVal();
|
|
||||||
if ( ! func_val )
|
|
||||||
// A call to a function that hasn't been defined.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto func = func_val->AsFunc();
|
|
||||||
if ( func->GetKind() != BuiltinFunc::BUILTIN_FUNC )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto& args = c->Args()->Exprs();
|
|
||||||
|
|
||||||
const NameExpr* n = nullptr; // name to assign to, if any
|
|
||||||
|
|
||||||
if ( e->Tag() != EXPR_CALL )
|
|
||||||
n = e->GetOp1()->AsRefExpr()->GetOp1()->AsNameExpr();
|
|
||||||
|
|
||||||
using GenBuiltIn = bool (ZAMCompiler::*)(const NameExpr* n, const ExprPList& args);
|
|
||||||
static std::vector<std::pair<const char*, GenBuiltIn>> builtins = {
|
|
||||||
{"Analyzer::__name", &ZAMCompiler::BuiltIn_Analyzer__name},
|
|
||||||
{"Broker::__flush_logs", &ZAMCompiler::BuiltIn_Broker__flush_logs},
|
|
||||||
{"Files::__enable_reassembly", &ZAMCompiler::BuiltIn_Files__enable_reassembly},
|
|
||||||
{"Files::__set_reassembly_buffer", &ZAMCompiler::BuiltIn_Files__set_reassembly_buffer},
|
|
||||||
{"Log::__write", &ZAMCompiler::BuiltIn_Log__write},
|
|
||||||
{"cat", &ZAMCompiler::BuiltIn_cat},
|
|
||||||
{"current_time", &ZAMCompiler::BuiltIn_current_time},
|
|
||||||
{"get_port_transport_proto", &ZAMCompiler::BuiltIn_get_port_etc},
|
|
||||||
{"network_time", &ZAMCompiler::BuiltIn_network_time},
|
|
||||||
{"reading_live_traffic", &ZAMCompiler::BuiltIn_reading_live_traffic},
|
|
||||||
{"reading_traces", &ZAMCompiler::BuiltIn_reading_traces},
|
|
||||||
{"strstr", &ZAMCompiler::BuiltIn_strstr},
|
|
||||||
{"sub_bytes", &ZAMCompiler::BuiltIn_sub_bytes},
|
|
||||||
{"to_lower", &ZAMCompiler::BuiltIn_to_lower},
|
|
||||||
};
|
|
||||||
|
|
||||||
for ( auto& b : builtins )
|
|
||||||
if ( util::streq(func->Name(), b.first) )
|
|
||||||
return (this->*(b.second))(n, args);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_Analyzer__name(const NameExpr* n, const ExprPList& args) {
|
SimpleZBI::SimpleZBI(std::string name, ZOp _op, int _nargs, bool _ret_val_matters)
|
||||||
if ( ! n ) {
|
: ZAMBuiltIn(std::move(name), _ret_val_matters), op(_op), nargs(_nargs) {}
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( args[0]->Tag() == EXPR_CONST )
|
SimpleZBI::SimpleZBI(std::string name, ZOp _const_op, ZOp _op, bool _ret_val_matters)
|
||||||
// Doesn't seem worth developing a variant for this weird
|
: ZAMBuiltIn(std::move(name), _ret_val_matters), op(_op), const_op(_const_op), nargs(1) {}
|
||||||
// usage case.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
auto arg_t = args[0]->AsNameExpr();
|
|
||||||
|
|
||||||
auto z = ZInstI(OP_ANALYZER__NAME_VV, nslot, FrameSlot(arg_t));
|
|
||||||
z.SetType(args[0]->GetType());
|
|
||||||
|
|
||||||
AddInst(z);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_Broker__flush_logs(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( n )
|
|
||||||
AddInst(ZInstI(OP_BROKER_FLUSH_LOGS_V, Frame1Slot(n, OP1_WRITE)));
|
|
||||||
else
|
|
||||||
AddInst(ZInstI(OP_BROKER_FLUSH_LOGS_X));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_Files__enable_reassembly(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( n )
|
|
||||||
// While this built-in nominally returns a value, existing
|
|
||||||
// script code ignores it, so for now we don't bother
|
|
||||||
// special-casing the possibility that it doesn't.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( args[0]->Tag() == EXPR_CONST )
|
|
||||||
// Weird!
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto arg_f = args[0]->AsNameExpr();
|
|
||||||
|
|
||||||
AddInst(ZInstI(OP_FILES__ENABLE_REASSEMBLY_V, FrameSlot(arg_f)));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_Files__set_reassembly_buffer(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( n )
|
|
||||||
// See above for enable_reassembly
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( args[0]->Tag() == EXPR_CONST )
|
|
||||||
// Weird!
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto arg_f = FrameSlot(args[0]->AsNameExpr());
|
|
||||||
|
|
||||||
|
bool SimpleZBI::Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const {
|
||||||
ZInstI z;
|
ZInstI z;
|
||||||
|
if ( nargs == 0 ) {
|
||||||
if ( args[1]->Tag() == EXPR_CONST ) {
|
if ( n )
|
||||||
auto arg_cnt = args[1]->AsConstExpr()->Value()->AsCount();
|
z = ZInstI(op, zam->Frame1Slot(n, OP1_WRITE));
|
||||||
z = ZInstI(OP_FILES__SET_REASSEMBLY_BUFFER_VC, arg_f, arg_cnt);
|
|
||||||
z.op_type = OP_VV_I2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
z = ZInstI(OP_FILES__SET_REASSEMBLY_BUFFER_VV, arg_f, FrameSlot(args[1]->AsNameExpr()));
|
|
||||||
|
|
||||||
AddInst(z);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_Log__write(const NameExpr* n, const ExprPList& args) {
|
|
||||||
auto id = args[0];
|
|
||||||
auto columns = args[1];
|
|
||||||
|
|
||||||
if ( columns->Tag() != EXPR_NAME )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto columns_n = columns->AsNameExpr();
|
|
||||||
auto col_slot = FrameSlot(columns_n);
|
|
||||||
|
|
||||||
bool const_id = (id->Tag() == EXPR_CONST);
|
|
||||||
|
|
||||||
ZInstAux* aux = nullptr;
|
|
||||||
|
|
||||||
if ( const_id ) {
|
|
||||||
aux = new ZInstAux(1);
|
|
||||||
aux->Add(0, id->AsConstExpr()->ValuePtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
ZInstI z;
|
|
||||||
|
|
||||||
if ( n ) {
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
if ( const_id ) {
|
|
||||||
z = ZInstI(OP_LOG_WRITEC_VV, nslot, col_slot);
|
|
||||||
z.aux = aux;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
z = ZInstI(OP_LOG_WRITE_VVV, nslot, FrameSlot(id->AsNameExpr()), col_slot);
|
z = ZInstI(op);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( const_id ) {
|
ASSERT(nargs == 1);
|
||||||
z = ZInstI(OP_LOG_WRITEC_V, col_slot, id->AsConstExpr());
|
auto& t = args[0]->GetType();
|
||||||
z.aux = aux;
|
|
||||||
|
if ( args[0]->Tag() == EXPR_NAME ) {
|
||||||
|
auto a0 = zam->FrameSlot(args[0]->AsNameExpr());
|
||||||
|
if ( n )
|
||||||
|
z = ZInstI(op, zam->Frame1Slot(n, OP1_WRITE), a0);
|
||||||
|
else
|
||||||
|
z = ZInstI(op, a0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
z = ZInstI(OP_LOG_WRITE_VV, FrameSlot(id->AsNameExpr()), col_slot);
|
else {
|
||||||
|
if ( const_op == OP_NOP )
|
||||||
|
// This can happen for BiFs that aren't foldable, and for
|
||||||
|
// which it's implausible they'll be called with a constant
|
||||||
|
// argument.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( n )
|
||||||
|
z = ZInstI(const_op, zam->Frame1Slot(n, OP1_WRITE));
|
||||||
|
else
|
||||||
|
z = ZInstI(const_op);
|
||||||
|
|
||||||
|
z.c = ZVal(args[0]->AsConstExpr()->ValuePtr(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
z.t = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
z.SetType(columns_n->GetType());
|
if ( n )
|
||||||
|
z.is_managed = ZVal::IsManagedType(n->GetType());
|
||||||
|
|
||||||
AddInst(z);
|
zam->AddInst(z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_cat(const NameExpr* n, const ExprPList& args) {
|
CondZBI::CondZBI(std::string name, ZOp _op, ZOp _cond_op, int _nargs)
|
||||||
if ( ! n ) {
|
: SimpleZBI(std::move(name), _op, _nargs, true), cond_op(_cond_op) {}
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
|
bool CondZBI::BuildCond(ZAMCompiler* zam, const ExprPList& args, int& branch_v) const {
|
||||||
|
if ( cond_op == OP_NOP )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( nargs == 1 && args[0]->Tag() != EXPR_NAME )
|
||||||
|
// ZBI-worthy predicates called with constant arguments will generally
|
||||||
|
// have been folded. If not, for simplicity we don't support the
|
||||||
|
// flavor where they're called with a constant.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If we get here, then the ZBI is good-to-go.
|
||||||
|
|
||||||
|
if ( ! zam )
|
||||||
|
// This was just a check, not an actual build.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
ZInstI z;
|
||||||
|
|
||||||
|
if ( nargs == 0 ) {
|
||||||
|
z = ZInstI(cond_op, 0);
|
||||||
|
z.op_type = OP_V_I1;
|
||||||
|
branch_v = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
else {
|
||||||
|
ASSERT(nargs == 1);
|
||||||
|
|
||||||
|
auto a0 = args[0];
|
||||||
|
auto a0_slot = zam->FrameSlot(a0->AsNameExpr());
|
||||||
|
z = ZInstI(cond_op, a0_slot, 0);
|
||||||
|
z.op_type = OP_VV_I2;
|
||||||
|
z.t = a0->GetType();
|
||||||
|
branch_v = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
zam->AddInst(z);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OptAssignZBI::OptAssignZBI(std::string name, ZOp _op, ZOp _op2, int _nargs)
|
||||||
|
: SimpleZBI(std::move(name), _op, _nargs, false), op2(_op2) {
|
||||||
|
have_both = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OptAssignZBI::Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const {
|
||||||
|
if ( n )
|
||||||
|
return SimpleZBI::Build(zam, n, args);
|
||||||
|
|
||||||
|
ZInstI z;
|
||||||
|
if ( nargs == 0 )
|
||||||
|
z = ZInstI(op2);
|
||||||
|
else {
|
||||||
|
ASSERT(nargs == 1);
|
||||||
|
auto a0 = zam->FrameSlot(args[0]->AsNameExpr());
|
||||||
|
z = ZInstI(op2, a0);
|
||||||
|
z.t = args[0]->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
zam->AddInst(z);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CatZBI::Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const {
|
||||||
|
auto nslot = zam->Frame1Slot(n, OP1_WRITE);
|
||||||
auto& a0 = args[0];
|
auto& a0 = args[0];
|
||||||
ZInstI z;
|
ZInstI z;
|
||||||
|
|
||||||
|
@ -205,23 +151,23 @@ bool ZAMCompiler::BuiltIn_cat(const NameExpr* n, const ExprPList& args) {
|
||||||
|
|
||||||
else if ( args.size() > 1 ) {
|
else if ( args.size() > 1 ) {
|
||||||
switch ( args.size() ) {
|
switch ( args.size() ) {
|
||||||
case 2: z = GenInst(OP_CAT2_V, n); break;
|
case 2: z = zam->GenInst(OP_CAT2_V, n); break;
|
||||||
case 3: z = GenInst(OP_CAT3_V, n); break;
|
case 3: z = zam->GenInst(OP_CAT3_V, n); break;
|
||||||
case 4: z = GenInst(OP_CAT4_V, n); break;
|
case 4: z = zam->GenInst(OP_CAT4_V, n); break;
|
||||||
case 5: z = GenInst(OP_CAT5_V, n); break;
|
case 5: z = zam->GenInst(OP_CAT5_V, n); break;
|
||||||
case 6: z = GenInst(OP_CAT6_V, n); break;
|
case 6: z = zam->GenInst(OP_CAT6_V, n); break;
|
||||||
case 7: z = GenInst(OP_CAT7_V, n); break;
|
case 7: z = zam->GenInst(OP_CAT7_V, n); break;
|
||||||
case 8: z = GenInst(OP_CAT8_V, n); break;
|
case 8: z = zam->GenInst(OP_CAT8_V, n); break;
|
||||||
|
|
||||||
default: z = GenInst(OP_CATN_V, n); break;
|
default: z = zam->GenInst(OP_CATN_V, n); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
z.aux = BuildCatAux(args);
|
z.aux = BuildCatAux(zam, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( a0->GetType()->Tag() != TYPE_STRING ) {
|
else if ( a0->GetType()->Tag() != TYPE_STRING ) {
|
||||||
if ( a0->Tag() == EXPR_NAME ) {
|
if ( a0->Tag() == EXPR_NAME ) {
|
||||||
z = GenInst(OP_CAT1FULL_VV, n, a0->AsNameExpr());
|
z = zam->GenInst(OP_CAT1FULL_VV, n, a0->AsNameExpr());
|
||||||
z.t = a0->GetType();
|
z.t = a0->GetType();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -232,19 +178,19 @@ bool ZAMCompiler::BuiltIn_cat(const NameExpr* n, const ExprPList& args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( a0->Tag() == EXPR_CONST ) {
|
else if ( a0->Tag() == EXPR_CONST ) {
|
||||||
z = GenInst(OP_CAT1_VC, n, a0->AsConstExpr());
|
z = zam->GenInst(OP_CAT1_VC, n, a0->AsConstExpr());
|
||||||
z.t = n->GetType();
|
z.t = n->GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
z = GenInst(OP_CAT1_VV, n, a0->AsNameExpr());
|
z = zam->GenInst(OP_CAT1_VV, n, a0->AsNameExpr());
|
||||||
|
|
||||||
AddInst(z);
|
zam->AddInst(z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZInstAux* ZAMCompiler::BuildCatAux(const ExprPList& args) {
|
ZInstAux* CatZBI::BuildCatAux(ZAMCompiler* zam, const ExprPList& args) const {
|
||||||
auto n = args.size();
|
auto n = args.size();
|
||||||
auto aux = new ZInstAux(n);
|
auto aux = new ZInstAux(n);
|
||||||
aux->cat_args = new std::unique_ptr<CatArg>[n];
|
aux->cat_args = new std::unique_ptr<CatArg>[n];
|
||||||
|
@ -257,7 +203,9 @@ ZInstAux* ZAMCompiler::BuildCatAux(const ExprPList& args) {
|
||||||
|
|
||||||
if ( a_i->Tag() == EXPR_CONST ) {
|
if ( a_i->Tag() == EXPR_CONST ) {
|
||||||
auto c = a_i->AsConstExpr()->ValuePtr();
|
auto c = a_i->AsConstExpr()->ValuePtr();
|
||||||
aux->Add(i, c); // it will be ignored
|
aux->Add(i, c); // we add it to consume a slot, but it'll be ignored
|
||||||
|
|
||||||
|
// Convert it up front and transform into a fixed string.
|
||||||
auto sv = ZAM_val_cat(c);
|
auto sv = ZAM_val_cat(c);
|
||||||
auto s = sv->AsString();
|
auto s = sv->AsString();
|
||||||
auto b = reinterpret_cast<char*>(s->Bytes());
|
auto b = reinterpret_cast<char*>(s->Bytes());
|
||||||
|
@ -265,7 +213,7 @@ ZInstAux* ZAMCompiler::BuildCatAux(const ExprPList& args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
auto slot = FrameSlot(a_i->AsNameExpr());
|
auto slot = zam->FrameSlot(a_i->AsNameExpr());
|
||||||
aux->Add(i, slot, t);
|
aux->Add(i, slot, t);
|
||||||
|
|
||||||
switch ( t->Tag() ) {
|
switch ( t->Tag() ) {
|
||||||
|
@ -293,215 +241,395 @@ ZInstAux* ZAMCompiler::BuildCatAux(const ExprPList& args) {
|
||||||
return aux;
|
return aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_current_time(const NameExpr* n, const ExprPList& args) {
|
bool SortZBI::Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const {
|
||||||
if ( ! n ) {
|
// The checks the sort() BiF does can all be computed statically.
|
||||||
reporter->Warning("return value from built-in function ignored");
|
if ( args.size() > 2 )
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
|
|
||||||
AddInst(ZInstI(OP_CURRENT_TIME_V, nslot));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_get_port_etc(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( ! n ) {
|
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto p = args[0];
|
|
||||||
|
|
||||||
if ( p->Tag() != EXPR_NAME )
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto pn = p->AsNameExpr();
|
auto v = args[0]->AsNameExpr();
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
if ( v->GetType()->Tag() != TYPE_VECTOR )
|
||||||
|
return false;
|
||||||
|
|
||||||
AddInst(ZInstI(OP_GET_PORT_TRANSPORT_PROTO_VV, nslot, FrameSlot(pn)));
|
const auto& elt_type = v->GetType()->Yield();
|
||||||
|
|
||||||
return true;
|
if ( args.size() == 1 ) {
|
||||||
}
|
if ( ! IsIntegral(elt_type->Tag()) && elt_type->InternalType() != TYPE_INTERNAL_DOUBLE )
|
||||||
|
return false;
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_network_time(const NameExpr* n, const ExprPList& args) {
|
return OptAssignZBI::Build(zam, n, args);
|
||||||
if ( ! n ) {
|
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
// If we get here, then there's a comparison function.
|
||||||
|
const auto& comp_val = args[1];
|
||||||
|
if ( ! IsFunc(comp_val->GetType()->Tag()) )
|
||||||
|
return false;
|
||||||
|
|
||||||
AddInst(ZInstI(OP_NETWORK_TIME_V, nslot));
|
if ( comp_val->Tag() != EXPR_NAME )
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
auto comp_func = comp_val->AsNameExpr();
|
||||||
}
|
auto comp_type = comp_func->GetType()->AsFuncType();
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_reading_live_traffic(const NameExpr* n, const ExprPList& args) {
|
if ( comp_type->Yield()->Tag() != TYPE_INT || ! comp_type->ParamList()->AllMatch(elt_type, 0) ||
|
||||||
if ( ! n ) {
|
comp_type->ParamList()->GetTypes().size() != 2 )
|
||||||
reporter->Warning("return value from built-in function ignored");
|
return false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
|
|
||||||
AddInst(ZInstI(OP_READING_LIVE_TRAFFIC_V, nslot));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_reading_traces(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( ! n ) {
|
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
|
|
||||||
AddInst(ZInstI(OP_READING_TRACES_V, nslot));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_strstr(const NameExpr* n, const ExprPList& args) {
|
|
||||||
if ( ! n ) {
|
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto big = args[0];
|
|
||||||
auto little = args[1];
|
|
||||||
|
|
||||||
auto big_n = big->Tag() == EXPR_NAME ? big->AsNameExpr() : nullptr;
|
|
||||||
auto little_n = little->Tag() == EXPR_NAME ? little->AsNameExpr() : nullptr;
|
|
||||||
|
|
||||||
ZInstI z;
|
ZInstI z;
|
||||||
|
|
||||||
if ( big_n && little_n )
|
if ( n )
|
||||||
z = GenInst(OP_STRSTR_VVV, n, big_n, little_n);
|
z = ZInstI(OP_SORT_WITH_CMP_VVV, zam->Frame1Slot(n, OP1_WRITE), zam->FrameSlot(v), zam->FrameSlot(comp_func));
|
||||||
else if ( big_n )
|
|
||||||
z = GenInst(OP_STRSTR_VVC, n, big_n, little->AsConstExpr());
|
|
||||||
else if ( little_n )
|
|
||||||
z = GenInst(OP_STRSTR_VCV, n, little_n, big->AsConstExpr());
|
|
||||||
else
|
else
|
||||||
return false;
|
z = ZInstI(OP_SORT_WITH_CMP_VV, zam->FrameSlot(v), zam->FrameSlot(comp_func));
|
||||||
|
|
||||||
AddInst(z);
|
zam->AddInst(z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_sub_bytes(const NameExpr* n, const ExprPList& args) {
|
MultiZBI::MultiZBI(std::string name, bool _ret_val_matters, BiFArgsInfo _args_info, int _type_arg)
|
||||||
if ( ! n ) {
|
: ZAMBuiltIn(std::move(name), _ret_val_matters), args_info(std::move(_args_info)), type_arg(_type_arg) {}
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
MultiZBI::MultiZBI(std::string name, BiFArgsInfo _args_info, BiFArgsInfo _assign_args_info, int _type_arg)
|
||||||
|
: MultiZBI(std::move(name), false, _args_info, _type_arg) {
|
||||||
|
assign_args_info = std::move(_assign_args_info);
|
||||||
|
have_both = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiZBI::Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const {
|
||||||
|
auto ai = &args_info;
|
||||||
|
if ( n && have_both ) {
|
||||||
|
ai = &assign_args_info;
|
||||||
|
ASSERT(! ai->empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto arg_s = args[0];
|
auto bif_arg_info = ai->find(ComputeArgsType(args));
|
||||||
auto arg_start = args[1];
|
if ( bif_arg_info == ai->end() )
|
||||||
auto arg_n = args[2];
|
// Not a Constant/Variable combination this ZBI supports.
|
||||||
|
return false;
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
const auto& bi = bif_arg_info->second;
|
||||||
|
auto op = bi.op;
|
||||||
|
|
||||||
int v2 = FrameSlotIfName(arg_s);
|
std::vector<ValPtr> consts;
|
||||||
int v3 = ConvertToCount(arg_start);
|
std::vector<int> v;
|
||||||
int v4 = ConvertToInt(arg_n);
|
|
||||||
|
|
||||||
auto c = arg_s->Tag() == EXPR_CONST ? arg_s->AsConstExpr() : nullptr;
|
for ( auto i = 0U; i < args.size(); ++i ) {
|
||||||
|
auto a = args[i];
|
||||||
|
if ( a->Tag() == EXPR_NAME )
|
||||||
|
v.push_back(zam->FrameSlot(a->AsNameExpr()));
|
||||||
|
else
|
||||||
|
consts.push_back(a->AsConstExpr()->ValuePtr());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nslot = n ? zam->Frame1Slot(n, OP1_WRITE) : -1;
|
||||||
|
|
||||||
ZInstI z;
|
ZInstI z;
|
||||||
|
|
||||||
switch ( ConstArgsMask(args, 3) ) {
|
if ( args.size() == 2 ) {
|
||||||
case 0x0: // all variable
|
if ( consts.empty() ) {
|
||||||
z = ZInstI(OP_SUB_BYTES_VVVV, nslot, v2, v3, v4);
|
if ( n )
|
||||||
z.op_type = OP_VVVV;
|
z = ZInstI(op, nslot, v[0], v[1]);
|
||||||
break;
|
else
|
||||||
|
z = ZInstI(op, v[0], v[1]);
|
||||||
case 0x1: // last argument a constant
|
}
|
||||||
z = ZInstI(OP_SUB_BYTES_VVVi, nslot, v2, v3, v4);
|
else {
|
||||||
z.op_type = OP_VVVV_I4;
|
ASSERT(consts.size() == 1);
|
||||||
break;
|
if ( n )
|
||||||
|
z = ZInstI(op, nslot, v[0]);
|
||||||
case 0x2: // 2nd argument a constant; flip!
|
else
|
||||||
z = ZInstI(OP_SUB_BYTES_VViV, nslot, v2, v4, v3);
|
z = ZInstI(op, v[0]);
|
||||||
z.op_type = OP_VVVV_I4;
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x3: // both 2nd and third are constants
|
|
||||||
z = ZInstI(OP_SUB_BYTES_VVii, nslot, v2, v3, v4);
|
|
||||||
z.op_type = OP_VVVV_I3_I4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x4: // first argument a constant
|
|
||||||
ASSERT(c);
|
|
||||||
z = ZInstI(OP_SUB_BYTES_VVVC, nslot, v3, v4, c);
|
|
||||||
z.op_type = OP_VVVC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x5: // first and third constant
|
|
||||||
ASSERT(c);
|
|
||||||
z = ZInstI(OP_SUB_BYTES_VViC, nslot, v3, v4, c);
|
|
||||||
z.op_type = OP_VVVC_I3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x6: // first and second constant - flip!
|
|
||||||
ASSERT(c);
|
|
||||||
z = ZInstI(OP_SUB_BYTES_ViVC, nslot, v4, v3, c);
|
|
||||||
z.op_type = OP_VVVC_I3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x7: // whole shebang
|
|
||||||
ASSERT(c);
|
|
||||||
z = ZInstI(OP_SUB_BYTES_ViiC, nslot, v3, v4, c);
|
|
||||||
z.op_type = OP_VVVC_I2_I3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: reporter->InternalError("bad constant mask");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddInst(z);
|
else if ( args.size() == 3 ) {
|
||||||
|
switch ( consts.size() ) {
|
||||||
|
case 0:
|
||||||
|
if ( n )
|
||||||
|
z = ZInstI(op, nslot, v[0], v[1], v[2]);
|
||||||
|
else
|
||||||
|
z = ZInstI(op, v[0], v[1], v[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if ( n )
|
||||||
|
z = ZInstI(op, nslot, v[0], v[1]);
|
||||||
|
else
|
||||||
|
z = ZInstI(op, v[0], v[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
auto c2 = consts[1];
|
||||||
|
auto c2_t = c2->GetType()->Tag();
|
||||||
|
|
||||||
|
ASSERT(c2_t == TYPE_BOOL || c2_t == TYPE_INT || c2_t == TYPE_COUNT);
|
||||||
|
int slot_val;
|
||||||
|
if ( c2_t == TYPE_COUNT )
|
||||||
|
slot_val = static_cast<int>(c2->AsCount());
|
||||||
|
else
|
||||||
|
slot_val = c2->AsInt();
|
||||||
|
|
||||||
|
if ( n )
|
||||||
|
z = ZInstI(op, nslot, v[0], slot_val);
|
||||||
|
else
|
||||||
|
z = ZInstI(op, v[0], slot_val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: reporter->InternalError("inconsistency in MultiZBI::Build");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
reporter->InternalError("inconsistency in MultiZBI::Build");
|
||||||
|
|
||||||
|
z.op_type = bi.op_type;
|
||||||
|
|
||||||
|
if ( n )
|
||||||
|
z.is_managed = ZVal::IsManagedType(n->GetType());
|
||||||
|
|
||||||
|
if ( ! consts.empty() ) {
|
||||||
|
z.t = consts[0]->GetType();
|
||||||
|
z.c = ZVal(consts[0], z.t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type_arg >= 0 && ! z.t )
|
||||||
|
z.t = args[type_arg]->GetType();
|
||||||
|
|
||||||
|
zam->AddInst(z);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::BuiltIn_to_lower(const NameExpr* n, const ExprPList& args) {
|
BiFArgsType MultiZBI::ComputeArgsType(const ExprPList& args) const {
|
||||||
if ( ! n ) {
|
|
||||||
reporter->Warning("return value from built-in function ignored");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nslot = Frame1Slot(n, OP1_WRITE);
|
|
||||||
|
|
||||||
if ( args[0]->Tag() == EXPR_CONST ) {
|
|
||||||
auto arg_c = args[0]->AsConstExpr()->Value()->AsStringVal();
|
|
||||||
ValPtr arg_lc = {AdoptRef{}, ZAM_to_lower(arg_c)};
|
|
||||||
auto arg_lce = make_intrusive<ConstExpr>(arg_lc);
|
|
||||||
auto z = ZInstI(OP_ASSIGN_CONST_VC, nslot, arg_lce.get());
|
|
||||||
z.is_managed = true;
|
|
||||||
AddInst(z);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
auto arg_s = args[0]->AsNameExpr();
|
|
||||||
AddInst(ZInstI(OP_TO_LOWER_VV, nslot, FrameSlot(arg_s)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
zeek_uint_t ZAMCompiler::ConstArgsMask(const ExprPList& args, int nargs) const {
|
|
||||||
ASSERT(args.length() == nargs);
|
|
||||||
|
|
||||||
zeek_uint_t mask = 0;
|
zeek_uint_t mask = 0;
|
||||||
|
|
||||||
for ( int i = 0; i < nargs; ++i ) {
|
for ( auto i = 0U; i < args.size(); ++i ) {
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
if ( args[i]->Tag() == EXPR_CONST )
|
if ( args[i]->Tag() == EXPR_CONST )
|
||||||
mask |= 1;
|
mask |= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mask;
|
return BiFArgsType(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// To create a new built-in, add it to the following collection. We chose
|
||||||
|
// this style with an aim to making the entries both easy to update & readable.
|
||||||
|
// The names of the variables don't matter, so we keep them short to aid
|
||||||
|
// readability.
|
||||||
|
|
||||||
|
SimpleZBI an_ZBI{"Analyzer::__name", OP_ANALYZER_NAME_VC, OP_ANALYZER_NAME_VV};
|
||||||
|
SimpleZBI ae_ZBI{"Files::__analyzer_enabled", OP_ANALYZER_ENABLED_VC, OP_ANALYZER_ENABLED_VV};
|
||||||
|
SimpleZBI fan_ZBI{"Files::__analyzer_name", OP_FILE_ANALYZER_NAME_VC, OP_FILE_ANALYZER_NAME_VV};
|
||||||
|
SimpleZBI fer_ZBI{"Files::__enable_reassembly", OP_FILES_ENABLE_REASSEMBLY_V, 1, false};
|
||||||
|
SimpleZBI ct_ZBI{"clear_table", OP_CLEAR_TABLE_V, 1, false};
|
||||||
|
SimpleZBI currt_ZBI{"current_time", OP_CURRENT_TIME_V, 0};
|
||||||
|
SimpleZBI gptp_ZBI{"get_port_transport_proto", OP_GET_PORT_TRANSPORT_PROTO_VV, 1};
|
||||||
|
SimpleZBI ipa_ZBI{"is_protocol_analyzer", OP_IS_PROTOCOL_ANALYZER_VC, OP_IS_PROTOCOL_ANALYZER_VV, true};
|
||||||
|
SimpleZBI lc_ZBI{"lookup_connection", OP_LOOKUP_CONN_VV, 1};
|
||||||
|
SimpleZBI nt_ZBI{"network_time", OP_NETWORK_TIME_V, 0};
|
||||||
|
SimpleZBI sfh_ZBI{"set_file_handle", OP_SET_FILE_HANDLE_V, 1, false};
|
||||||
|
SimpleZBI sta_ZBI{"subnet_to_addr", OP_SUBNET_TO_ADDR_VV, 1};
|
||||||
|
SimpleZBI ttd_ZBI{"time_to_double", OP_TIME_TO_DOUBLE_VV, 1};
|
||||||
|
SimpleZBI tl_ZBI{"to_lower", OP_TO_LOWER_VV, 1};
|
||||||
|
|
||||||
|
CondZBI ce_ZBI{"connection_exists", OP_CONN_EXISTS_VV, OP_CONN_EXISTS_COND_VV, 1};
|
||||||
|
CondZBI iip_ZBI{"is_icmp_port", OP_IS_ICMP_PORT_VV, OP_IS_ICMP_PORT_COND_VV, 1};
|
||||||
|
CondZBI itp_ZBI{"is_tcp_port", OP_IS_TCP_PORT_VV, OP_IS_TCP_PORT_COND_VV, 1};
|
||||||
|
CondZBI iup_ZBI{"is_udp_port", OP_IS_UDP_PORT_VV, OP_IS_UDP_PORT_COND_VV, 1};
|
||||||
|
CondZBI iv4_ZBI{"is_v4_addr", OP_IS_V4_ADDR_VV, OP_IS_V4_ADDR_COND_VV, 1};
|
||||||
|
CondZBI iv6_ZBI{"is_v6_addr", OP_IS_V6_ADDR_VV, OP_IS_V6_ADDR_COND_VV, 1};
|
||||||
|
CondZBI rlt_ZBI{"reading_live_traffic", OP_READING_LIVE_TRAFFIC_V, OP_READING_LIVE_TRAFFIC_COND_V, 0};
|
||||||
|
CondZBI rt_ZBI{"reading_traces", OP_READING_TRACES_V, OP_READING_TRACES_COND_V, 0};
|
||||||
|
|
||||||
|
// These have a different form to avoid invoking copy constructors.
|
||||||
|
auto cat_ZBI = CatZBI();
|
||||||
|
auto sort_ZBI = SortZBI();
|
||||||
|
|
||||||
|
// For the following, clang-format makes them hard to follow compared to
|
||||||
|
// a manual layout.
|
||||||
|
//
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
OptAssignZBI bfl_ZBI{ "Broker::__flush_logs",
|
||||||
|
OP_BROKER_FLUSH_LOGS_V, OP_BROKER_FLUSH_LOGS_X,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
OptAssignZBI rgc_ZBI{ "PacketAnalyzer::GTPV1::remove_gtpv1_connection",
|
||||||
|
OP_REMOVE_GTPV1_VV, OP_REMOVE_GTPV1_V,
|
||||||
|
1
|
||||||
|
};
|
||||||
|
OptAssignZBI rtc_ZBI{ "PacketAnalyzer::TEREDO::remove_teredo_connection",
|
||||||
|
OP_REMOVE_TEREDO_VV, OP_REMOVE_TEREDO_V,
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI faa_ZBI{ "Files::__add_analyzer",
|
||||||
|
{{{VVV}, {OP_FILES_ADD_ANALYZER_VVV, OP_VVV}},
|
||||||
|
{{VCV}, {OP_FILES_ADD_ANALYZER_ViV, OP_VVC}}},
|
||||||
|
{{{VVV}, {OP_FILES_ADD_ANALYZER_VVVV, OP_VVVV}},
|
||||||
|
{{VCV}, {OP_FILES_ADD_ANALYZER_VViV, OP_VVVC}}},
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI fra_ZBI{ "Files::__remove_analyzer",
|
||||||
|
{{{VVV}, {OP_FILES_REMOVE_ANALYZER_VVV, OP_VVV}},
|
||||||
|
{{VCV}, {OP_FILES_REMOVE_ANALYZER_ViV, OP_VVC}}},
|
||||||
|
{{{VVV}, {OP_FILES_REMOVE_ANALYZER_VVVV, OP_VVVV}},
|
||||||
|
{{VCV}, {OP_FILES_REMOVE_ANALYZER_VViV, OP_VVVC}}},
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI fsrb_ZBI{ "Files::__set_reassembly_buffer",
|
||||||
|
{{{VV}, {OP_FILES_SET_REASSEMBLY_BUFFER_VV, OP_VV}},
|
||||||
|
{{VC}, {OP_FILES_SET_REASSEMBLY_BUFFER_VC, OP_VV_I2}}},
|
||||||
|
{{{VV}, {OP_FILES_SET_REASSEMBLY_BUFFER_VVV, OP_VVV}},
|
||||||
|
{{VC}, {OP_FILES_SET_REASSEMBLY_BUFFER_VVC, OP_VVV_I3}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI lw_ZBI{ "Log::__write",
|
||||||
|
{{{VV}, {OP_LOG_WRITE_VV, OP_VV}},
|
||||||
|
{{CV}, {OP_LOG_WRITEC_V, OP_V}}},
|
||||||
|
{{{VV}, {OP_LOG_WRITE_VVV, OP_VVV}},
|
||||||
|
{{CV}, {OP_LOG_WRITEC_VV, OP_VV}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI gccbt_ZBI{ "get_current_conn_bytes_threshold", true,
|
||||||
|
{{{VV}, {OP_GET_BYTES_THRESH_VVV, OP_VVV}},
|
||||||
|
{{VC}, {OP_GET_BYTES_THRESH_VVi, OP_VVC}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI sccbt_ZBI{ "set_current_conn_bytes_threshold",
|
||||||
|
{{{VVV}, {OP_SET_BYTES_THRESH_VVV, OP_VVV}},
|
||||||
|
{{VVC}, {OP_SET_BYTES_THRESH_VVi, OP_VVC}},
|
||||||
|
{{VCV}, {OP_SET_BYTES_THRESH_ViV, OP_VVC}},
|
||||||
|
{{VCC}, {OP_SET_BYTES_THRESH_Vii, OP_VVC_I2}}},
|
||||||
|
{{{VVV}, {OP_SET_BYTES_THRESH_VVVV, OP_VVVV}},
|
||||||
|
{{VVC}, {OP_SET_BYTES_THRESH_VVVi, OP_VVVC}},
|
||||||
|
{{VCV}, {OP_SET_BYTES_THRESH_VViV, OP_VVVC}},
|
||||||
|
{{VCC}, {OP_SET_BYTES_THRESH_VVii, OP_VVVC_I3}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI sw_ZBI{ "starts_with", true,
|
||||||
|
{{{VV}, {OP_STARTS_WITH_VVV, OP_VVV}},
|
||||||
|
{{VC}, {OP_STARTS_WITH_VVC, OP_VVC}},
|
||||||
|
{{CV}, {OP_STARTS_WITH_VCV, OP_VVC}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI strcmp_ZBI{ "strcmp", true,
|
||||||
|
{{{VV}, {OP_STRCMP_VVV, OP_VVV}},
|
||||||
|
{{VC}, {OP_STRCMP_VVC, OP_VVC}},
|
||||||
|
{{CV}, {OP_STRCMP_VCV, OP_VVC}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI strstr_ZBI{ "strstr", true,
|
||||||
|
{{{VV}, {OP_STRSTR_VVV, OP_VVV}},
|
||||||
|
{{VC}, {OP_STRSTR_VVC, OP_VVC}},
|
||||||
|
{{CV}, {OP_STRSTR_VCV, OP_VVC}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiZBI sb_ZBI{ "sub_bytes", true,
|
||||||
|
{{{VVV}, {OP_SUB_BYTES_VVVV, OP_VVVV}},
|
||||||
|
{{VVC}, {OP_SUB_BYTES_VVVi, OP_VVVC}},
|
||||||
|
{{VCV}, {OP_SUB_BYTES_VViV, OP_VVVC}},
|
||||||
|
{{VCC}, {OP_SUB_BYTES_VVii, OP_VVVC_I3}},
|
||||||
|
{{CVV}, {OP_SUB_BYTES_VVVC, OP_VVVC}},
|
||||||
|
{{CVC}, {OP_SUB_BYTES_VViC, OP_VVVC_I3}},
|
||||||
|
{{CCV}, {OP_SUB_BYTES_ViVC, OP_VVVC_I3}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Helper function that extracts the underlying Func* from a CallExpr
|
||||||
|
// node. Returns nil if it's not accessible.
|
||||||
|
static const Func* get_func(const CallExpr* c) {
|
||||||
|
auto func_expr = c->Func();
|
||||||
|
if ( func_expr->Tag() != EXPR_NAME )
|
||||||
|
// An indirect call.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto func_val = func_expr->AsNameExpr()->Id()->GetVal();
|
||||||
|
if ( ! func_val )
|
||||||
|
// A call to a function that hasn't been defined.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return func_val->AsFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsZAM_BuiltIn(ZAMCompiler* zam, const Expr* e) {
|
||||||
|
// The expression e is either directly a call (in which case there's
|
||||||
|
// no return value), or an assignment to a call.
|
||||||
|
const CallExpr* c;
|
||||||
|
|
||||||
|
if ( e->Tag() == EXPR_CALL )
|
||||||
|
c = e->AsCallExpr();
|
||||||
|
else
|
||||||
|
c = e->GetOp2()->AsCallExpr();
|
||||||
|
|
||||||
|
auto func = get_func(c);
|
||||||
|
if ( ! func )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string fn = func->Name();
|
||||||
|
|
||||||
|
// It's useful to intercept any lingering calls to the script-level
|
||||||
|
// Log::write as well as the Log::__write BiF. When inlining there can
|
||||||
|
// still be script-level calls if the calling function got too big to
|
||||||
|
// inline them. We could do this for other script-level functions that
|
||||||
|
// are simply direct wrappers for BiFs, but this is only one that has
|
||||||
|
// turned up as significant in profiling.
|
||||||
|
if ( fn == "Log::write" )
|
||||||
|
fn = "Log::__write";
|
||||||
|
|
||||||
|
auto b = builtins.find(fn);
|
||||||
|
if ( b == builtins.end() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& bi = b->second;
|
||||||
|
|
||||||
|
const NameExpr* n = nullptr; // name to assign to, if any
|
||||||
|
if ( e->Tag() != EXPR_CALL )
|
||||||
|
n = e->GetOp1()->AsRefExpr()->GetOp1()->AsNameExpr();
|
||||||
|
|
||||||
|
if ( bi->ReturnValMatters() ) {
|
||||||
|
if ( ! n ) {
|
||||||
|
reporter->Warning("return value from built-in function ignored");
|
||||||
|
|
||||||
|
// The call is a no-op. We could return false here and have it
|
||||||
|
// execute (for no purpose). We can also return true, which will
|
||||||
|
// have the effect of just ignoring the statement.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( n && ! bi->HaveBothReturnValAndNon() )
|
||||||
|
// Because the return value "doesn't matter", we've built the
|
||||||
|
// corresponding ZIB assuming we don't need a version that does
|
||||||
|
// the assignment. If we *do* have an assignment, let the usual
|
||||||
|
// call take place.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return bi->Build(zam, n, c->Args()->Exprs());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsZAM_BuiltInCond(ZAMCompiler* zam, const CallExpr* c, int& branch_v) {
|
||||||
|
auto func = get_func(c);
|
||||||
|
if ( ! func )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto b = builtins.find(func->Name());
|
||||||
|
if ( b == builtins.end() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return b->second->BuildCond(zam, c->Args()->Exprs(), branch_v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsZAM_BuiltInCond(const CallExpr* c) {
|
||||||
|
int branch_v; // ignored
|
||||||
|
return IsZAM_BuiltInCond(nullptr, c, branch_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace zeek::detail
|
} // namespace zeek::detail
|
||||||
|
|
|
@ -1,29 +1,195 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
// ZAM compiler method declarations for built-in functions.
|
// ZAM classes for built-in functions. We refer to the script-level notion
|
||||||
//
|
// as a BiF, and the (potential) ZAM-level replacement as a ZBI = ZAM built-in.
|
||||||
// This file is only included by ZAM.h, in the context of the ZAM class
|
|
||||||
// declaration (so these are methods, not standalone functions). We maintain
|
|
||||||
// it separately so that the conceptual overhead of adding a new built-in
|
|
||||||
// is lower.
|
|
||||||
|
|
||||||
// If the given expression corresponds to a call to a ZAM built-in,
|
#pragma once
|
||||||
// then compiles the call and returns true. Otherwise, returns false.
|
|
||||||
bool IsZAM_BuiltIn(const Expr* e);
|
|
||||||
|
|
||||||
// Built-ins return true if able to compile the call, false if not.
|
#include "zeek/Expr.h"
|
||||||
bool BuiltIn_Analyzer__name(const NameExpr* n, const ExprPList& args);
|
#include "zeek/script_opt/ZAM/Compile.h"
|
||||||
bool BuiltIn_Broker__flush_logs(const NameExpr* n, const ExprPList& args);
|
|
||||||
bool BuiltIn_Files__enable_reassembly(const NameExpr* n, const ExprPList& args);
|
namespace zeek::detail {
|
||||||
bool BuiltIn_Files__set_reassembly_buffer(const NameExpr* n, const ExprPList& args);
|
|
||||||
bool BuiltIn_Log__write(const NameExpr* n, const ExprPList& args);
|
// Base class for analyzing function calls to BiFs to see if they can
|
||||||
bool BuiltIn_cat(const NameExpr* n, const ExprPList& args);
|
// be replaced with ZBIs.
|
||||||
ZInstAux* BuildCatAux(const ExprPList& args);
|
class ZAMBuiltIn {
|
||||||
bool BuiltIn_current_time(const NameExpr* n, const ExprPList& args);
|
public:
|
||||||
bool BuiltIn_get_port_etc(const NameExpr* n, const ExprPList& args);
|
// Constructed using the name of the BiF and a flag that if true means
|
||||||
bool BuiltIn_network_time(const NameExpr* n, const ExprPList& args);
|
// that the point of calling the BiF is to do something with its return
|
||||||
bool BuiltIn_reading_live_traffic(const NameExpr* n, const ExprPList& args);
|
// value (in particular, the BiF does not have side-effects).
|
||||||
bool BuiltIn_reading_traces(const NameExpr* n, const ExprPList& args);
|
ZAMBuiltIn(std::string name, bool _ret_val_matters);
|
||||||
bool BuiltIn_strstr(const NameExpr* n, const ExprPList& args);
|
virtual ~ZAMBuiltIn() = default;
|
||||||
bool BuiltIn_sub_bytes(const NameExpr* n, const ExprPList& args);
|
|
||||||
bool BuiltIn_to_lower(const NameExpr* n, const ExprPList& args);
|
bool ReturnValMatters() const { return ret_val_matters; }
|
||||||
|
bool HaveBothReturnValAndNon() const { return have_both; }
|
||||||
|
|
||||||
|
// Called to compile, if appropriate, a call to the BiF into the
|
||||||
|
// corresponding specialized instruction. "n", if non-nil, provides
|
||||||
|
// the assignment target for the return value. "args" are the (reduced)
|
||||||
|
// arguments in the call, all either names or constants.
|
||||||
|
//
|
||||||
|
// Returns true if the replacement was successful, false if it's not
|
||||||
|
// appropriate.
|
||||||
|
virtual bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const = 0;
|
||||||
|
|
||||||
|
// Similar to Build(), but done in the context of a conditional. If
|
||||||
|
// successful, "branch_v" is updated with the slot in the newly added
|
||||||
|
// instruction where the branch target lives.
|
||||||
|
//
|
||||||
|
// If "zam" is nil then does the true/false checking but not the actual
|
||||||
|
// compilation. In this case, "branch_v" is unchanged.
|
||||||
|
virtual bool BuildCond(ZAMCompiler* zam, const ExprPList& args, int& branch_v) const { return false; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ret_val_matters = true;
|
||||||
|
|
||||||
|
// If true, then there are two versions of the ZBI, one for returning
|
||||||
|
// a value and one for when the value is ignored.
|
||||||
|
bool have_both = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class for dealing with simple 0- or 1-argument ZBIs that don't have
|
||||||
|
// any special considerations for applicability or compiling. These are
|
||||||
|
// quite common.
|
||||||
|
class SimpleZBI : public ZAMBuiltIn {
|
||||||
|
public:
|
||||||
|
// This constructor is for ZBIs that either take no arguments, or always
|
||||||
|
// take a single variable as their argument.
|
||||||
|
SimpleZBI(std::string name, ZOp _op, int _nargs, bool _ret_val_matters = true);
|
||||||
|
|
||||||
|
// A version for supporting a single argument that can be either a
|
||||||
|
// constant (first operand) or a variable (second operand).
|
||||||
|
SimpleZBI(std::string name, ZOp _const_op, ZOp _op, bool _ret_val_matters = true);
|
||||||
|
|
||||||
|
bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Operand used for the 0-argument or 1-argument-that's-a-variable case.
|
||||||
|
ZOp op;
|
||||||
|
|
||||||
|
// Operand used for the 1-argument-that's-a-constant case.
|
||||||
|
ZOp const_op = OP_NOP;
|
||||||
|
|
||||||
|
int nargs;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A form of simple ZBIs that also support calling the BiF in a conditional.
|
||||||
|
class CondZBI : public SimpleZBI {
|
||||||
|
public:
|
||||||
|
CondZBI(std::string name, ZOp _op, ZOp _cond_op, int _nargs);
|
||||||
|
|
||||||
|
bool BuildCond(ZAMCompiler* zam, const ExprPList& args, int& branch_v) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ZOp cond_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A form of simple ZBIs that support assignment but do not require it.
|
||||||
|
class OptAssignZBI : public SimpleZBI {
|
||||||
|
public:
|
||||||
|
// Second argument is assignment flavor, third is assignment-less flavor.
|
||||||
|
OptAssignZBI(std::string name, ZOp _op, ZOp _op2, int _nargs);
|
||||||
|
|
||||||
|
bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ZOp op2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The cat() ZBI has an involved build process that can employ a number
|
||||||
|
// of different ZAM operations.
|
||||||
|
class CatZBI : public ZAMBuiltIn {
|
||||||
|
public:
|
||||||
|
CatZBI() : ZAMBuiltIn("cat", true) {}
|
||||||
|
|
||||||
|
bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// cat() ZBIs can have complex auxiliary information capturing the various
|
||||||
|
// transformations (and fixed strings) to compute for each call.
|
||||||
|
ZInstAux* BuildCatAux(ZAMCompiler* zam, const ExprPList& args) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The sort() ZBI needs to refrain from replacing the BiF call if the
|
||||||
|
// arguments will generate an error (which can be determined at compile-time).
|
||||||
|
// Doing so enables us to streamline the corresponding ZAM operations.
|
||||||
|
class SortZBI : public OptAssignZBI {
|
||||||
|
public:
|
||||||
|
SortZBI() : OptAssignZBI("sort", OP_SORT_VV, OP_SORT_V, 1) {}
|
||||||
|
|
||||||
|
bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// The last form of ZBI is for more complex BiFs that take multiple arguments,
|
||||||
|
// which vary in whether some of them can be constants or have to be variables.
|
||||||
|
// Currently, 2- and 3-argument BiFs are supported.
|
||||||
|
|
||||||
|
// The following encodes the possible patterns of 2- and 3-argument calls
|
||||||
|
// to BiFs. V = Variable argument, C = Constant argument. The enums have
|
||||||
|
// values assigned to them reflecting the bit-pattern of the arguments from
|
||||||
|
// left (most significant) to right (least), with a 1-bit encoding Constant,
|
||||||
|
// 0-bit for Variable.
|
||||||
|
enum BiFArgsType {
|
||||||
|
VV = 0x0,
|
||||||
|
VC = 0x1,
|
||||||
|
CV = 0x2,
|
||||||
|
CC = 0x3,
|
||||||
|
|
||||||
|
VVV = 0x0,
|
||||||
|
VVC = 0x1,
|
||||||
|
VCV = 0x2,
|
||||||
|
VCC = 0x3,
|
||||||
|
CVV = 0x4,
|
||||||
|
CVC = 0x5,
|
||||||
|
CCV = 0x6,
|
||||||
|
CCC = 0x7,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following captures a ZAM operation and its associated operand type.
|
||||||
|
struct BiFArgInfo {
|
||||||
|
ZOp op;
|
||||||
|
ZAMOpType op_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A map that associates ZAM operations (and types) with particular
|
||||||
|
// argument patterns.
|
||||||
|
using BiFArgsInfo = std::map<BiFArgsType, BiFArgInfo>;
|
||||||
|
|
||||||
|
// Class for supporting ZBIs that take multiple (i.e., > 1) arguments.
|
||||||
|
class MultiZBI : public ZAMBuiltIn {
|
||||||
|
public:
|
||||||
|
// This first constructor is for ZBIs that either always have return
|
||||||
|
// values or never do, and thus need just one BiFArgsInfo map.
|
||||||
|
// If "_type_arg" is non-negative, then it specifies which argument
|
||||||
|
// (numbered left-to-right, starting at 0) should be used to set the
|
||||||
|
// Zeek type associated with the generated ZAM instruction.
|
||||||
|
MultiZBI(std::string name, bool _ret_val_matters, BiFArgsInfo _args_info, int _type_arg = -1);
|
||||||
|
|
||||||
|
// Alternative constructor for ZBIs that have optional return values.
|
||||||
|
// The first map is for the non-assignment case, the second for the
|
||||||
|
// assignment case.
|
||||||
|
MultiZBI(std::string name, BiFArgsInfo _args_info, BiFArgsInfo _assign_args_info, int _type_arg = -1);
|
||||||
|
|
||||||
|
bool Build(ZAMCompiler* zam, const NameExpr* n, const ExprPList& args) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Returns an enum describing the pattern of Constants/Variables in the
|
||||||
|
// given argument list.
|
||||||
|
BiFArgsType ComputeArgsType(const ExprPList& args) const;
|
||||||
|
|
||||||
|
BiFArgsInfo args_info;
|
||||||
|
BiFArgsInfo assign_args_info;
|
||||||
|
int type_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the given expression corresponds to a call to a ZAM built-in, then
|
||||||
|
// compiles the call and returns true. Otherwise, returns false.
|
||||||
|
extern bool IsZAM_BuiltIn(ZAMCompiler* zam, const Expr* e);
|
||||||
|
|
||||||
|
// If the given expression corresponds to a call to a ZAM built-in that has
|
||||||
|
// a conditional version, compiles the conditional and returns true, and
|
||||||
|
// updates branch_v to reflect the branch slot. Otherwise, returns false.
|
||||||
|
extern bool IsZAM_BuiltInCond(ZAMCompiler* zam, const CallExpr* c, int& branch_v);
|
||||||
|
|
||||||
|
} // namespace zeek::detail
|
||||||
|
|
|
@ -85,6 +85,13 @@ public:
|
||||||
void Dump();
|
void Dump();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class SimpleZBI;
|
||||||
|
friend class CondZBI;
|
||||||
|
friend class OptAssignZBI;
|
||||||
|
friend class SortZBI;
|
||||||
|
friend class CatZBI;
|
||||||
|
friend class MultiZBI;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void InitGlobals();
|
void InitGlobals();
|
||||||
void InitArgs();
|
void InitArgs();
|
||||||
|
@ -182,6 +189,7 @@ private:
|
||||||
const ZAMStmt CompileAddToExpr(const AddToExpr* e);
|
const ZAMStmt CompileAddToExpr(const AddToExpr* e);
|
||||||
const ZAMStmt CompileRemoveFromExpr(const RemoveFromExpr* e);
|
const ZAMStmt CompileRemoveFromExpr(const RemoveFromExpr* e);
|
||||||
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
||||||
|
const ZAMStmt CompileZAMBuiltin(const NameExpr* lhs, const ScriptOptBuiltinExpr* zbi);
|
||||||
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs);
|
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs);
|
||||||
const ZAMStmt CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e);
|
const ZAMStmt CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e);
|
||||||
const ZAMStmt CompileScheduleExpr(const ScheduleExpr* e);
|
const ZAMStmt CompileScheduleExpr(const ScheduleExpr* e);
|
||||||
|
@ -246,17 +254,8 @@ private:
|
||||||
|
|
||||||
const ZAMStmt Is(const NameExpr* n, const Expr* e);
|
const ZAMStmt Is(const NameExpr* n, const Expr* e);
|
||||||
|
|
||||||
#include "zeek/script_opt/ZAM/BuiltIn.h"
|
|
||||||
#include "zeek/script_opt/ZAM/Inst-Gen.h"
|
#include "zeek/script_opt/ZAM/Inst-Gen.h"
|
||||||
|
|
||||||
// A bit weird, but handy for switch statements used in built-in
|
|
||||||
// operations: returns a bit mask of which of the arguments in the
|
|
||||||
// given list correspond to constants, with the high-ordered bit
|
|
||||||
// being the first argument (argument "0" in the list) and the
|
|
||||||
// low-ordered bit being the last. Second parameter is the number
|
|
||||||
// of arguments that should be present.
|
|
||||||
zeek_uint_t ConstArgsMask(const ExprPList& args, int nargs) const;
|
|
||||||
|
|
||||||
int ConvertToInt(const Expr* e) {
|
int ConvertToInt(const Expr* e) {
|
||||||
if ( e->Tag() == EXPR_NAME )
|
if ( e->Tag() == EXPR_NAME )
|
||||||
return FrameSlot(e->AsNameExpr()->Id());
|
return FrameSlot(e->AsNameExpr()->Id());
|
||||||
|
|
|
@ -971,7 +971,7 @@ const ZAMStmt ZAMCompiler::AssignToCall(const ExprStmt* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZAMCompiler::CheckForBuiltIn(const ExprPtr& e, CallExprPtr c) {
|
bool ZAMCompiler::CheckForBuiltIn(const ExprPtr& e, CallExprPtr c) {
|
||||||
if ( ! IsZAM_BuiltIn(e.get()) )
|
if ( ! IsZAM_BuiltIn(this, e.get()) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto ret = LastInst();
|
auto ret = LastInst();
|
||||||
|
|
|
@ -2360,21 +2360,76 @@ macro EvalSubBytes(arg1, arg2, arg3)
|
||||||
frame[z.v1].string_val = sv;
|
frame[z.v1].string_val = sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal-op Remove-Teredo
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval auto teredo = zeek::packet_mgr->GetAnalyzer("Teredo");
|
||||||
|
if ( teredo )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key(frame[z.v1].record_val);
|
||||||
|
static_cast<zeek::packet_analysis::teredo::TeredoAnalyzer*>(teredo.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Remove-Teredo
|
||||||
|
side-effects OP_REMOVE_TEREDO_V OP_V
|
||||||
|
type VV
|
||||||
|
eval auto teredo = zeek::packet_mgr->GetAnalyzer("Teredo");
|
||||||
|
if ( teredo )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key(frame[z.v2].record_val);
|
||||||
|
static_cast<zeek::packet_analysis::teredo::TeredoAnalyzer*>(teredo.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
frame[z.v1].int_val = 1;
|
||||||
|
|
||||||
|
internal-op Remove-GTPv1
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval auto gtpv1 = zeek::packet_mgr->GetAnalyzer("GTPv1");
|
||||||
|
if ( gtpv1 )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key(frame[z.v1].record_val);
|
||||||
|
static_cast<zeek::packet_analysis::gtpv1::GTPv1_Analyzer*>(gtpv1.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Remove-GTPv1
|
||||||
|
side-effects OP_REMOVE_GTPV1_V OP_V
|
||||||
|
type VV
|
||||||
|
eval auto gtpv1 = zeek::packet_mgr->GetAnalyzer("GTPv1");
|
||||||
|
if ( gtpv1 )
|
||||||
|
{
|
||||||
|
zeek::detail::ConnKey conn_key(frame[z.v2].record_val);
|
||||||
|
static_cast<zeek::packet_analysis::gtpv1::GTPv1_Analyzer*>(gtpv1.get())->RemoveConnection(conn_key);
|
||||||
|
}
|
||||||
|
frame[z.v1].int_val = 1;
|
||||||
|
|
||||||
|
internal-op Set-File-Handle
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval auto handle = frame[z.v1].string_val;
|
||||||
|
auto bytes = reinterpret_cast<const char*>(handle->Bytes());
|
||||||
|
auto h = std::string(bytes, handle->Len());
|
||||||
|
zeek::file_mgr->SetHandle(h);
|
||||||
|
|
||||||
|
internal-op Subnet-To-Addr
|
||||||
|
type VV
|
||||||
|
eval Unref(frame[z.v1].addr_val);
|
||||||
|
frame[z.v1] = ZVal(make_intrusive<AddrVal>(frame[z.v2].subnet_val->Prefix()));
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Sub-Bytes
|
||||||
type VVVV
|
type VVVV
|
||||||
eval EvalSubBytes(frame[z.v2], frame[z.v3].uint_val, frame[z.v4].int_val)
|
eval EvalSubBytes(frame[z.v2], frame[z.v3].uint_val, frame[z.v4].int_val)
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Sub-Bytes
|
||||||
type VVVi
|
type VVVi
|
||||||
eval EvalSubBytes(frame[z.v2], frame[z.v3].uint_val, z.v4)
|
eval EvalSubBytes(frame[z.v2], frame[z.v3].uint_val, z.c.int_val)
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Sub-Bytes
|
||||||
type VViV
|
type VViV
|
||||||
eval EvalSubBytes(frame[z.v2], zeek_uint_t(z.v4), frame[z.v3].int_val)
|
eval EvalSubBytes(frame[z.v2], z.c.uint_val, frame[z.v3].int_val)
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Sub-Bytes
|
||||||
type VVii
|
type VVii
|
||||||
eval EvalSubBytes(frame[z.v2], zeek_uint_t(z.v3), z.v4)
|
eval EvalSubBytes(frame[z.v2], z.c.uint_val, z.v3)
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Sub-Bytes
|
||||||
type VVVC
|
type VVVC
|
||||||
|
@ -2388,9 +2443,9 @@ internal-op Sub-Bytes
|
||||||
type ViVC
|
type ViVC
|
||||||
eval EvalSubBytes(z.c, zeek_uint_t(z.v3), frame[z.v2].uint_val)
|
eval EvalSubBytes(z.c, zeek_uint_t(z.v3), frame[z.v2].uint_val)
|
||||||
|
|
||||||
internal-op Sub-Bytes
|
internal-op Time-To-Double
|
||||||
type ViiC
|
type VV
|
||||||
eval EvalSubBytes(z.c, zeek_uint_t(z.v2), z.v3)
|
eval frame[z.v1] = frame[z.v2];
|
||||||
|
|
||||||
|
|
||||||
internal-op To-Lower
|
internal-op To-Lower
|
||||||
|
@ -2412,8 +2467,8 @@ eval auto sv = ZAM_to_lower(frame[z.v2].string_val);
|
||||||
# actually used.
|
# actually used.
|
||||||
|
|
||||||
macro LogWritePre(id_val, columns_slot)
|
macro LogWritePre(id_val, columns_slot)
|
||||||
auto id = id_val;
|
auto id = id_val.ToVal(ZAM::log_ID_enum_type);
|
||||||
auto columns = frame[z.columns_slot].ToVal(z.t);
|
auto columns = frame[z.columns_slot].record_val;
|
||||||
|
|
||||||
macro LogWriteResPost()
|
macro LogWriteResPost()
|
||||||
bool result = log_mgr->Write(id->AsEnumVal(), columns->AsRecordVal());
|
bool result = log_mgr->Write(id->AsEnumVal(), columns->AsRecordVal());
|
||||||
|
@ -2425,13 +2480,13 @@ macro LogWriteNoResPost()
|
||||||
internal-op Log-Write
|
internal-op Log-Write
|
||||||
side-effects OP_LOG_WRITE_VV OP_VV
|
side-effects OP_LOG_WRITE_VV OP_VV
|
||||||
type VVV
|
type VVV
|
||||||
eval LogWritePre(frame[z.v2].ToVal(ZAM::log_ID_enum_type), v3)
|
eval LogWritePre(frame[z.v2], v3)
|
||||||
LogWriteResPost()
|
LogWriteResPost()
|
||||||
|
|
||||||
internal-op Log-WriteC
|
internal-op Log-WriteC
|
||||||
side-effects OP_LOG_WRITEC_V OP_V
|
side-effects OP_LOG_WRITEC_V OP_V
|
||||||
type VV
|
type VV
|
||||||
eval LogWritePre(z.aux->elems[0].Constant(), v2)
|
eval LogWritePre(z.c, v2)
|
||||||
LogWriteResPost()
|
LogWriteResPost()
|
||||||
|
|
||||||
# Versions that discard the return value.
|
# Versions that discard the return value.
|
||||||
|
@ -2439,14 +2494,14 @@ internal-op Log-Write
|
||||||
side-effects
|
side-effects
|
||||||
op1-read
|
op1-read
|
||||||
type VV
|
type VV
|
||||||
eval LogWritePre(frame[z.v1].ToVal(ZAM::log_ID_enum_type), v2)
|
eval LogWritePre(frame[z.v1], v2)
|
||||||
LogWriteNoResPost()
|
LogWriteNoResPost()
|
||||||
|
|
||||||
internal-op Log-WriteC
|
internal-op Log-WriteC
|
||||||
side-effects
|
side-effects
|
||||||
op1-read
|
op1-read
|
||||||
type V
|
type V
|
||||||
eval LogWritePre(z.aux->elems[0].Constant(), v1)
|
eval LogWritePre(z.c, v1)
|
||||||
LogWriteNoResPost()
|
LogWriteNoResPost()
|
||||||
|
|
||||||
internal-op Broker-Flush-Logs
|
internal-op Broker-Flush-Logs
|
||||||
|
@ -2471,6 +2526,116 @@ eval auto mask = frame[z.v2].uint_val & PORT_SPACE_MASK;
|
||||||
v = 3;
|
v = 3;
|
||||||
frame[z.v1].uint_val = v;
|
frame[z.v1].uint_val = v;
|
||||||
|
|
||||||
|
internal-op Conn-Exists
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = session_mgr->FindConnection(frame[z.v2].record_val) != nullptr;
|
||||||
|
|
||||||
|
internal-op Conn-Exists-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( ! session_mgr->FindConnection(frame[z.v1].record_val) )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Conn-Exists-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( session_mgr->FindConnection(frame[z.v1].record_val) )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Lookup-Conn
|
||||||
|
type VV
|
||||||
|
eval auto cid = frame[z.v2].record_val;
|
||||||
|
Connection* conn = session_mgr->FindConnection(cid);
|
||||||
|
ValPtr res;
|
||||||
|
if ( conn )
|
||||||
|
res = conn->GetVal();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ZAM_run_time_error(z.loc, "connection ID not a known connection", cid);
|
||||||
|
res = build_dummy_conn_record();
|
||||||
|
}
|
||||||
|
AssignV1(ZVal(res, res->GetType()));
|
||||||
|
|
||||||
|
internal-op Is-ICMP-Port
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = (frame[z.v2].uint_val & PORT_SPACE_MASK) == ICMP_PORT_MASK;
|
||||||
|
|
||||||
|
internal-op Is-ICMP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) != ICMP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Is-ICMP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) == ICMP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Is-TCP-Port
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = (frame[z.v2].uint_val & PORT_SPACE_MASK) == TCP_PORT_MASK;
|
||||||
|
|
||||||
|
internal-op Is-TCP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) != TCP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Is-TCP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) == TCP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Is-UDP-Port
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = (frame[z.v2].uint_val & PORT_SPACE_MASK) == UDP_PORT_MASK;
|
||||||
|
|
||||||
|
internal-op Is-UDP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) != UDP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Is-UDP-Port-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( (frame[z.v1].uint_val & PORT_SPACE_MASK) == UDP_PORT_MASK )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Is-V4-Addr
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = frame[z.v2].addr_val->AsAddr().GetFamily() == IPv4;
|
||||||
|
|
||||||
|
internal-op Is-V4-Addr-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( frame[z.v1].addr_val->AsAddr().GetFamily() != IPv4 )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Is-V4-Addr-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( frame[z.v1].addr_val->AsAddr().GetFamily() == IPv4 )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Is-V6-Addr
|
||||||
|
type VV
|
||||||
|
eval frame[z.v1].int_val = frame[z.v2].addr_val->AsAddr().GetFamily() == IPv6;
|
||||||
|
|
||||||
|
internal-op Is-V6-Addr-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( frame[z.v1].addr_val->AsAddr().GetFamily() != IPv6 )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
|
internal-op Not-Is-V6-Addr-Cond
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( frame[z.v1].addr_val->AsAddr().GetFamily() == IPv6 )
|
||||||
|
BRANCH(v2)
|
||||||
|
|
||||||
internal-op Network-Time
|
internal-op Network-Time
|
||||||
type V
|
type V
|
||||||
eval frame[z.v1].double_val = run_state::network_time;
|
eval frame[z.v1].double_val = run_state::network_time;
|
||||||
|
@ -2483,19 +2648,120 @@ internal-op Reading-Live-Traffic
|
||||||
type V
|
type V
|
||||||
eval frame[z.v1].int_val = run_state::reading_live;
|
eval frame[z.v1].int_val = run_state::reading_live;
|
||||||
|
|
||||||
|
internal-op Reading-Live-Traffic-Cond
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval if ( ! run_state::reading_live )
|
||||||
|
BRANCH(v1)
|
||||||
|
|
||||||
|
internal-op Not-Reading-Live-Traffic-Cond
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval if ( run_state::reading_live )
|
||||||
|
BRANCH(v1)
|
||||||
|
|
||||||
internal-op Reading-Traces
|
internal-op Reading-Traces
|
||||||
type V
|
type V
|
||||||
eval frame[z.v1].int_val = run_state::reading_traces;
|
eval frame[z.v1].int_val = run_state::reading_traces;
|
||||||
|
|
||||||
internal-op StrStr
|
internal-op Reading-Traces-Cond
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval if ( ! run_state::reading_traces )
|
||||||
|
BRANCH(v1)
|
||||||
|
|
||||||
|
internal-op Not-Reading-Traces-Cond
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval if ( run_state::reading_traces )
|
||||||
|
BRANCH(v1)
|
||||||
|
|
||||||
|
internal-op Sort
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval if ( frame[z.v1].vector_val->Size() > 1 )
|
||||||
|
frame[z.v1].vector_val->Sort();
|
||||||
|
|
||||||
|
internal-op Sort
|
||||||
|
type VV
|
||||||
|
eval auto vv = frame[z.v2].vector_val;
|
||||||
|
if ( vv->Size() > 1 )
|
||||||
|
vv->Sort();
|
||||||
|
zeek::Ref(vv);
|
||||||
|
Unref(frame[z.v1].vector_val);
|
||||||
|
frame[z.v1].vector_val = vv;
|
||||||
|
|
||||||
|
internal-op Sort-With-Cmp
|
||||||
|
op1-read
|
||||||
|
type VV
|
||||||
|
eval if ( frame[z.v1].vector_val->Size() > 1 )
|
||||||
|
frame[z.v1].vector_val->Sort(frame[z.v2].func_val);
|
||||||
|
|
||||||
|
internal-op Sort-With-Cmp
|
||||||
type VVV
|
type VVV
|
||||||
eval EvalStrStr(frame[z.v2], frame[z.v3])
|
eval auto vv = frame[z.v2].vector_val;
|
||||||
|
if ( vv->Size() > 1 )
|
||||||
|
vv->Sort(frame[z.v3].func_val);
|
||||||
|
zeek::Ref(vv);
|
||||||
|
Unref(frame[z.v1].vector_val);
|
||||||
|
frame[z.v1].vector_val = vv;
|
||||||
|
|
||||||
|
macro EvalStartsWith(str_val, sub_val)
|
||||||
|
auto str = str_val.string_val;
|
||||||
|
auto sub = sub_val.string_val;
|
||||||
|
auto str_n = str->Len();
|
||||||
|
auto sub_n = sub->Len();
|
||||||
|
if ( str_n < sub_n )
|
||||||
|
frame[z.v1].int_val = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto str_b = str->Bytes();
|
||||||
|
auto sub_b = sub->Bytes();
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i < sub_n; ++i )
|
||||||
|
if ( str_b[i] != sub_b[i] )
|
||||||
|
break;
|
||||||
|
frame[z.v1].int_val = i == sub_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Starts-With
|
||||||
|
type VVV
|
||||||
|
eval EvalStartsWith(frame[z.v2], frame[z.v3])
|
||||||
|
|
||||||
|
internal-op Starts-With
|
||||||
|
type VCV
|
||||||
|
eval EvalStartsWith(z.c, frame[z.v2])
|
||||||
|
|
||||||
|
internal-op Starts-With
|
||||||
|
type VVC
|
||||||
|
eval EvalStartsWith(frame[z.v2], z.c)
|
||||||
|
|
||||||
|
macro EvalStrCmp(s1_src, s2_src)
|
||||||
|
auto s1 = s1_src.string_val;
|
||||||
|
auto s2 = s2_src.string_val;
|
||||||
|
frame[z.v1].int_val = Bstr_cmp(s1->AsString(), s2->AsString());
|
||||||
|
|
||||||
|
internal-op StrCmp
|
||||||
|
type VVV
|
||||||
|
eval EvalStrCmp(frame[z.v2], frame[z.v3])
|
||||||
|
|
||||||
|
internal-op StrCmp
|
||||||
|
type VCV
|
||||||
|
eval EvalStrCmp(z.c, frame[z.v2])
|
||||||
|
|
||||||
|
internal-op StrCmp
|
||||||
|
type VVC
|
||||||
|
eval EvalStrCmp(frame[z.v2], z.c)
|
||||||
|
|
||||||
macro EvalStrStr(big_value, little_value)
|
macro EvalStrStr(big_value, little_value)
|
||||||
auto big = big_value.string_val;
|
auto big = big_value.string_val;
|
||||||
auto little = little_value.string_val;
|
auto little = little_value.string_val;
|
||||||
frame[z.v1].int_val = 1 + big->AsString()->FindSubstring(little->AsString());
|
frame[z.v1].int_val = 1 + big->AsString()->FindSubstring(little->AsString());
|
||||||
|
|
||||||
|
internal-op StrStr
|
||||||
|
type VVV
|
||||||
|
eval EvalStrStr(frame[z.v2], frame[z.v3])
|
||||||
|
|
||||||
internal-op StrStr
|
internal-op StrStr
|
||||||
type VCV
|
type VCV
|
||||||
eval EvalStrStr(z.c, frame[z.v2])
|
eval EvalStrStr(z.c, frame[z.v2])
|
||||||
|
@ -2674,9 +2940,8 @@ eval CatNPre()
|
||||||
ca[7]->RenderInto(frame, aux->elems[7].Slot(), res_p);
|
ca[7]->RenderInto(frame, aux->elems[7].Slot(), res_p);
|
||||||
CatNPost()
|
CatNPost()
|
||||||
|
|
||||||
internal-op Analyzer--Name
|
macro AnalyzerName(tag)
|
||||||
type VV
|
auto atype = tag.ToVal(z.t);
|
||||||
eval auto atype = frame[z.v2].ToVal(z.t);
|
|
||||||
auto val = atype->AsEnumVal();
|
auto val = atype->AsEnumVal();
|
||||||
Unref(frame[z.v1].string_val);
|
Unref(frame[z.v1].string_val);
|
||||||
plugin::Component* component = zeek::analyzer_mgr->Lookup(val);
|
plugin::Component* component = zeek::analyzer_mgr->Lookup(val);
|
||||||
|
@ -2689,20 +2954,291 @@ eval auto atype = frame[z.v2].ToVal(z.t);
|
||||||
else
|
else
|
||||||
frame[z.v1].string_val = new StringVal("<error>");
|
frame[z.v1].string_val = new StringVal("<error>");
|
||||||
|
|
||||||
internal-op Files--Enable-Reassembly
|
internal-op Analyzer-Name
|
||||||
|
type VV
|
||||||
|
eval AnalyzerName(frame[z.v2])
|
||||||
|
|
||||||
|
internal-op Analyzer-Name
|
||||||
|
type VC
|
||||||
|
eval AnalyzerName(z.c)
|
||||||
|
|
||||||
|
macro FilesAddOrRemoveAnalyzer(file_id_slot, tag, args_slot, METHOD)
|
||||||
|
auto file_id = frame[z.file_id_slot].string_val;
|
||||||
|
using zeek::BifType::Record::Files::AnalyzerArgs;
|
||||||
|
auto rv = frame[z.args_slot].record_val->CoerceTo(AnalyzerArgs);
|
||||||
|
bool result = zeek::file_mgr->METHOD(
|
||||||
|
file_id->CheckString(),
|
||||||
|
zeek::file_mgr->GetComponentTag(tag.ToVal(z.t).get()),
|
||||||
|
std::move(rv));
|
||||||
|
|
||||||
|
macro FilesAddAnalyzer(file_id_slot, tag, args_slot)
|
||||||
|
FilesAddOrRemoveAnalyzer(file_id_slot, tag, args_slot, AddAnalyzer)
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
op1-read
|
||||||
|
type VVV
|
||||||
|
eval FilesAddAnalyzer(v1, frame[z.v2], v3)
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
op1-read
|
||||||
|
type ViV
|
||||||
|
eval FilesAddAnalyzer(v1, z.c, v2)
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
type VVVV
|
||||||
|
side-effects OP_FILES_ADD_ANALYZER_VVV OP_VVV
|
||||||
|
eval FilesAddAnalyzer(v2, frame[z.v3], v4)
|
||||||
|
frame[z.v1].int_val = result;
|
||||||
|
|
||||||
|
internal-op Files-Add-Analyzer
|
||||||
|
type VViV
|
||||||
|
side-effects OP_FILES_ADD_ANALYZER_ViV OP_VVC
|
||||||
|
eval FilesAddAnalyzer(v2, z.c, v3)
|
||||||
|
frame[z.v1].int_val = result;
|
||||||
|
|
||||||
|
macro FilesRemoveAnalyzer(file_id_slot, tag, args_slot)
|
||||||
|
FilesAddOrRemoveAnalyzer(file_id_slot, tag, args_slot, RemoveAnalyzer)
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
op1-read
|
||||||
|
type VVV
|
||||||
|
eval FilesRemoveAnalyzer(v1, frame[z.v2], v3)
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
op1-read
|
||||||
|
type ViV
|
||||||
|
eval FilesRemoveAnalyzer(v1, z.c, v2)
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
type VVVV
|
||||||
|
side-effects OP_FILES_REMOVE_ANALYZER_VVV OP_VVV
|
||||||
|
eval FilesRemoveAnalyzer(v2, frame[z.v3], v4)
|
||||||
|
frame[z.v1].int_val = result;
|
||||||
|
|
||||||
|
internal-op Files-Remove-Analyzer
|
||||||
|
type VViV
|
||||||
|
side-effects OP_FILES_REMOVE_ANALYZER_ViV OP_VVC
|
||||||
|
eval FilesRemoveAnalyzer(v2, z.c, v3)
|
||||||
|
frame[z.v1].int_val = result;
|
||||||
|
|
||||||
|
macro AnalyzerEnabled(tag)
|
||||||
|
auto atype = tag.ToVal(z.t);
|
||||||
|
auto c = zeek::file_mgr->Lookup(atype->AsEnumVal());
|
||||||
|
frame[z.v1].int_val = c && c->Enabled();
|
||||||
|
|
||||||
|
internal-op Analyzer-Enabled
|
||||||
|
type VV
|
||||||
|
eval AnalyzerEnabled(frame[z.v2])
|
||||||
|
|
||||||
|
internal-op Analyzer-Enabled
|
||||||
|
type VC
|
||||||
|
eval AnalyzerEnabled(z.c)
|
||||||
|
|
||||||
|
macro FileAnalyzerName(tag)
|
||||||
|
auto atype = tag.ToVal(z.t);
|
||||||
|
Unref(frame[z.v1].string_val);
|
||||||
|
frame[z.v1] = ZVal(file_mgr->GetComponentNameVal({NewRef{}, atype->AsEnumVal()}));
|
||||||
|
|
||||||
|
internal-op File-Analyzer-Name
|
||||||
|
type VV
|
||||||
|
eval FileAnalyzerName(frame[z.v2])
|
||||||
|
|
||||||
|
internal-op File-Analyzer-Name
|
||||||
|
type VC
|
||||||
|
eval FileAnalyzerName(z.c)
|
||||||
|
|
||||||
|
macro IsProtocolAnalyzer(tag)
|
||||||
|
auto atype = tag.ToVal(z.t);
|
||||||
|
frame[z.v1].int_val = analyzer_mgr->Lookup(atype->AsEnumVal()) != nullptr;
|
||||||
|
|
||||||
|
internal-op Is-Protocol-Analyzer
|
||||||
|
type VV
|
||||||
|
eval IsProtocolAnalyzer(frame[z.v2])
|
||||||
|
|
||||||
|
internal-op Is-Protocol-Analyzer
|
||||||
|
type VC
|
||||||
|
eval IsProtocolAnalyzer(z.c)
|
||||||
|
|
||||||
|
internal-op Clear-Table
|
||||||
|
op1-read
|
||||||
|
type V
|
||||||
|
eval frame[z.v1].table_val->RemoveAll();
|
||||||
|
|
||||||
|
internal-op Files-Enable-Reassembly
|
||||||
op1-read
|
op1-read
|
||||||
type V
|
type V
|
||||||
eval auto f = frame[z.v1].string_val->CheckString();
|
eval auto f = frame[z.v1].string_val->CheckString();
|
||||||
file_mgr->EnableReassembly(f);
|
file_mgr->EnableReassembly(f);
|
||||||
|
|
||||||
internal-op Files--Set-Reassembly-Buffer
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
op1-read
|
op1-read
|
||||||
type VV
|
type VV
|
||||||
eval auto f = frame[z.v1].string_val->CheckString();
|
eval auto f = frame[z.v1].string_val->CheckString();
|
||||||
file_mgr->SetReassemblyBuffer(f, frame[z.v2].uint_val);
|
file_mgr->SetReassemblyBuffer(f, frame[z.v2].uint_val);
|
||||||
|
|
||||||
internal-op Files--Set-Reassembly-Buffer
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
|
type VVV
|
||||||
|
side-effects OP_FILES_SET_REASSEMBLY_BUFFER_VV OP_VV
|
||||||
|
eval auto f = frame[z.v2].string_val->CheckString();
|
||||||
|
frame[z.v1].int_val = file_mgr->SetReassemblyBuffer(f, frame[z.v3].uint_val);
|
||||||
|
|
||||||
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
op1-read
|
op1-read
|
||||||
type VC
|
type VC
|
||||||
eval auto f = frame[z.v1].string_val->CheckString();
|
eval auto f = frame[z.v1].string_val->CheckString();
|
||||||
file_mgr->SetReassemblyBuffer(f, zeek_uint_t(z.v2));
|
file_mgr->SetReassemblyBuffer(f, zeek_uint_t(z.v2));
|
||||||
|
|
||||||
|
internal-op Files-Set-Reassembly-Buffer
|
||||||
|
type VVC
|
||||||
|
side-effects OP_FILES_SET_REASSEMBLY_BUFFER_VC OP_VC
|
||||||
|
eval auto f = frame[z.v2].string_val->CheckString();
|
||||||
|
frame[z.v1].int_val = file_mgr->SetReassemblyBuffer(f, zeek_uint_t(z.v2));
|
||||||
|
|
||||||
|
macro GetBytesThresh(cid, is_orig)
|
||||||
|
zeek::analyzer::Analyzer* a = analyzer::conn_size::GetConnsizeAnalyzer(cid);
|
||||||
|
auto res = 0U;
|
||||||
|
if ( a )
|
||||||
|
res = static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->GetByteAndPacketThreshold(true, is_orig);
|
||||||
|
frame[z.v1].uint_val = res;
|
||||||
|
|
||||||
|
internal-op Get-Bytes-Thresh
|
||||||
|
type VVV
|
||||||
|
eval GetBytesThresh(frame[z.v2].record_val, frame[z.v3].int_val)
|
||||||
|
|
||||||
|
internal-op Get-Bytes-Thresh
|
||||||
|
type VVi
|
||||||
|
eval GetBytesThresh(frame[z.v2].record_val, z.c.uint_val)
|
||||||
|
|
||||||
|
macro SetBytesThresh(cid, threshold, is_orig)
|
||||||
|
bool res = false;
|
||||||
|
zeek::analyzer::Analyzer* a = analyzer::conn_size::GetConnsizeAnalyzer(cid);
|
||||||
|
if ( a )
|
||||||
|
{
|
||||||
|
static_cast<analyzer::conn_size::ConnSize_Analyzer*>(a)->SetByteAndPacketThreshold(threshold, true, is_orig);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
op1-read
|
||||||
|
type VVV
|
||||||
|
eval SetBytesThresh(frame[z.v1].record_val, frame[z.v2].uint_val, frame[z.v3].int_val)
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
op1-read
|
||||||
|
type VVi
|
||||||
|
eval SetBytesThresh(frame[z.v1].record_val, frame[z.v2].uint_val, z.c.int_val)
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
op1-read
|
||||||
|
type ViV
|
||||||
|
eval SetBytesThresh(frame[z.v1].record_val, z.c.uint_val, frame[z.v2].int_val)
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
op1-read
|
||||||
|
type Vii
|
||||||
|
eval SetBytesThresh(frame[z.v1].record_val, z.c.uint_val, z.v2)
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
type VVVV
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VVV OP_VVV
|
||||||
|
eval SetBytesThresh(frame[z.v2].record_val, frame[z.v3].uint_val, frame[z.v4].int_val)
|
||||||
|
frame[z.v1].int_val = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
type VVVi
|
||||||
|
side-effects OP_SET_BYTES_THRESH_VVi OP_VVV_I3
|
||||||
|
eval SetBytesThresh(frame[z.v2].record_val, frame[z.v3].uint_val, z.c.int_val)
|
||||||
|
frame[z.v1].int_val = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
type VViV
|
||||||
|
side-effects OP_SET_BYTES_THRESH_ViV OP_VVV_I3
|
||||||
|
eval SetBytesThresh(frame[z.v2].record_val, z.c.uint_val, frame[z.v3].int_val)
|
||||||
|
frame[z.v1].int_val = res;
|
||||||
|
|
||||||
|
internal-op Set-Bytes-Thresh
|
||||||
|
type VVii
|
||||||
|
side-effects OP_SET_BYTES_THRESH_Vii OP_VVC_I2
|
||||||
|
eval SetBytesThresh(frame[z.v2].record_val, z.c.uint_val, zeek_uint_t(z.v3))
|
||||||
|
frame[z.v1].int_val = res;
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# Instructions for known script functions
|
||||||
|
########################################
|
||||||
|
|
||||||
|
internal-op Func-Id-String
|
||||||
|
type VV
|
||||||
|
eval auto id_rec = frame[z.v2].record_val;
|
||||||
|
auto orig_h = id_rec->RawField(0).addr_val->AsAddr().AsString();
|
||||||
|
auto resp_h = id_rec->RawField(2).addr_val->AsAddr().AsString();
|
||||||
|
auto orig_p = static_cast<uint32_t>(id_rec->RawField(1).uint_val) & ~PORT_SPACE_MASK;
|
||||||
|
auto resp_p = static_cast<uint32_t>(id_rec->RawField(3).uint_val) & ~PORT_SPACE_MASK;
|
||||||
|
/* Maximum address size is for IPv6 with no compression. Each
|
||||||
|
* 8 16-bit hex elements plus 7 colons between them plus the two []'s
|
||||||
|
* = 8*4 + 7 + 2 = 41 characters.
|
||||||
|
*
|
||||||
|
* Maximum port size is 5.
|
||||||
|
*
|
||||||
|
* Two of these = 2*41 + 2*5 = 92.
|
||||||
|
* Other delimiters: two ':', one ' < ' for 5 more.
|
||||||
|
*
|
||||||
|
* TOTAL: 97 characters.
|
||||||
|
*
|
||||||
|
* We use considerably more for safety.
|
||||||
|
*/
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof buf, "%s:%u > %s:%u", orig_h.c_str(), orig_p, resp_h.c_str(), resp_p);
|
||||||
|
Unref(frame[z.v1].string_val);
|
||||||
|
frame[z.v1].string_val = new StringVal(buf);
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# Instructions for script-level idioms
|
||||||
|
########################################
|
||||||
|
|
||||||
|
internal-op MinU
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].uint_val = std::min(frame[z.v2].uint_val, z.c.uint_val);
|
||||||
|
|
||||||
|
internal-op MinI
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].int_val = std::min(frame[z.v2].int_val, z.c.int_val);
|
||||||
|
|
||||||
|
internal-op MinD
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].double_val = std::min(frame[z.v2].double_val, z.c.double_val);
|
||||||
|
|
||||||
|
internal-op MinU
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].uint_val = std::min(frame[z.v2].uint_val, frame[z.v3].uint_val);
|
||||||
|
|
||||||
|
internal-op MinI
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].int_val = std::min(frame[z.v2].int_val, frame[z.v3].int_val);
|
||||||
|
|
||||||
|
internal-op MinD
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].double_val = std::min(frame[z.v2].double_val, frame[z.v3].double_val);
|
||||||
|
|
||||||
|
internal-op MaxU
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].uint_val = std::max(frame[z.v2].uint_val, z.c.uint_val);
|
||||||
|
|
||||||
|
internal-op MaxI
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].int_val = std::max(frame[z.v2].int_val, z.c.int_val);
|
||||||
|
|
||||||
|
internal-op MaxD
|
||||||
|
type VVC
|
||||||
|
eval frame[z.v1].double_val = std::max(frame[z.v2].double_val, z.c.double_val);
|
||||||
|
|
||||||
|
internal-op MaxU
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].uint_val = std::max(frame[z.v2].uint_val, frame[z.v3].uint_val);
|
||||||
|
|
||||||
|
internal-op MaxI
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].int_val = std::max(frame[z.v2].int_val, frame[z.v3].int_val);
|
||||||
|
|
||||||
|
internal-op MaxD
|
||||||
|
type VVV
|
||||||
|
eval frame[z.v1].double_val = std::max(frame[z.v2].double_val, frame[z.v3].double_val);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "zeek/IPAddr.h"
|
#include "zeek/IPAddr.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
#include "zeek/ZeekString.h"
|
#include "zeek/ZeekString.h"
|
||||||
|
#include "zeek/script_opt/ZAM/BuiltIn.h"
|
||||||
#include "zeek/script_opt/ZAM/Compile.h"
|
#include "zeek/script_opt/ZAM/Compile.h"
|
||||||
|
|
||||||
namespace zeek::detail {
|
namespace zeek::detail {
|
||||||
|
@ -179,6 +180,36 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
||||||
case OP_HAS_FIELD_COND_VVV: z->op = OP_NOT_HAS_FIELD_COND_VVV; break;
|
case OP_HAS_FIELD_COND_VVV: z->op = OP_NOT_HAS_FIELD_COND_VVV; break;
|
||||||
case OP_NOT_HAS_FIELD_COND_VVV: z->op = OP_HAS_FIELD_COND_VVV; break;
|
case OP_NOT_HAS_FIELD_COND_VVV: z->op = OP_HAS_FIELD_COND_VVV; break;
|
||||||
|
|
||||||
|
case OP_CONN_EXISTS_COND_VV: z->op = OP_NOT_CONN_EXISTS_COND_VV; break;
|
||||||
|
case OP_NOT_CONN_EXISTS_COND_VV: z->op = OP_CONN_EXISTS_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_IS_ICMP_PORT_COND_VV: z->op = OP_NOT_IS_ICMP_PORT_COND_VV; break;
|
||||||
|
case OP_NOT_IS_ICMP_PORT_COND_VV: z->op = OP_IS_ICMP_PORT_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_IS_TCP_PORT_COND_VV: z->op = OP_NOT_IS_TCP_PORT_COND_VV; break;
|
||||||
|
case OP_NOT_IS_TCP_PORT_COND_VV: z->op = OP_IS_TCP_PORT_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_IS_UDP_PORT_COND_VV: z->op = OP_NOT_IS_UDP_PORT_COND_VV; break;
|
||||||
|
case OP_NOT_IS_UDP_PORT_COND_VV: z->op = OP_IS_UDP_PORT_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_IS_V4_ADDR_COND_VV: z->op = OP_NOT_IS_V4_ADDR_COND_VV; break;
|
||||||
|
case OP_NOT_IS_V4_ADDR_COND_VV: z->op = OP_IS_V4_ADDR_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_IS_V6_ADDR_COND_VV: z->op = OP_NOT_IS_V6_ADDR_COND_VV; break;
|
||||||
|
case OP_NOT_IS_V6_ADDR_COND_VV: z->op = OP_IS_V6_ADDR_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_READING_LIVE_TRAFFIC_COND_V: z->op = OP_NOT_READING_LIVE_TRAFFIC_COND_V; break;
|
||||||
|
case OP_NOT_READING_LIVE_TRAFFIC_COND_V: z->op = OP_READING_LIVE_TRAFFIC_COND_V; break;
|
||||||
|
|
||||||
|
case OP_READING_TRACES_COND_V: z->op = OP_NOT_READING_TRACES_COND_V; break;
|
||||||
|
case OP_NOT_READING_TRACES_COND_V: z->op = OP_READING_TRACES_COND_V; break;
|
||||||
|
|
||||||
|
case OP_TABLE_HAS_ELEMENTS_COND_VV: z->op = OP_NOT_TABLE_HAS_ELEMENTS_COND_VV; break;
|
||||||
|
case OP_NOT_TABLE_HAS_ELEMENTS_COND_VV: z->op = OP_TABLE_HAS_ELEMENTS_COND_VV; break;
|
||||||
|
|
||||||
|
case OP_VECTOR_HAS_ELEMENTS_COND_VV: z->op = OP_NOT_VECTOR_HAS_ELEMENTS_COND_VV; break;
|
||||||
|
case OP_NOT_VECTOR_HAS_ELEMENTS_COND_VV: z->op = OP_VECTOR_HAS_ELEMENTS_COND_VV; break;
|
||||||
|
|
||||||
case OP_VAL_IS_IN_TABLE_COND_VVV: z->op = OP_VAL_IS_NOT_IN_TABLE_COND_VVV; break;
|
case OP_VAL_IS_IN_TABLE_COND_VVV: z->op = OP_VAL_IS_NOT_IN_TABLE_COND_VVV; break;
|
||||||
case OP_VAL_IS_NOT_IN_TABLE_COND_VVV: z->op = OP_VAL_IS_IN_TABLE_COND_VVV; break;
|
case OP_VAL_IS_NOT_IN_TABLE_COND_VVV: z->op = OP_VAL_IS_IN_TABLE_COND_VVV; break;
|
||||||
|
|
||||||
|
@ -205,10 +236,6 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v) {
|
||||||
auto op1 = e->GetOp1();
|
auto op1 = e->GetOp1();
|
||||||
auto op2 = e->GetOp2();
|
auto op2 = e->GetOp2();
|
||||||
|
|
||||||
NameExpr* n1 = nullptr;
|
|
||||||
NameExpr* n2 = nullptr;
|
|
||||||
ConstExpr* c = nullptr;
|
|
||||||
|
|
||||||
if ( e->Tag() == EXPR_HAS_FIELD ) {
|
if ( e->Tag() == EXPR_HAS_FIELD ) {
|
||||||
auto hf = e->AsHasFieldExpr();
|
auto hf = e->AsHasFieldExpr();
|
||||||
auto z = GenInst(OP_HAS_FIELD_COND_VVV, op1->AsNameExpr(), hf->Field());
|
auto z = GenInst(OP_HAS_FIELD_COND_VVV, op1->AsNameExpr(), hf->Field());
|
||||||
|
@ -218,7 +245,6 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( e->Tag() == EXPR_IN ) {
|
if ( e->Tag() == EXPR_IN ) {
|
||||||
auto op1 = e->GetOp1();
|
|
||||||
auto op2 = e->GetOp2()->AsNameExpr();
|
auto op2 = e->GetOp2()->AsNameExpr();
|
||||||
|
|
||||||
// First, deal with the easy cases: it's a single index.
|
// First, deal with the easy cases: it's a single index.
|
||||||
|
@ -293,6 +319,31 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v) {
|
||||||
return AddInst(z);
|
return AddInst(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( e->Tag() == EXPR_CALL ) {
|
||||||
|
auto c = static_cast<const CallExpr*>(e);
|
||||||
|
if ( IsZAM_BuiltInCond(this, c, branch_v) )
|
||||||
|
return LastInst();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( e->Tag() == EXPR_SCRIPT_OPT_BUILTIN ) {
|
||||||
|
auto bi = static_cast<const ScriptOptBuiltinExpr*>(e);
|
||||||
|
ASSERT(bi->Tag() == ScriptOptBuiltinExpr::HAS_ELEMENTS);
|
||||||
|
auto aggr = bi->GetOp1()->AsNameExpr();
|
||||||
|
|
||||||
|
ZOp op;
|
||||||
|
if ( aggr->GetType()->Tag() == TYPE_TABLE )
|
||||||
|
op = OP_TABLE_HAS_ELEMENTS_COND_VV;
|
||||||
|
else
|
||||||
|
op = OP_VECTOR_HAS_ELEMENTS_COND_VV;
|
||||||
|
|
||||||
|
branch_v = 2;
|
||||||
|
return AddInst(GenInst(op, aggr, +0));
|
||||||
|
}
|
||||||
|
|
||||||
|
NameExpr* n1 = nullptr;
|
||||||
|
NameExpr* n2 = nullptr;
|
||||||
|
ConstExpr* c = nullptr;
|
||||||
|
|
||||||
if ( op1->Tag() == EXPR_NAME ) {
|
if ( op1->Tag() == EXPR_NAME ) {
|
||||||
n1 = op1->AsNameExpr();
|
n1 = op1->AsNameExpr();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "zeek/Trigger.h"
|
#include "zeek/Trigger.h"
|
||||||
#include "zeek/script_opt/ScriptOpt.h"
|
#include "zeek/script_opt/ScriptOpt.h"
|
||||||
#include "zeek/script_opt/ZAM/Compile.h"
|
#include "zeek/script_opt/ZAM/Compile.h"
|
||||||
|
#include "zeek/session/Manager.h"
|
||||||
|
|
||||||
// Needed for managing the corresponding values.
|
// Needed for managing the corresponding values.
|
||||||
#include "zeek/File.h"
|
#include "zeek/File.h"
|
||||||
|
@ -20,10 +21,16 @@
|
||||||
|
|
||||||
// Just needed for BiFs.
|
// Just needed for BiFs.
|
||||||
#include "zeek/analyzer/Manager.h"
|
#include "zeek/analyzer/Manager.h"
|
||||||
|
#include "zeek/analyzer/protocol/conn-size/ConnSize.h"
|
||||||
#include "zeek/broker/Manager.h"
|
#include "zeek/broker/Manager.h"
|
||||||
#include "zeek/file_analysis/Manager.h"
|
#include "zeek/file_analysis/Manager.h"
|
||||||
|
#include "zeek/file_analysis/file_analysis.bif.h"
|
||||||
#include "zeek/logging/Manager.h"
|
#include "zeek/logging/Manager.h"
|
||||||
#include "zeek/packet_analysis/Manager.h"
|
#include "zeek/packet_analysis/Manager.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/gtpv1/GTPv1.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/teredo/Teredo.h"
|
||||||
|
|
||||||
|
#include "zeek.bif.func_h"
|
||||||
|
|
||||||
// For reading_live and reading_traces
|
// For reading_live and reading_traces
|
||||||
#include "zeek/RunState.h"
|
#include "zeek/RunState.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue