Merge remote-tracking branch 'origin/topic/johanna/bit-1181'

BIT-1181 #merged

* origin/topic/johanna/bit-1181:
  Input: Further small changes to error handling
  Add error events to input framework.
This commit is contained in:
Robin Sommer 2016-07-26 14:48:23 -07:00
commit 5b73345b73
33 changed files with 599 additions and 156 deletions

47
CHANGES
View file

@ -1,4 +1,51 @@
2.4-722 | 2016-07-26 14:48:23 -0700
* Input: Further small changes to error handling
Calling Error() in an input reader now automatically will disable the
reader and return a failure in the Update/Heartbeat calls.
Also adds more tests.
Addresses BIT-1181 (Johanna Amann)
* Add error events to input framework. (Johanna Amann)
This change introduces error events for Table and Event readers.
Users can now specify an event that is called when an info,
warning, or error is emitted by their input reader. This can,
e.g., be used to raise notices in case errors occur when reading
an important input stream.
Example:
event error_event(desc: Input::TableDescription, msg: string, level: Reporter::Level)
{
...
}
event bro_init()
{
Input::add_table([$source="a", $error_ev=error_event, ...]);
}
Addresses BIT-1181.
* Convert all errors in the ASCII formatter into warnings (to show
that they are non-fatal. (Johanna Amann)
* Enable SQLite shared cache mode. This allows all threads accessing
the same database to share sqlite objects. See
https://www.sqlite.org/sharedcache.html. Addresses BIT-1325.
(Johanna Amann)
* NetControl: Adjust default priority of ACTION_DROP hook to standad
level. (Johanna Amann)
* Fix types when constructing SYN_packet record. Fixes BIT-1650.
(Grant Moyer).
2.4-715 | 2016-07-23 07:27:05 -0700 2.4-715 | 2016-07-23 07:27:05 -0700
* SQLite writer: Remove unused string formatting function. (Johanna Amann) * SQLite writer: Remove unused string formatting function. (Johanna Amann)

3
NEWS
View file

@ -144,6 +144,9 @@ New Functionality
- The pcap buffer size can be set through the new option Pcap::bufsize. - The pcap buffer size can be set through the new option Pcap::bufsize.
- Input framework readers Table and Event can now define a custom
event to receive logging messages.
Changed Functionality Changed Functionality
--------------------- ---------------------

View file

@ -1 +1 @@
2.4-715 2.4-722

View file

@ -103,6 +103,17 @@ export {
## it is skipped. ## it is skipped.
pred: function(typ: Input::Event, left: any, right: any): bool &optional; pred: function(typ: Input::Event, left: any, right: any): bool &optional;
## Error event that is raised when an information, warning or error
## is raised by the input stream. If the level is error, the stream will automatically
## be closed.
## The event receives the Input::TableDescription as the first argument, the
## message as the second argument and the Reporter::Level as the third argument.
##
## The event is raised like if it had been declared as follows:
## error_ev: function(desc: TableDescription, message: string, level: Reporter::Level) &optional;
## The actual declaration uses the ``any`` type because of deficiencies of the Bro type system.
error_ev: any &optional;
## A key/value table that will be passed to the reader. ## A key/value table that will be passed to the reader.
## Interpretation of the values is left to the reader, but ## Interpretation of the values is left to the reader, but
## usually they will be used for configuration purposes. ## usually they will be used for configuration purposes.
@ -146,6 +157,17 @@ export {
## all fields, or each field value as a separate argument). ## all fields, or each field value as a separate argument).
ev: any; ev: any;
## Error event that is raised when an information, warning or error
## is raised by the input stream. If the level is error, the stream will automatically
## be closed.
## The event receives the Input::EventDescription as the first argument, the
## message as the second argument and the Reporter::Level as the third argument.
##
## The event is raised like it had been declared as follows:
## error_ev: function(desc: EventDescription, message: string, level: Reporter::Level) &optional;
## The actual declaration uses the ``any`` type because of deficiencies of the Bro type system.
error_ev: any &optional;
## A key/value table that will be passed to the reader. ## A key/value table that will be passed to the reader.
## Interpretation of the values is left to the reader, but ## Interpretation of the values is left to the reader, but
## usually they will be used for configuration purposes. ## usually they will be used for configuration purposes.

View file

@ -17,22 +17,14 @@ export {
## The reporter logging stream identifier. ## The reporter logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## An indicator of reporter message severity.
type Level: enum {
## Informational, not needing specific attention.
INFO,
## Warning of a potential problem.
WARNING,
## A non-fatal error that should be addressed, but doesn't
## terminate program execution.
ERROR
};
## The record type which contains the column fields of the reporter log. ## The record type which contains the column fields of the reporter log.
type Info: record { type Info: record {
## The network time at which the reporter event was generated. ## The network time at which the reporter event was generated.
ts: time &log; ts: time &log;
## The severity of the reporter message. ## The severity of the reporter message. Levels are INFO for informational
## messages, not needing specific attention; WARNING for warning of a potential
## problem, and ERROR for a non-fatal error that should be addressed, but doesn't
## terminate program execution.
level: Level &log; level: Level &log;
## An info/warning/error message that could have either been ## An info/warning/error message that could have either been
## generated from the internal Bro core or at the scripting-layer. ## generated from the internal Bro core or at the scripting-layer.

View file

@ -300,7 +300,7 @@ void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out,
{ {
va_list aq; va_list aq;
va_copy(aq, ap); va_copy(aq, ap);
int n = vsnprintf(buffer, size, fmt, aq); int n = safe_vsnprintf(buffer, size, fmt, aq);
va_end(aq); va_end(aq);
if ( postfix ) if ( postfix )
@ -321,7 +321,7 @@ void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out,
if ( postfix ) if ( postfix )
// Note, if you change this fmt string, adjust the additional // Note, if you change this fmt string, adjust the additional
// buffer size above. // buffer size above.
sprintf(buffer + strlen(buffer), " [%s]", postfix); safe_snprintf(buffer + strlen(buffer), size - strlen(buffer), " [%s]", postfix);
if ( event && via_events && ! in_error_handler ) if ( event && via_events && ! in_error_handler )
{ {

View file

@ -32,12 +32,7 @@ protected:
InterpreterException() {} InterpreterException() {}
}; };
// Check printf-style variadic arguments if we can.
#if __GNUC__
#define FMT_ATTR __attribute__((format(printf, 2, 3))) // sic! 1st is "this" I guess. #define FMT_ATTR __attribute__((format(printf, 2, 3))) // sic! 1st is "this" I guess.
#else
#define FMT_ATTR
#endif
class Reporter { class Reporter {
public: public:

View file

@ -67,6 +67,7 @@ public:
EnumVal* type; EnumVal* type;
ReaderFrontend* reader; ReaderFrontend* reader;
TableVal* config; TableVal* config;
EventHandlerPtr error_event;
RecordVal* description; RecordVal* description;
@ -78,7 +79,7 @@ protected:
Manager::Stream::Stream(StreamType t) Manager::Stream::Stream(StreamType t)
: name(), removed(), stream_type(t), type(), reader(), config(), : name(), removed(), stream_type(t), type(), reader(), config(),
description() error_event(), description()
{ {
} }
@ -103,7 +104,6 @@ public:
unsigned int num_idx_fields; unsigned int num_idx_fields;
unsigned int num_val_fields; unsigned int num_val_fields;
bool want_record; bool want_record;
EventHandlerPtr table_event;
TableVal* tab; TableVal* tab;
RecordType* rtype; RecordType* rtype;
@ -129,7 +129,7 @@ public:
bool want_record; bool want_record;
EventStream(); EventStream();
~EventStream(); ~EventStream();
}; };
class Manager::AnalysisStream: public Manager::Stream { class Manager::AnalysisStream: public Manager::Stream {
@ -432,6 +432,13 @@ bool Manager::CreateEventStream(RecordVal* fval)
else else
assert(false); assert(false);
Val* error_event_val = fval->Lookup("error_ev", true);
Func* error_event = error_event_val ? error_event_val->AsFunc() : nullptr;
Unref(error_event_val);
if ( ! CheckErrorEventTypes(stream_name, error_event, false) )
return false;
vector<Field*> fieldsV; // vector, because UnrollRecordType needs it vector<Field*> fieldsV; // vector, because UnrollRecordType needs it
bool status = (! UnrollRecordType(&fieldsV, fields, "", allow_file_func)); bool status = (! UnrollRecordType(&fieldsV, fields, "", allow_file_func));
@ -459,6 +466,7 @@ bool Manager::CreateEventStream(RecordVal* fval)
stream->num_fields = fieldsV.size(); stream->num_fields = fieldsV.size();
stream->fields = fields->Ref()->AsRecordType(); stream->fields = fields->Ref()->AsRecordType();
stream->event = event_registry->Lookup(event->Name()); stream->event = event_registry->Lookup(event->Name());
stream->error_event = error_event ? event_registry->Lookup(error_event->Name()) : nullptr;
stream->want_record = ( want_record->InternalInt() == 1 ); stream->want_record = ( want_record->InternalInt() == 1 );
Unref(want_record); // ref'd by lookupwithdefault Unref(want_record); // ref'd by lookupwithdefault
@ -558,8 +566,6 @@ bool Manager::CreateTableStream(RecordVal* fval)
} }
} }
Val* event_val = fval->Lookup("ev", true); Val* event_val = fval->Lookup("ev", true);
Func* event = event_val ? event_val->AsFunc() : 0; Func* event = event_val ? event_val->AsFunc() : 0;
Unref(event_val); Unref(event_val);
@ -628,9 +634,15 @@ bool Manager::CreateTableStream(RecordVal* fval)
} }
assert(want_record->InternalInt() == 1 || want_record->InternalInt() == 0); assert(want_record->InternalInt() == 1 || want_record->InternalInt() == 0);
} }
Val* error_event_val = fval->Lookup("error_ev", true);
Func* error_event = error_event_val ? error_event_val->AsFunc() : nullptr;
Unref(error_event_val);
if ( ! CheckErrorEventTypes(stream_name, error_event, true) )
return false;
vector<Field*> fieldsV; // vector, because we don't know the length beforehands vector<Field*> fieldsV; // vector, because we don't know the length beforehands
bool status = (! UnrollRecordType(&fieldsV, idx, "", false)); bool status = (! UnrollRecordType(&fieldsV, idx, "", false));
@ -678,6 +690,7 @@ bool Manager::CreateTableStream(RecordVal* fval)
stream->rtype = val ? val->AsRecordType() : 0; stream->rtype = val ? val->AsRecordType() : 0;
stream->itype = idx->AsRecordType(); stream->itype = idx->AsRecordType();
stream->event = event ? event_registry->Lookup(event->Name()) : 0; stream->event = event ? event_registry->Lookup(event->Name()) : 0;
stream->error_event = error_event ? event_registry->Lookup(error_event->Name()) : nullptr;
stream->currDict = new PDict(InputHash); stream->currDict = new PDict(InputHash);
stream->currDict->SetDeleteFunc(input_hash_delete_func); stream->currDict->SetDeleteFunc(input_hash_delete_func);
stream->lastDict = new PDict(InputHash); stream->lastDict = new PDict(InputHash);
@ -698,6 +711,54 @@ bool Manager::CreateTableStream(RecordVal* fval)
return true; return true;
} }
bool Manager::CheckErrorEventTypes(std::string stream_name, Func* ev, bool table)
{
if ( ev == nullptr )
return true;
FuncType* etype = ev->FType()->AsFuncType();
if ( etype->Flavor() != FUNC_FLAVOR_EVENT )
{
reporter->Error("Input stream %s: Error event is a function, not an event", stream_name.c_str());
return false;
}
const type_list* args = etype->ArgTypes()->Types();
if ( args->length() != 3 )
{
reporter->Error("Input stream %s: Error event must take 3 arguments", stream_name.c_str());
return false;
}
if ( table && ! same_type((*args)[0], BifType::Record::Input::TableDescription, 0) )
{
reporter->Error("Input stream %s: Error event's first attribute must be of type Input::TableDescription", stream_name.c_str());
return false;
}
if ( ! table && ! same_type((*args)[0], BifType::Record::Input::EventDescription, 0) )
{
reporter->Error("Input stream %s: Error event's first attribute must be of type Input::EventDescription", stream_name.c_str());
return false;
}
if ( (*args)[1]->Tag() != TYPE_STRING )
{
reporter->Error("Input stream %s: Error event's second attribute must be of type string", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[2], BifType::Enum::Reporter::Level, 0) )
{
reporter->Error("Input stream %s: Error event's third attribute must be of type Reporter::Level", stream_name.c_str());
return false;
}
return true;
}
bool Manager::CreateAnalysisStream(RecordVal* fval) bool Manager::CreateAnalysisStream(RecordVal* fval)
{ {
RecordType* rtype = fval->Type()->AsRecordType(); RecordType* rtype = fval->Type()->AsRecordType();
@ -1054,7 +1115,7 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
if ( idxhash == 0 ) if ( idxhash == 0 )
{ {
reporter->Error("Could not hash line. Ignoring"); Warning(i, "Could not hash line. Ignoring");
return stream->num_val_fields + stream->num_idx_fields; return stream->num_val_fields + stream->num_idx_fields;
} }
@ -1719,7 +1780,7 @@ bool Manager::Delete(ReaderFrontend* reader, Value* *vals)
Val* retptr = stream->tab->Delete(idxval); Val* retptr = stream->tab->Delete(idxval);
success = ( retptr != 0 ); success = ( retptr != 0 );
if ( ! success ) if ( ! success )
reporter->Error("Internal error while deleting values from input table"); Warning(i, "Internal error while deleting values from input table");
else else
Unref(retptr); Unref(retptr);
} }
@ -1771,6 +1832,9 @@ bool Manager::CallPred(Func* pred_func, const int numvals, ...)
return result; return result;
} }
// Raise everything in here as warnings so it is passed to scriptland without
// looking "fatal". In addition to these warnings, ReaderBackend will queue
// one reporter message.
bool Manager::SendEvent(ReaderFrontend* reader, const string& name, const int num_vals, Value* *vals) bool Manager::SendEvent(ReaderFrontend* reader, const string& name, const int num_vals, Value* *vals)
{ {
Stream *i = FindStream(reader); Stream *i = FindStream(reader);
@ -1783,7 +1847,7 @@ bool Manager::SendEvent(ReaderFrontend* reader, const string& name, const int nu
EventHandler* handler = event_registry->Lookup(name.c_str()); EventHandler* handler = event_registry->Lookup(name.c_str());
if ( handler == 0 ) if ( handler == 0 )
{ {
reporter->Error("Event %s not found", name.c_str()); Warning(i, "Event %s not found", name.c_str());
delete_value_ptr_array(vals, num_vals); delete_value_ptr_array(vals, num_vals);
return false; return false;
} }
@ -1797,7 +1861,7 @@ bool Manager::SendEvent(ReaderFrontend* reader, const string& name, const int nu
int num_event_vals = type->NumFields(); int num_event_vals = type->NumFields();
if ( num_vals != num_event_vals ) if ( num_vals != num_event_vals )
{ {
reporter->Error("Wrong number of values for event %s", name.c_str()); Warning(i, "Wrong number of values for event %s", name.c_str());
delete_value_ptr_array(vals, num_vals); delete_value_ptr_array(vals, num_vals);
return false; return false;
} }
@ -2315,7 +2379,7 @@ Val* Manager::ValueToVal(const Stream* i, const Value* val, BroType* request_typ
bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str()); bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str());
if ( index == -1 ) if ( index == -1 )
{ {
reporter->Error("Value not '%s' for stream '%s' is not a valid enum.", Warning(i, "Value not '%s' for stream '%s' is not a valid enum.",
enum_string.c_str(), i->name.c_str()); enum_string.c_str(), i->name.c_str());
have_error = true; have_error = true;
@ -2367,3 +2431,132 @@ void Manager::Terminate()
} }
} }
void Manager::Info(ReaderFrontend* reader, const char* msg)
{
Stream *i = FindStream(reader);
if ( !i )
{
reporter->Error("Stream not found in Info; lost message: %s", msg);
return;
}
ErrorHandler(i, ErrorType::INFO, false, "%s", msg);
}
void Manager::Warning(ReaderFrontend* reader, const char* msg)
{
Stream *i = FindStream(reader);
if ( !i )
{
reporter->Error("Stream not found in Warning; lost message: %s", msg);
return;
}
ErrorHandler(i, ErrorType::WARNING, false, "%s", msg);
}
void Manager::Error(ReaderFrontend* reader, const char* msg)
{
Stream *i = FindStream(reader);
if ( !i )
{
reporter->Error("Stream not found in Error; lost message: %s", msg);
return;
}
ErrorHandler(i, ErrorType::ERROR, false, "%s", msg);
}
void Manager::Info(const Stream* i, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ErrorHandler(i, ErrorType::INFO, true, fmt, ap);
va_end(ap);
}
void Manager::Warning(const Stream* i, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ErrorHandler(i, ErrorType::WARNING, true, fmt, ap);
va_end(ap);
}
void Manager::Error(const Stream* i, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ErrorHandler(i, ErrorType::ERROR, true, fmt, ap);
va_end(ap);
}
void Manager::ErrorHandler(const Stream* i, ErrorType et, bool reporter_send, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ErrorHandler(i, et, reporter_send, fmt, ap);
va_end(ap);
}
void Manager::ErrorHandler(const Stream* i, ErrorType et, bool reporter_send, const char* fmt, va_list ap)
{
char* buf;
int n = vasprintf(&buf, fmt, ap);
if ( n < 0 || buf == nullptr )
{
reporter->InternalError("Could not format error message %s for stream %s", fmt, i->name.c_str());
return;
}
// send our script level error event
if ( i->error_event )
{
EnumVal* ev;
switch (et)
{
case ErrorType::INFO:
ev = new EnumVal(BifEnum::Reporter::INFO, BifType::Enum::Reporter::Level);
break;
case ErrorType::WARNING:
ev = new EnumVal(BifEnum::Reporter::WARNING, BifType::Enum::Reporter::Level);
break;
case ErrorType::ERROR:
ev = new EnumVal(BifEnum::Reporter::ERROR, BifType::Enum::Reporter::Level);
break;
default:
reporter->InternalError("Unknown error type while trying to report input error %s", fmt);
}
StringVal* message = new StringVal(buf);
SendEvent(i->error_event, 3, i->description->Ref(), message, ev);
}
if ( reporter_send )
{
switch (et)
{
case ErrorType::INFO:
reporter->Info("%s", buf);
break;
case ErrorType::WARNING:
reporter->Warning("%s", buf);
break;
case ErrorType::ERROR:
reporter->Error("%s", buf);
break;
default:
reporter->InternalError("Unknown error type while trying to report input error %s", fmt);
}
}
free(buf);
}

View file

@ -109,6 +109,7 @@ protected:
friend class ReaderClosedMessage; friend class ReaderClosedMessage;
friend class DisableMessage; friend class DisableMessage;
friend class EndOfDataMessage; friend class EndOfDataMessage;
friend class ReaderErrorMessage;
// For readers to write to input stream in direct mode (reporting // For readers to write to input stream in direct mode (reporting
// new/deleted values directly). Functions take ownership of // new/deleted values directly). Functions take ownership of
@ -143,6 +144,13 @@ protected:
// stream is still received. // stream is still received.
bool RemoveStreamContinuation(ReaderFrontend* reader); bool RemoveStreamContinuation(ReaderFrontend* reader);
// Signal Informational messages, warnings and errors. These will be
// passed to the error function in scriptland. Note that the messages
// are not passed to reporter - this is done in ReaderBackend.
void Info(ReaderFrontend* reader, const char* msg);
void Warning(ReaderFrontend* reader, const char* msg);
void Error(ReaderFrontend* reader, const char* msg);
/** /**
* Deletes an existing input stream. * Deletes an existing input stream.
* *
@ -165,6 +173,11 @@ private:
bool CreateStream(Stream*, RecordVal* description); bool CreateStream(Stream*, RecordVal* description);
// Check if the types of the error_ev event are correct. If table is
// true, check for tablestream type, otherwhise check for eventstream
// type.
bool CheckErrorEventTypes(std::string stream_name, Func* error_event, bool table);
// SendEntry implementation for Table stream. // SendEntry implementation for Table stream.
int SendEntryTable(Stream* i, const threading::Value* const *vals); int SendEntryTable(Stream* i, const threading::Value* const *vals);
@ -219,6 +232,16 @@ private:
// Converts a Bro ListVal to a RecordVal given the record type. // Converts a Bro ListVal to a RecordVal given the record type.
RecordVal* ListValToRecordVal(ListVal* list, RecordType *request_type, int* position); RecordVal* ListValToRecordVal(ListVal* list, RecordType *request_type, int* position);
// Internally signal errors, warnings, etc.
// These are sent on to input scriptland and reporter.log
void Info(const Stream* i, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
void Warning(const Stream* i, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
void Error(const Stream* i, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
enum class ErrorType { INFO, WARNING, ERROR };
void ErrorHandler(const Stream* i, ErrorType et, bool reporter_send, const char* fmt, ...) __attribute__((format(printf, 5, 6)));
void ErrorHandler(const Stream* i, ErrorType et, bool reporter_send, const char* fmt, va_list ap);
Stream* FindStream(const string &name); Stream* FindStream(const string &name);
Stream* FindStream(ReaderFrontend* reader); Stream* FindStream(ReaderFrontend* reader);

View file

@ -78,6 +78,26 @@ private:
Value* *val; Value* *val;
}; };
class ReaderErrorMessage : public threading::OutputMessage<ReaderFrontend>
{
public:
enum Type {
INFO, WARNING, ERROR
};
ReaderErrorMessage(ReaderFrontend* reader, Type arg_type, const char* arg_msg)
: threading::OutputMessage<ReaderFrontend>("ReaderErrorMessage", reader)
{ type = arg_type; msg = copy_string(arg_msg); }
virtual ~ReaderErrorMessage() { delete [] msg; }
virtual bool Process();
private:
const char* msg;
Type type;
};
class SendEntryMessage : public threading::OutputMessage<ReaderFrontend> { class SendEntryMessage : public threading::OutputMessage<ReaderFrontend> {
public: public:
SendEntryMessage(ReaderFrontend* reader, Value* *val) SendEntryMessage(ReaderFrontend* reader, Value* *val)
@ -136,7 +156,6 @@ public:
private: private:
}; };
class DisableMessage : public threading::OutputMessage<ReaderFrontend> class DisableMessage : public threading::OutputMessage<ReaderFrontend>
{ {
public: public:
@ -156,6 +175,27 @@ public:
} }
}; };
bool ReaderErrorMessage::Process()
{
switch ( type ) {
case INFO:
input_mgr->Info(Object(), msg);
break;
case WARNING:
input_mgr->Warning(Object(), msg);
break;
case ERROR:
input_mgr->Error(Object(), msg);
break;
}
return true;
}
using namespace input; using namespace input;
ReaderBackend::ReaderBackend(ReaderFrontend* arg_frontend) : MsgThread() ReaderBackend::ReaderBackend(ReaderFrontend* arg_frontend) : MsgThread()
@ -266,11 +306,16 @@ bool ReaderBackend::Update()
if ( ! success ) if ( ! success )
DisableFrontend(); DisableFrontend();
return success; return ! disabled; // always return failure if we have been disabled in the meantime
} }
void ReaderBackend::DisableFrontend() void ReaderBackend::DisableFrontend()
{ {
// We might already have been disabled - e.g., due to a call to
// error. In that case, ignore this...
if ( disabled )
return;
// We also set disabled here, because there still may be other // We also set disabled here, because there still may be other
// messages queued and we will dutifully ignore these from now. // messages queued and we will dutifully ignore these from now.
disabled = true; disabled = true;
@ -285,4 +330,25 @@ bool ReaderBackend::OnHeartbeat(double network_time, double current_time)
return DoHeartbeat(network_time, current_time); return DoHeartbeat(network_time, current_time);
} }
void ReaderBackend::Info(const char* msg)
{
SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::INFO, msg));
MsgThread::Info(msg);
}
void ReaderBackend::Warning(const char* msg)
{
SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::WARNING, msg));
MsgThread::Warning(msg);
}
void ReaderBackend::Error(const char* msg)
{
SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::ERROR, msg));
MsgThread::Error(msg);
// Force errors to be fatal.
DisableFrontend();
}
} }

View file

@ -63,7 +63,7 @@ public:
* an argument to callbacks. One must not otherwise access the * an argument to callbacks. One must not otherwise access the
* frontend, it's running in a different thread. * frontend, it's running in a different thread.
*/ */
ReaderBackend(ReaderFrontend* frontend); explicit ReaderBackend(ReaderFrontend* frontend);
/** /**
* Destructor. * Destructor.
@ -186,8 +186,22 @@ public:
int NumFields() const { return num_fields; } int NumFields() const { return num_fields; }
// Overridden from MsgThread. // Overridden from MsgThread.
virtual bool OnHeartbeat(double network_time, double current_time); bool OnHeartbeat(double network_time, double current_time) override;
virtual bool OnFinish(double network_time); bool OnFinish(double network_time) override;
void Info(const char* msg) override;
void Warning(const char* msg) override;
/**
* Reports an error in the child thread. For input readers, it is assumed
* that Info and Warnings do not cause the read operation to fail (they might
* signal that, e.g., a single line was ignored).
*
* It is assumed that Errors are not recoverable. Calling the Error function
* will return the error back to scriptland and also *automatically* causes
* the current reader to be disabled and torn down.
*/
void Error(const char* msg) override;
protected: protected:
// Methods that have to be overwritten by the individual readers // Methods that have to be overwritten by the individual readers
@ -325,7 +339,6 @@ protected:
*/ */
void EndCurrentSend(); void EndCurrentSend();
private: private:
// Frontend that instantiated us. This object must not be accessed // Frontend that instantiated us. This object must not be accessed
// from this class, it's running in a different thread! // from this class, it's running in a different thread!

View file

@ -341,7 +341,7 @@ bool Ascii::DoUpdate()
if ( val == 0 ) if ( val == 0 )
{ {
Error(Fmt("Could not convert line '%s' to Val. Ignoring line.", line.c_str())); Warning(Fmt("Could not convert line '%s' to Val. Ignoring line.", line.c_str()));
error = true; error = true;
break; break;
} }

View file

@ -38,7 +38,7 @@ public:
* @param name A descriptive name for writer's type (e.g., \c Ascii). * @param name A descriptive name for writer's type (e.g., \c Ascii).
* *
*/ */
WriterBackend(WriterFrontend* frontend); explicit WriterBackend(WriterFrontend* frontend);
/** /**
* Destructor. * Destructor.
@ -248,8 +248,12 @@ public:
bool FinishedRotation(); bool FinishedRotation();
// Overridden from MsgThread. // Overridden from MsgThread.
virtual bool OnHeartbeat(double network_time, double current_time); bool OnHeartbeat(double network_time, double current_time) override;
virtual bool OnFinish(double network_time); bool OnFinish(double network_time) override;
// Let the compiler know that we are aware that there is a virtual
// info function in the base.
using MsgThread::Info;
protected: protected:
friend class FinishMessage; friend class FinishMessage;

View file

@ -23,7 +23,7 @@ public:
* internal formatting. * internal formatting.
* *
*/ */
Formatter(threading::MsgThread* t); explicit Formatter(threading::MsgThread* t);
/** /**
* Destructor. * Destructor.

View file

@ -64,7 +64,7 @@ public:
* *
* @param msg The message. It will be prefixed with the thread's name. * @param msg The message. It will be prefixed with the thread's name.
*/ */
void Info(const char* msg); virtual void Info(const char* msg);
/** /**
* Reports a warning from the child thread that may indicate a * Reports a warning from the child thread that may indicate a
@ -73,9 +73,14 @@ public:
* *
* Only the child thread may call this method. * Only the child thread may call this method.
* *
* Can be overriden in derived classed to hook into the error handling
* but must should generally also call the parent implementation. Note
* that this method is always called by the child thread and must not access
* data or datastructures of the main thread directly.
*
* @param msg The message. It will be prefixed with the thread's name. * @param msg The message. It will be prefixed with the thread's name.
*/ */
void Warning(const char* msg); virtual void Warning(const char* msg);
/** /**
* Reports a non-fatal error from the child thread. The main thread * Reports a non-fatal error from the child thread. The main thread
@ -84,9 +89,14 @@ public:
* *
* Only the child thread may call this method. * Only the child thread may call this method.
* *
* Can be overriden in derived classed to hook into the error handling
* but must should generally also call the parent implementation. Note
* that this method is always called by the child thread and must not access
* data or datastructures of the main thread directly.
*
* @param msg The message. It will be prefixed with the thread's name. * @param msg The message. It will be prefixed with the thread's name.
*/ */
void Error(const char* msg); virtual void Error(const char* msg);
/** /**
* Reports a fatal error from the child thread. The main thread will * Reports a fatal error from the child thread. The main thread will
@ -223,10 +233,10 @@ protected:
* Overriden from BasicThread. * Overriden from BasicThread.
* *
*/ */
virtual void Run(); void Run() override;
virtual void OnWaitForStop(); void OnWaitForStop() override;
virtual void OnSignalStop(); void OnSignalStop() override;
virtual void OnKill(); void OnKill() override;
private: private:
/** /**

View file

@ -232,7 +232,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
val->val.int_val = 0; val->val.int_val = 0;
else else
{ {
GetThread()->Error(GetThread()->Fmt("Field: %s Invalid value for boolean: %s", GetThread()->Warning(GetThread()->Fmt("Field: %s Invalid value for boolean: %s",
name.c_str(), start)); name.c_str(), start));
goto parse_error; goto parse_error;
} }
@ -273,7 +273,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
size_t pos = unescaped.find("/"); size_t pos = unescaped.find("/");
if ( pos == unescaped.npos ) if ( pos == unescaped.npos )
{ {
GetThread()->Error(GetThread()->Fmt("Invalid value for subnet: %s", start)); GetThread()->Warning(GetThread()->Fmt("Invalid value for subnet: %s", start));
goto parse_error; goto parse_error;
} }
@ -348,7 +348,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
if ( pos >= length ) if ( pos >= length )
{ {
GetThread()->Error(GetThread()->Fmt("Internal error while parsing set. pos %d >= length %d." GetThread()->Warning(GetThread()->Fmt("Internal error while parsing set. pos %d >= length %d."
" Element: %s", pos, length, element.c_str())); " Element: %s", pos, length, element.c_str()));
error = true; error = true;
break; break;
@ -357,7 +357,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
threading::Value* newval = ParseValue(element, name, subtype); threading::Value* newval = ParseValue(element, name, subtype);
if ( newval == 0 ) if ( newval == 0 )
{ {
GetThread()->Error("Error while reading set or vector"); GetThread()->Warning("Error while reading set or vector");
error = true; error = true;
break; break;
} }
@ -375,7 +375,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
lvals[pos] = ParseValue("", name, subtype); lvals[pos] = ParseValue("", name, subtype);
if ( lvals[pos] == 0 ) if ( lvals[pos] == 0 )
{ {
GetThread()->Error("Error while trying to add empty set element"); GetThread()->Warning("Error while trying to add empty set element");
goto parse_error; goto parse_error;
} }
@ -394,7 +394,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
if ( pos != length ) if ( pos != length )
{ {
GetThread()->Error(GetThread()->Fmt("Internal error while parsing set: did not find all elements: %s", start)); GetThread()->Warning(GetThread()->Fmt("Internal error while parsing set: did not find all elements: %s", start));
goto parse_error; goto parse_error;
} }
@ -402,7 +402,7 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
} }
default: default:
GetThread()->Error(GetThread()->Fmt("unsupported field format %d for %s", type, GetThread()->Warning(GetThread()->Fmt("unsupported field format %d for %s", type,
name.c_str())); name.c_str()));
goto parse_error; goto parse_error;
} }
@ -419,13 +419,13 @@ bool Ascii::CheckNumberError(const char* start, const char* end) const
threading::MsgThread* thread = GetThread(); threading::MsgThread* thread = GetThread();
if ( end == start && *end != '\0' ) { if ( end == start && *end != '\0' ) {
thread->Error(thread->Fmt("String '%s' contained no parseable number", start)); thread->Warning(thread->Fmt("String '%s' contained no parseable number", start));
return true; return true;
} }
if ( end - start == 0 && *end == '\0' ) if ( end - start == 0 && *end == '\0' )
{ {
thread->Error("Got empty string for number field"); thread->Warning("Got empty string for number field");
return true; return true;
} }
@ -434,13 +434,13 @@ bool Ascii::CheckNumberError(const char* start, const char* end) const
if ( errno == EINVAL ) if ( errno == EINVAL )
{ {
thread->Error(thread->Fmt("String '%s' could not be converted to a number", start)); thread->Warning(thread->Fmt("String '%s' could not be converted to a number", start));
return true; return true;
} }
else if ( errno == ERANGE ) else if ( errno == ERANGE )
{ {
thread->Error(thread->Fmt("Number '%s' out of supported range.", start)); thread->Warning(thread->Fmt("Number '%s' out of supported range.", start));
return true; return true;
} }

View file

@ -209,3 +209,13 @@ type gtp_rai: record;
type gtp_qos_profile: record; type gtp_qos_profile: record;
type gtp_private_extension: record; type gtp_private_extension: record;
type gtp_gsn_addr: record; type gtp_gsn_addr: record;
module Reporter;
enum Level %{
INFO = 0,
WARNING = 1,
ERROR = 2,
%}
module GLOBAL;

View file

@ -27,12 +27,6 @@
#include "bro-config.h" #include "bro-config.h"
#include "siphash24.h" #include "siphash24.h"
#if __STDC__
#define myattribute __attribute__
#else
#define myattribute(x)
#endif
#ifdef DEBUG #ifdef DEBUG
#include <assert.h> #include <assert.h>
@ -165,7 +159,7 @@ extern const char* fmt_bytes(const char* data, int len);
// Note: returns a pointer into a shared buffer. // Note: returns a pointer into a shared buffer.
extern const char* fmt(const char* format, ...) extern const char* fmt(const char* format, ...)
myattribute((format (printf, 1, 2))); __attribute__((format (printf, 1, 2)));
extern const char* fmt_access_time(double time); extern const char* fmt_access_time(double time);
extern bool ensure_intermediate_dirs(const char* dirname); extern bool ensure_intermediate_dirs(const char* dirname);

View file

@ -29,7 +29,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -61,7 +61,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -106,7 +106,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -138,7 +138,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type

View file

@ -33,4 +33,9 @@ error: Input stream event6: Event has wrong number of arguments
error: Input stream event7: Incompatible type for event in field 3. Need type 'int':int, got 'record':record { i:int; r:record { i:int; s:file of string; }; } error: Input stream event7: Incompatible type for event in field 3. Need type 'int':int, got 'record':record { i:int; r:record { i:int; s:file of string; }; }
error: Input stream event8: Incompatible type for event in field 5. Need type 'addr':addr, got 'string':string error: Input stream event8: Incompatible type for event in field 5. Need type 'addr':addr, got 'string':string
error: Input stream event9: Event has wrong number of arguments error: Input stream event9: Event has wrong number of arguments
error: Input stream error1: Error event's first attribute must be of type Input::EventDescription
error: Input stream error2: Error event's first attribute must be of type Input::TableDescription
error: Input stream error3: Error event's first attribute must be of type Input::EventDescription
error: Input stream error4: Error event's second attribute must be of type string
error: Input stream error5: Error event's third attribute must be of type Reporter::Level
received termination signal received termination signal

View file

@ -4,7 +4,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -16,7 +16,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -28,7 +28,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -40,7 +40,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -52,7 +52,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -64,7 +64,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -76,7 +76,7 @@ print outfile, A::description;
print outfile, A::tpe; print outfile, A::tpe;
print outfile, A::i; print outfile, A::i;
print outfile, A::b; print outfile, A::b;
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -1,8 +1,8 @@
error: ../input.log/Input::READER_ASCII: Number '12129223372036854775800' out of supported range. warning: ../input.log/Input::READER_ASCII: Number '12129223372036854775800' out of supported range.
error: ../input.log/Input::READER_ASCII: Could not convert line '12129223372036854775800 121218446744073709551612' to Val. Ignoring line. warning: ../input.log/Input::READER_ASCII: Could not convert line '12129223372036854775800 121218446744073709551612' to Val. Ignoring line.
warning: ../input.log/Input::READER_ASCII: Number '9223372036854775801TEXTHERE' contained non-numeric trailing characters. Ignored trailing characters 'TEXTHERE' warning: ../input.log/Input::READER_ASCII: Number '9223372036854775801TEXTHERE' contained non-numeric trailing characters. Ignored trailing characters 'TEXTHERE'
warning: ../input.log/Input::READER_ASCII: Number '1Justtext' contained non-numeric trailing characters. Ignored trailing characters 'Justtext' warning: ../input.log/Input::READER_ASCII: Number '1Justtext' contained non-numeric trailing characters. Ignored trailing characters 'Justtext'
error: ../input.log/Input::READER_ASCII: String 'Justtext' contained no parseable number warning: ../input.log/Input::READER_ASCII: String 'Justtext' contained no parseable number
error: ../input.log/Input::READER_ASCII: Could not convert line 'Justtext 1' to Val. Ignoring line. warning: ../input.log/Input::READER_ASCII: Could not convert line 'Justtext 1' to Val. Ignoring line.
received termination signal received termination signal
>>> >>>

View file

@ -1,4 +1,6 @@
error: ../input.log/Input::READER_ASCII: String 'l' contained no parseable number warning: ../input.log/Input::READER_ASCII: String 'l' contained no parseable number
error: ../input.log/Input::READER_ASCII: Could not convert line ' l' to Val. Ignoring line. warning: ../input.log/Input::READER_ASCII: Could not convert line ' l' to Val. Ignoring line.
warning: ../input.log/Input::READER_ASCII: String 'l' contained no parseable number
warning: ../input.log/Input::READER_ASCII: Could not convert line ' l' to Val. Ignoring line.
received termination signal received termination signal
>>> >>>

View file

@ -1,3 +1,8 @@
TableErrorEvent, String 'l' contained no parseable number, Reporter::WARNING
TableErrorEvent, Could not convert line '\x09l' to Val. Ignoring line., Reporter::WARNING
{ {
[] = [c=5] [] = [c=5]
} }
EventErrorEvent, String 'l' contained no parseable number, Reporter::WARNING
EventErrorEvent, Could not convert line '\x09l' to Val. Ignoring line., Reporter::WARNING
Event, [c=5]

View file

@ -1,2 +1,2 @@
error: Value not 'IdoNot::Exist' for stream 'enum' is not a valid enum. warning: Value not 'IdoNot::Exist' for stream 'enum' is not a valid enum.
received termination signal received termination signal

View file

@ -11,7 +11,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -29,7 +29,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -47,7 +47,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -65,7 +65,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -83,7 +83,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -101,7 +101,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -119,7 +119,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -137,7 +137,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -6,7 +6,7 @@ print outfile, s;
Input::remove(input); Input::remove(input);
close(outfile); close(outfile);
terminate(); terminate();
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -12,7 +12,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -31,7 +31,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -50,7 +50,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -69,7 +69,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -88,7 +88,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -107,7 +107,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -126,7 +126,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -145,7 +145,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -11,7 +11,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -29,7 +29,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -47,7 +47,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -65,7 +65,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -83,7 +83,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -101,7 +101,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -119,7 +119,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -137,7 +137,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -155,7 +155,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -173,7 +173,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -191,7 +191,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -209,7 +209,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -227,7 +227,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -245,7 +245,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -263,7 +263,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -281,7 +281,7 @@ close(outfile);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -12,7 +12,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -31,7 +31,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -50,7 +50,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -69,7 +69,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -88,7 +88,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -107,7 +107,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -126,7 +126,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW
@ -145,7 +145,7 @@ Input::remove(input);
terminate(); terminate();
} }
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Input::EVENT_NEW Input::EVENT_NEW

View file

@ -46,7 +46,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -141,7 +141,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -248,7 +248,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -475,7 +475,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -600,7 +600,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -725,7 +725,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -850,7 +850,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -975,7 +975,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1205,7 +1205,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1258,7 +1258,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1311,7 +1311,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1364,7 +1364,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1417,7 +1417,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type
@ -1470,7 +1470,7 @@ print A::outfile, A::typ;
print A::outfile, A::left; print A::outfile, A::left;
print A::outfile, A::right; print A::outfile, A::right;
return (T); return (T);
}, config={ }, error_ev=<uninitialized>, config={
}] }]
Type Type

View file

@ -118,6 +118,31 @@ event event10(description: Input::TableDescription, tpe: Input::Event, i: Idx, c
{ {
} }
# these are legit to test the error events
event event11(description: Input::EventDescription, tpe: Input::Event, v: Val)
{
}
event errorhandler1(desc: Input::TableDescription, msg: string, level: Reporter::Level)
{
}
event errorhandler2(desc: Input::EventDescription, msg: string, level: Reporter::Level)
{
}
event errorhandler3(desc: string, msg: string, level: Reporter::Level)
{
}
event errorhandler4(desc: Input::EventDescription, msg: count, level: Reporter::Level)
{
}
event errorhandler5(desc: Input::EventDescription, msg: string, level: count)
{
}
event kill_me() event kill_me()
{ {
terminate(); terminate();
@ -129,23 +154,23 @@ event bro_init()
Input::add_event([$source="input.log", $name="file", $fields=FileVal, $ev=line_file, $want_record=T]); 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="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_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="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="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=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="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="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=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="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="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="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="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="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="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="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="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="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="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="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_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="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="event2", $fields=OptionalFileVal, $ev=kill_me, $want_record=T]);
@ -157,5 +182,11 @@ event bro_init()
Input::add_event([$source="input.log", $name="event8", $fields=Val, $ev=event8, $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]); Input::add_event([$source="input.log", $name="event9", $fields=Val, $ev=event9, $want_record=F]);
Input::add_event([$source="input.log", $name="error1", $fields=Val, $ev=event11, $want_record=T, $error_ev=errorhandler1]);
Input::add_table([$source="input.log", $name="error2", $idx=Idx, $val=Val, $destination=val_table, $error_ev=errorhandler2]);
Input::add_event([$source="input.log", $name="error3", $fields=Val, $ev=event11, $want_record=T, $error_ev=errorhandler3]);
Input::add_event([$source="input.log", $name="error4", $fields=Val, $ev=event11, $want_record=T, $error_ev=errorhandler4]);
Input::add_event([$source="input.log", $name="error5", $fields=Val, $ev=event11, $want_record=T, $error_ev=errorhandler5]);
schedule 3secs { kill_me() }; schedule 3secs { kill_me() };
} }

View file

@ -26,18 +26,46 @@ type Val: record {
c: count; c: count;
}; };
global endcount: count = 0;
global servers: table[string] of Val = table(); global servers: table[string] of Val = table();
event handle_our_errors(desc: Input::TableDescription, msg: string, level: Reporter::Level)
{
print outfile, "TableErrorEvent", msg, level;
}
event handle_our_errors_event(desc: Input::EventDescription, msg: string, level: Reporter::Level)
{
print outfile, "EventErrorEvent", msg, level;
}
event line(description: Input::EventDescription, tpe: Input::Event, v: Val)
{
print outfile, "Event", v;
}
event bro_init() event bro_init()
{ {
outfile = open("../out"); outfile = open("../out");
# first read in the old stuff into the table... # first read in the old stuff into the table...
Input::add_table([$source="../input.log", $name="ssh", $idx=Idx, $val=Val, $destination=servers]); Input::add_table([$source="../input.log", $name="ssh", $error_ev=handle_our_errors, $idx=Idx, $val=Val, $destination=servers]);
Input::add_event([$source="../input.log", $name="sshevent", $error_ev=handle_our_errors_event, $fields=Val, $want_record=T, $ev=line]);
} }
event Input::end_of_data(name: string, source:string) event Input::end_of_data(name: string, source:string)
{ {
print outfile, servers; ++endcount;
Input::remove("ssh");
terminate(); if ( endcount == 1 )
{
print outfile, servers;
Input::remove("ssh");
}
if ( endcount == 2 )
{
Input::remove("sshevent");
terminate();
}
} }