diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d8bf63505b..2201c69995 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -692,6 +692,31 @@ bool Manager::ForceUpdate(const string &name) return true; // update is async :( } + +Val* Manager::RecordValToIndexVal(RecordVal *r) { + Val* idxval; + + RecordType *type = r->Type()->AsRecordType(); + + int num_fields = type->NumFields(); + + if ( num_fields == 1 && type->FieldDecl(0)->type->Tag() != TYPE_RECORD ) { + idxval = r->Lookup(0); + } else { + ListVal *l = new ListVal(TYPE_ANY); + for ( int j = 0 ; j < num_fields; j++ ) { + Val* rval = r->Lookup(j); + assert(rval != 0); + l->Append(r->LookupWithDefault(j)); + } + idxval = l; + } + + + return idxval; +} + + Val* Manager::ValueToIndexVal(int num_fields, const RecordType *type, const Value* const *vals) { Val* idxval; int position = 0; @@ -788,8 +813,8 @@ int Manager::SendEntryTable(Filter* i, const Value* const *vals) { } - Val* idxval = ValueToIndexVal(filter->num_idx_fields, filter->itype, vals); Val* valval; + RecordVal* predidx = 0; int position = filter->num_idx_fields; if ( filter->num_val_fields == 0 ) { @@ -806,8 +831,10 @@ int Manager::SendEntryTable(Filter* i, const Value* const *vals) { if ( filter->pred ) { EnumVal* ev; //Ref(idxval); - int startpos = 0; - Val* predidx = ValueToRecordVal(vals, filter->itype, &startpos); + int startpos = 0; + //Val* predidx = ListValToRecordVal(idxval->AsListVal(), filter->itype, &startpos); + predidx = ValueToRecordVal(vals, filter->itype, &startpos); + //ValueToRecordVal(vals, filter->itype, &startpos); Ref(valval); if ( updated ) { @@ -818,13 +845,14 @@ int Manager::SendEntryTable(Filter* i, const Value* const *vals) { bool result; if ( filter->num_val_fields > 0 ) { // we have values - result = CallPred(filter->pred, 3, ev, predidx, valval); + result = CallPred(filter->pred, 3, ev, predidx->Ref(), valval); } else { // no values - result = CallPred(filter->pred, 2, ev, predidx); + result = CallPred(filter->pred, 2, ev, predidx->Ref()); } if ( result == false ) { + Unref(predidx); if ( !updated ) { // throw away. Hence - we quit. And remove the entry from the current dictionary... delete(filter->currDict->RemoveEntry(idxhash)); @@ -839,6 +867,13 @@ int Manager::SendEntryTable(Filter* i, const Value* const *vals) { } + Val* idxval; + if ( predidx != 0 ) { + idxval = RecordValToIndexVal(predidx); + Unref(predidx); + } else { + idxval = ValueToIndexVal(filter->num_idx_fields, filter->itype, vals); + } Val* oldval = 0; if ( updated == true ) { assert(filter->num_val_fields > 0); diff --git a/src/input/Manager.h b/src/input/Manager.h index 71169c4bc2..c6dd40bd95 100644 --- a/src/input/Manager.h +++ b/src/input/Manager.h @@ -158,6 +158,7 @@ private: // Converts a threading::value to a record type. mostly used by ValueToVal RecordVal* ValueToRecordVal(const threading::Value* const *vals, RecordType *request_type, int* position); + Val* RecordValToIndexVal(RecordVal *r); // Converts a Bro ListVal to a RecordVal given the record type RecordVal* ListValToRecordVal(ListVal* list, RecordType *request_type, int* position); diff --git a/testing/btest/Baseline/scripts.base.frameworks.input.predicatemodify/out b/testing/btest/Baseline/scripts.base.frameworks.input.predicatemodify/out new file mode 100644 index 0000000000..c648e63710 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.input.predicatemodify/out @@ -0,0 +1,4 @@ +{ +[2, idxmodified] = [b=T, s=test2], +[1, idx1] = [b=T, s=testmodified] +} diff --git a/testing/btest/scripts/base/frameworks/input/predicatemodify.bro b/testing/btest/scripts/base/frameworks/input/predicatemodify.bro new file mode 100644 index 0000000000..c3198d8483 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/input/predicatemodify.bro @@ -0,0 +1,50 @@ +# +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +@TEST-START-FILE input.log +#separator \x09 +#path ssh +#fields i b s ss +#types int bool string string +1 T test1 idx1 +2 T test2 idx2 +@TEST-END-FILE + +redef InputAscii::empty_field = "EMPTY"; + +module A; + +type Idx: record { + i: int; + ss: string; +}; + +type Val: record { + b: bool; + s: string; +}; + +global servers: table[int, string] of Val = table(); + +event bro_init() +{ + # first read in the old stuff into the table... + Input::add_table([$source="input.log", $name="input", $idx=Idx, $val=Val, $destination=servers, + $pred(typ: Input::Event, left: Idx, right: Val) = { + if ( left$i == 1 ) { + right$s = "testmodified"; + } + + if ( left$i == 2 ) { + left$ss = "idxmodified"; + } + return T; + } + ]); + Input::remove("input"); +} + +event Input::update_finished(name: string, source: string) { + print servers; +}