mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
allow sets to be read from files, convenience function for reading a file once,
bug in destructor that could lead to a segfault.
This commit is contained in:
parent
2a6387129c
commit
a68e6b9fa4
3 changed files with 75 additions and 15 deletions
|
@ -4,6 +4,8 @@
|
||||||
module Input;
|
module Input;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
redef enum Input::ID += { TABLE_READ };
|
||||||
|
|
||||||
## The default input reader used. Defaults to `READER_ASCII`.
|
## The default input reader used. Defaults to `READER_ASCII`.
|
||||||
const default_reader = READER_ASCII &redef;
|
const default_reader = READER_ASCII &redef;
|
||||||
|
|
||||||
|
@ -27,7 +29,8 @@ export {
|
||||||
## Record that defines the values used as the index of the table
|
## Record that defines the values used as the index of the table
|
||||||
idx: any;
|
idx: any;
|
||||||
## Record that defines the values used as the values of the table
|
## Record that defines the values used as the values of the table
|
||||||
val: any;
|
## If val is undefined, destination has to be a set.
|
||||||
|
val: any &optional;
|
||||||
## Defines if the value of the table is a record (default), or a single value.
|
## Defines if the value of the table is a record (default), or a single value.
|
||||||
## Val can only contain one element when this is set to false.
|
## Val can only contain one element when this is set to false.
|
||||||
want_record: bool &default=T;
|
want_record: bool &default=T;
|
||||||
|
@ -103,6 +106,14 @@ export {
|
||||||
global remove_eventfilter: function(id: Input::ID, name: string) : bool;
|
global remove_eventfilter: function(id: Input::ID, name: string) : bool;
|
||||||
#global get_filter: function(id: ID, name: string) : Filter;
|
#global get_filter: function(id: ID, name: string) : Filter;
|
||||||
|
|
||||||
|
## Convenience function for reading a specific input source exactly once using
|
||||||
|
## exactly one tablefilter
|
||||||
|
##
|
||||||
|
## id: `Input::ID` enum value identifying the stream
|
||||||
|
## description: `StreamDescription` record describing the source.
|
||||||
|
## filter: the `TableFilter` record describing the filter.
|
||||||
|
global read_table: function(description: Input::StreamDescription, filter: Input::TableFilter) : bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@load base/input.bif
|
@load base/input.bif
|
||||||
|
@ -151,6 +162,27 @@ function remove_eventfilter(id: Input::ID, name: string) : bool
|
||||||
return __remove_eventfilter(id, name);
|
return __remove_eventfilter(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function read_table(description: Input::StreamDescription, filter: Input::TableFilter) : bool {
|
||||||
|
local ok: bool = T;
|
||||||
|
# since we create and delete it ourselves this should be ok... at least for singlethreaded operation
|
||||||
|
local id: Input::ID = Input::TABLE_READ;
|
||||||
|
|
||||||
|
ok = create_stream(id, description);
|
||||||
|
if ( ok ) {
|
||||||
|
ok = add_tablefilter(id, filter);
|
||||||
|
}
|
||||||
|
if ( ok ) {
|
||||||
|
ok = force_update(id);
|
||||||
|
}
|
||||||
|
if ( ok ) {
|
||||||
|
ok = remove_stream(id);
|
||||||
|
} else {
|
||||||
|
remove_stream(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
#function get_filter(id: ID, name: string) : Filter
|
#function get_filter(id: ID, name: string) : Filter
|
||||||
# {
|
# {
|
||||||
# if ( [id, name] in filters )
|
# if ( [id, name] in filters )
|
||||||
|
|
|
@ -86,6 +86,7 @@ InputMgr::Filter::~Filter() {
|
||||||
InputMgr::TableFilter::~TableFilter() {
|
InputMgr::TableFilter::~TableFilter() {
|
||||||
Unref(tab);
|
Unref(tab);
|
||||||
Unref(itype);
|
Unref(itype);
|
||||||
|
if ( rtype ) // can be 0 for sets
|
||||||
Unref(rtype);
|
Unref(rtype);
|
||||||
|
|
||||||
delete currDict;
|
delete currDict;
|
||||||
|
@ -110,6 +111,7 @@ InputMgr::ReaderInfo::~ReaderInfo() {
|
||||||
|
|
||||||
while ( it != filters.end() ) {
|
while ( it != filters.end() ) {
|
||||||
delete (*it).second;
|
delete (*it).second;
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unref(type);
|
Unref(type);
|
||||||
|
@ -354,7 +356,10 @@ bool InputMgr::AddTableFilter(EnumVal *id, RecordVal* fval) {
|
||||||
Val* pred = fval->Lookup(rtype->FieldOffset("pred"));
|
Val* pred = fval->Lookup(rtype->FieldOffset("pred"));
|
||||||
|
|
||||||
RecordType *idx = fval->Lookup(rtype->FieldOffset("idx"))->AsType()->AsTypeType()->Type()->AsRecordType();
|
RecordType *idx = fval->Lookup(rtype->FieldOffset("idx"))->AsType()->AsTypeType()->Type()->AsRecordType();
|
||||||
RecordType *val = fval->Lookup(rtype->FieldOffset("val"))->AsType()->AsTypeType()->Type()->AsRecordType();
|
RecordType *val = 0;
|
||||||
|
if ( fval->Lookup(rtype->FieldOffset("val")) != 0 ) {
|
||||||
|
val = fval->Lookup(rtype->FieldOffset("val"))->AsType()->AsTypeType()->Type()->AsRecordType();
|
||||||
|
}
|
||||||
TableVal *dst = fval->Lookup(rtype->FieldOffset("destination"))->AsTableVal();
|
TableVal *dst = fval->Lookup(rtype->FieldOffset("destination"))->AsTableVal();
|
||||||
|
|
||||||
Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record"));
|
Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record"));
|
||||||
|
@ -408,9 +413,14 @@ bool InputMgr::AddTableFilter(EnumVal *id, RecordVal* fval) {
|
||||||
|
|
||||||
int idxfields = fieldsV.size();
|
int idxfields = fieldsV.size();
|
||||||
|
|
||||||
|
if ( val ) // if we are not a set
|
||||||
status = status || !UnrollRecordType(&fieldsV, val, "");
|
status = status || !UnrollRecordType(&fieldsV, val, "");
|
||||||
|
|
||||||
int valfields = fieldsV.size() - idxfields;
|
int valfields = fieldsV.size() - idxfields;
|
||||||
|
|
||||||
|
if ( !val )
|
||||||
|
assert(valfields == 0);
|
||||||
|
|
||||||
if ( status ) {
|
if ( status ) {
|
||||||
reporter->Error("Problem unrolling");
|
reporter->Error("Problem unrolling");
|
||||||
return false;
|
return false;
|
||||||
|
@ -429,7 +439,7 @@ bool InputMgr::AddTableFilter(EnumVal *id, RecordVal* fval) {
|
||||||
filter->num_idx_fields = idxfields;
|
filter->num_idx_fields = idxfields;
|
||||||
filter->num_val_fields = valfields;
|
filter->num_val_fields = valfields;
|
||||||
filter->tab = dst->Ref()->AsTableVal();
|
filter->tab = dst->Ref()->AsTableVal();
|
||||||
filter->rtype = val->Ref()->AsRecordType();
|
filter->rtype = val ? val->Ref()->AsRecordType() : 0;
|
||||||
filter->itype = idx->Ref()->AsRecordType();
|
filter->itype = idx->Ref()->AsRecordType();
|
||||||
filter->event = event ? event_registry->Lookup(event->GetID()->Name()) : 0;
|
filter->event = event ? event_registry->Lookup(event->GetID()->Name()) : 0;
|
||||||
filter->currDict = new PDict(InputHash);
|
filter->currDict = new PDict(InputHash);
|
||||||
|
@ -681,7 +691,10 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
HashKey* idxhash = HashLogVals(filter->num_idx_fields, vals);
|
HashKey* idxhash = HashLogVals(filter->num_idx_fields, vals);
|
||||||
//reporter->Error("Result: %d", (uint64_t) idxhash->Hash());
|
//reporter->Error("Result: %d", (uint64_t) idxhash->Hash());
|
||||||
//reporter->Error("Hashing %d val fields", i->num_val_fields);
|
//reporter->Error("Hashing %d val fields", i->num_val_fields);
|
||||||
HashKey* valhash = HashLogVals(filter->num_val_fields, vals+filter->num_idx_fields);
|
HashKey* valhash = 0;
|
||||||
|
if ( filter->num_val_fields > 0 )
|
||||||
|
HashLogVals(filter->num_val_fields, vals+filter->num_idx_fields);
|
||||||
|
|
||||||
//reporter->Error("Result: %d", (uint64_t) valhash->Hash());
|
//reporter->Error("Result: %d", (uint64_t) valhash->Hash());
|
||||||
|
|
||||||
//reporter->Error("received entry with idxhash %d and valhash %d", (uint64_t) idxhash->Hash(), (uint64_t) valhash->Hash());
|
//reporter->Error("received entry with idxhash %d and valhash %d", (uint64_t) idxhash->Hash(), (uint64_t) valhash->Hash());
|
||||||
|
@ -689,12 +702,13 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
InputHash *h = filter->lastDict->Lookup(idxhash);
|
InputHash *h = filter->lastDict->Lookup(idxhash);
|
||||||
if ( h != 0 ) {
|
if ( h != 0 ) {
|
||||||
// seen before
|
// seen before
|
||||||
if ( h->valhash->Hash() == valhash->Hash() ) {
|
if ( filter->num_val_fields == 0 || h->valhash->Hash() == valhash->Hash() ) {
|
||||||
// ok, double.
|
// ok, exact duplicate
|
||||||
filter->lastDict->Remove(idxhash);
|
filter->lastDict->Remove(idxhash);
|
||||||
filter->currDict->Insert(idxhash, h);
|
filter->currDict->Insert(idxhash, h);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
assert( filter->num_val_fields > 0 );
|
||||||
// updated
|
// updated
|
||||||
filter->lastDict->Remove(idxhash);
|
filter->lastDict->Remove(idxhash);
|
||||||
delete(h);
|
delete(h);
|
||||||
|
@ -708,7 +722,9 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
Val* valval;
|
Val* valval;
|
||||||
|
|
||||||
int position = filter->num_idx_fields;
|
int position = filter->num_idx_fields;
|
||||||
if ( filter->num_val_fields == 1 && !filter->want_record ) {
|
if ( filter->num_val_fields == 0 ) {
|
||||||
|
valval = 0;
|
||||||
|
} else if ( filter->num_val_fields == 1 && !filter->want_record ) {
|
||||||
valval = LogValToVal(vals[position], filter->rtype->FieldType(0));
|
valval = LogValToVal(vals[position], filter->rtype->FieldType(0));
|
||||||
} else {
|
} else {
|
||||||
RecordVal * r = new RecordVal(filter->rtype);
|
RecordVal * r = new RecordVal(filter->rtype);
|
||||||
|
@ -732,6 +748,7 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
|
|
||||||
Val* oldval = 0;
|
Val* oldval = 0;
|
||||||
if ( updated == true ) {
|
if ( updated == true ) {
|
||||||
|
assert(filter->num_val_fields > 0);
|
||||||
// in that case, we need the old value to send the event (if we send an event).
|
// in that case, we need the old value to send the event (if we send an event).
|
||||||
oldval = filter->tab->Lookup(idxval);
|
oldval = filter->tab->Lookup(idxval);
|
||||||
}
|
}
|
||||||
|
@ -749,10 +766,12 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
val_list vl(3);
|
val_list vl( 2 + (filter->num_val_fields > 0) ); // 2 if we don't have values, 3 otherwise.
|
||||||
vl.append(ev);
|
vl.append(ev);
|
||||||
vl.append(idxval);
|
vl.append(idxval);
|
||||||
|
if ( filter->num_val_fields > 0 )
|
||||||
vl.append(valval);
|
vl.append(valval);
|
||||||
|
|
||||||
Val* v = filter->pred->Call(&vl);
|
Val* v = filter->pred->Call(&vl);
|
||||||
bool result = v->AsBool();
|
bool result = v->AsBool();
|
||||||
Unref(v);
|
Unref(v);
|
||||||
|
@ -794,6 +813,7 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
Ref(idxval);
|
Ref(idxval);
|
||||||
|
|
||||||
if ( updated ) { // in case of update send back the old value.
|
if ( updated ) { // in case of update send back the old value.
|
||||||
|
assert ( filter->num_val_fields > 0 );
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
||||||
assert ( oldval != 0 );
|
assert ( oldval != 0 );
|
||||||
Ref(oldval);
|
Ref(oldval);
|
||||||
|
@ -801,10 +821,14 @@ void InputMgr::SendEntryTable(const InputReader* reader, int id, const LogVal* c
|
||||||
} else {
|
} else {
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
||||||
Ref(valval);
|
Ref(valval);
|
||||||
|
if ( filter->num_val_fields == 0 ) {
|
||||||
|
SendEvent(filter->event, 3, ev, idxval);
|
||||||
|
} else {
|
||||||
SendEvent(filter->event, 3, ev, idxval, valval);
|
SendEvent(filter->event, 3, ev, idxval, valval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InputMgr::EndCurrentSend(const InputReader* reader, int id) {
|
void InputMgr::EndCurrentSend(const InputReader* reader, int id) {
|
||||||
|
@ -963,7 +987,9 @@ void InputMgr::PutTable(const InputReader* reader, int id, const LogVal* const *
|
||||||
Val* valval;
|
Val* valval;
|
||||||
|
|
||||||
int position = filter->num_idx_fields;
|
int position = filter->num_idx_fields;
|
||||||
if ( filter->num_val_fields == 1 && !filter->want_record ) {
|
if ( filter->num_val_fields == 0 ) {
|
||||||
|
valval = 0;
|
||||||
|
} else if ( filter->num_val_fields == 1 && !filter->want_record ) {
|
||||||
valval = LogValToVal(vals[filter->num_idx_fields], filter->rtype->FieldType(filter->num_idx_fields));
|
valval = LogValToVal(vals[filter->num_idx_fields], filter->rtype->FieldType(filter->num_idx_fields));
|
||||||
} else {
|
} else {
|
||||||
RecordVal * r = new RecordVal(filter->rtype);
|
RecordVal * r = new RecordVal(filter->rtype);
|
||||||
|
|
|
@ -49,4 +49,6 @@ event bro_init()
|
||||||
Input::add_tablefilter(A::INPUT, [$name="ssh", $idx=Idx, $val=Val, $destination=servers]);
|
Input::add_tablefilter(A::INPUT, [$name="ssh", $idx=Idx, $val=Val, $destination=servers]);
|
||||||
Input::force_update(A::INPUT);
|
Input::force_update(A::INPUT);
|
||||||
print servers;
|
print servers;
|
||||||
|
Input::remove_tablefilter(A::INPUT, "ssh");
|
||||||
|
Input::remove_stream(A::INPUT);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue