Several fixes for input manager error handling.

- First:
Due to architectural constraints, it is very hard for the
input framework to handle optional records. For an optional record,
either the whole record has to be missing, or all non-optional elements
of the record have to be defined. This information is not available
to input readers after the records have been unrolled into the threading
types.

Behavior so far was to treat optional records like they are non-optional,
without warning. The patch changes this behavior to emit an error on stream-
creation (during type-checking) and refusing to open the file. I think this
is a better idea - the behavior so far was undocumented and unintuitive.

- Second:
For table and event streams, reader backend creation was done very early,
before actually checking if all arguments are valid. Initialization is moved
after the checks now - this makes a number of delete statements unnecessary.
Also - I suspect threads of failed input reader instances were not deleted
until shutdown

- Third:
Add a couple more consistency checks, e.g. checking if the destination value
of a table has the same type as we need. We did not check everything in all
instances, instead we just assigned the things without caring (which works,
but is not really desirable).

This change also exposed a few bugs in other testcases where table definitions
were wrong (did not respect $want_record)

- Fourth:
Improve error messages and write testcases for all error messages (I think).
This commit is contained in:
Bernhard Amann 2013-12-05 15:04:28 -08:00
parent 574018f478
commit 3c59aa9459
8 changed files with 320 additions and 79 deletions

View file

@ -0,0 +1,161 @@
# Test different kinds of errors of the input framework
#
# @TEST-EXEC: bro -b %INPUT
# @TEST-EXEC: btest-diff .stderr
# @TEST-EXEC: btest-diff out
@TEST-START-FILE input.log
#separator \x09
#path ssh
#fields b i e c p sn a d t iv s sc ss se vc ve ns
#types bool int enum count port subnet addr double time interval string table table table vector vector string
T -42 SSH::LOG 21 123 10.0.0.0/24 1.2.3.4 3.14 1315801931.273616 100.000000 hurz 2,4,1,3 CC,AA,BB EMPTY 10,20,30 EMPTY 4242
@TEST-END-FILE
redef Input::accept_unsupported_types = T;
redef exit_only_after_terminate = T;
module Test;
global outfile: file;
type Idx: record {
c: count;
};
type Idx2: record {
c: count;
i: int;
};
type FileVal: record {
i: int;
s: file;
};
type Val: record {
i: int;
s: string;
a: addr;
};
type OptionalRecordVal: record {
i: int;
r: FileVal &optional;
};
type OptionalFileVal: record {
i: int;
s: file &optional;
};
global file_table: table[count] of FileVal = table();
global optional_file_table: table[count] of OptionalFileVal = table();
global record_table: table[count] of OptionalRecordVal = table();
global string_table: table[string] of OptionalRecordVal = table();
global val_table: table[count] of Val = table();
global val_table2: table[count, int] of Val = table();
global val_table3: table[count, int] of int = table();
global val_table4: table[count] of int;
event line_file(description: Input::EventDescription, tpe: Input::Event, r:FileVal)
{
print outfile, description$name;
print outfile, r;
}
event optional_line_file(description: Input::EventDescription, tpe: Input::Event, r:OptionalFileVal)
{
print outfile, description$name;
print outfile, r;
}
event line_record(description: Input::EventDescription, tpe: Input::Event, r: OptionalRecordVal)
{
print outfile, description$name;
print outfile, r;
}
event event1(description: Input::EventDescription, tpe: Input::Event, r: OptionalRecordVal, r2: OptionalRecordVal)
{
}
event event2(description: Input::TableDescription, tpe: string, r: OptionalRecordVal, r2: OptionalRecordVal)
{
}
event event3(description: Input::TableDescription, tpe: Input::Event, r: OptionalRecordVal, r2: OptionalRecordVal)
{
}
event event4(description: Input::TableDescription, tpe: Input::Event, r: Idx, r2: OptionalRecordVal)
{
}
event event5(description: Input::EventDescription, tpe: string, r: OptionalRecordVal, r2: OptionalRecordVal)
{
}
event event6(description: Input::EventDescription, tpe: Input::Event, r: OptionalRecordVal)
{
}
event event7(description: Input::EventDescription, tpe: Input::Event, r: OptionalRecordVal, r2:OptionalRecordVal)
{
}
event event8(description: Input::EventDescription, tpe: Input::Event, i: int, s:string, a:string)
{
}
event event9(description: Input::EventDescription, tpe: Input::Event, i: int, s:string, a:addr, ii: int)
{
}
event event10(description: Input::TableDescription, tpe: Input::Event, i: Idx, c: count)
{
}
event kill_me()
{
terminate();
}
event bro_init()
{
outfile = open("out");
Input::add_event([$source="input.log", $name="file", $fields=FileVal, $ev=line_file, $want_record=T]);
Input::add_event([$source="input.log", $name="optionalrecord", $fields=OptionalRecordVal, $ev=line_record, $want_record=T]);
Input::add_event([$source="input.log", $name="optionalfile", $fields=OptionalFileVal, $ev=optional_line_file, $want_record=T]);
Input::add_table([$source="input.log", $name="filetable", $idx=Idx, $val=FileVal, $destination=file_table]);
Input::add_table([$source="input.log", $name="optionalrecordtable", $idx=Idx, $val=OptionalRecordVal, $destination=record_table]);
Input::add_table([$source="input.log", $name="optionalfiletable", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table]);
Input::add_table([$source="input.log", $name="optionalfiletable", $idx=Idx, $val=OptionalFileVal, $destination=record_table]);
Input::add_table([$source="input.log", $name="optionalfiletable2", $idx=Idx, $val=OptionalFileVal, $destination=string_table]);
Input::add_table([$source="input.log", $name="optionalfiletable3", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=terminate]);
Input::add_table([$source="input.log", $name="optionalfiletable3", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=kill_me]);
Input::add_table([$source="input.log", $name="optionalfiletable4", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=event1]);
Input::add_table([$source="input.log", $name="optionalfiletable5", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=event2]);
Input::add_table([$source="input.log", $name="optionalfiletable6", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=event3]);
Input::add_table([$source="input.log", $name="optionalfiletable7", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=event4]);
Input::add_table([$source="input.log", $name="optionalfiletable8", $idx=Idx, $val=Val, $destination=val_table4, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable9", $idx=Idx2, $val=Val, $destination=val_table, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable10", $idx=Idx, $val=Val, $destination=val_table2, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable11", $idx=Idx2, $val=Idx, $destination=val_table3, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable12", $idx=Idx2, $val=Idx, $destination=val_table2, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable14", $idx=Idx, $val=OptionalFileVal, $destination=optional_file_table, $ev=event10, $want_record=F]);
Input::add_table([$source="input.log", $name="optionalfiletable15", $idx=Idx2, $val=Idx, $destination=val_table2, $want_record=T]);
Input::add_event([$source="input.log", $name="event1", $fields=OptionalFileVal, $ev=terminate, $want_record=T]);
Input::add_event([$source="input.log", $name="event2", $fields=OptionalFileVal, $ev=kill_me, $want_record=T]);
Input::add_event([$source="input.log", $name="event3", $fields=OptionalFileVal, $ev=event3, $want_record=T]);
Input::add_event([$source="input.log", $name="event4", $fields=OptionalFileVal, $ev=event5, $want_record=T]);
Input::add_event([$source="input.log", $name="event5", $fields=OptionalFileVal, $ev=event6, $want_record=T]);
Input::add_event([$source="input.log", $name="event6", $fields=OptionalFileVal, $ev=event7, $want_record=T]);
Input::add_event([$source="input.log", $name="event7", $fields=OptionalFileVal, $ev=event7, $want_record=F]);
Input::add_event([$source="input.log", $name="event8", $fields=Val, $ev=event8, $want_record=F]);
Input::add_event([$source="input.log", $name="event9", $fields=Val, $ev=event9, $want_record=F]);
schedule 3secs { kill_me() };
}

View file

@ -26,7 +26,7 @@ type Val: record {
b: bool;
};
global servers: table[int] of Val = table();
global servers: table[int] of bool = table();
event bro_init()
{

View file

@ -36,7 +36,7 @@ type Val: record {
b: bool;
};
global servers: table[int] of Val = table();
global servers: table[int] of bool = table();
global ct: int;
event line(description: Input::TableDescription, tpe: Input::Event, left: Idx, right: bool)

View file

@ -27,7 +27,7 @@ type Val: record {
b: bool;
};
global destination: table[int] of Val = table();
global destination: table[int] of bool = table();
const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};

View file

@ -31,7 +31,7 @@ type Val: record {
b: bool;
};
global destination: table[int] of Val = table();
global destination: table[int] of bool = table();
event line(description: Input::TableDescription, tpe: Input::Event, left: Idx, right: bool)
{
@ -51,5 +51,5 @@ event bro_init()
{
try = 0;
outfile = open("../out");
Input::add_table([$source="../input.log", $name="input", $idx=Idx, $val=Val, $destination=destination, $want_record=F,$ev=line]);
Input::add_table([$source="../input.log", $name="input", $idx=Idx, $val=Val, $destination=destination, $want_record=F, $ev=line]);
}