From 97b5f812c76b7115c50b7620a75bec09bc4af9ba Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 7 Jul 2011 10:40:52 -0700 Subject: [PATCH] A new event bro_script_loaded() raised for each policy script loaded. Also removing the -l command-line option as that can now be done at the script-level. A couple tests fail now that use -l. Leaving that until we have script-level replacement. --- src/Net.cc | 1 + src/Net.h | 14 ++++++ src/event.bif | 3 ++ src/main.cc | 23 +++++---- src/scan.l | 48 ++++--------------- .../policy.misc.loaded-scripts/output | 0 testing/btest/policy/misc/loaded-scripts.bro | 7 +++ 7 files changed, 46 insertions(+), 50 deletions(-) create mode 100644 testing/btest/Baseline/policy.misc.loaded-scripts/output create mode 100644 testing/btest/policy/misc/loaded-scripts.bro diff --git a/src/Net.cc b/src/Net.cc index c007760aca..df91521eee 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -71,6 +71,7 @@ double current_timestamp = 0.0; PktSrc* current_pktsrc = 0; IOSource* current_iosrc; +std::list files_scanned; RETSIGTYPE watchdog(int /* signo */) { diff --git a/src/Net.h b/src/Net.h index 16d36791d2..3544dd7f3d 100644 --- a/src/Net.h +++ b/src/Net.h @@ -90,4 +90,18 @@ extern PktDumper* pkt_dumper; // where to save packets extern char* writefile; +// Script file we have already scanned (or are in the process of scanning). +// They are identified by inode number. +struct ScannedFile { + ino_t inode; + int include_level; + string name; + + ScannedFile(ino_t arg_inode, int arg_include_level, string arg_name) + : inode(arg_inode), include_level(arg_include_level), name(arg_name) + { } +}; + +extern std::list files_scanned; + #endif diff --git a/src/event.bif b/src/event.bif index 96113980c1..7ec0d404ca 100644 --- a/src/event.bif +++ b/src/event.bif @@ -480,3 +480,6 @@ event netflow_v5_record%(r: nf_v5_record%); event reporter_info%(t: time, msg: string, location: string%) &error_handler; event reporter_warning%(t: time, msg: string, location: string%) &error_handler; event reporter_error%(t: time, msg: string, location: string%) &error_handler; + +# Raised for each policy script loaded. +event bro_script_loaded%(path: string, level: count%); diff --git a/src/main.cc b/src/main.cc index 3cba66d248..641535f870 100644 --- a/src/main.cc +++ b/src/main.cc @@ -91,7 +91,6 @@ DPM* dpm = 0; int optimize = 0; int do_notice_analysis = 0; int rule_bench = 0; -int print_loaded_scripts = 0; int generate_documentation = 0; SecondaryPath* secondary_path = 0; ConnCompressor* conn_compressor = 0; @@ -130,7 +129,7 @@ const char* bro_dns_fake() { if ( ! getenv("BRO_DNS_FAKE") ) return "off"; - else + else return "on"; } @@ -145,7 +144,6 @@ void usage() fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n"); fprintf(stderr, " -h|--help|-? | command line help\n"); fprintf(stderr, " -i|--iface | read from given interface\n"); - fprintf(stderr, " -l|--print-scripts | print all loaded scripts\n"); fprintf(stderr, " -Z|--doc-scripts | generate documentation for all loaded scripts\n"); fprintf(stderr, " -p|--prefix | add given prefix to policy file resolution\n"); fprintf(stderr, " -r|--readfile | read from given tcpdump file\n"); @@ -440,7 +438,7 @@ int main(int argc, char** argv) opterr = 0; char opts[256]; - safe_strncpy(opts, "B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGHLOPSWdghlvZ", + safe_strncpy(opts, "B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGHLOPSWdghvZ", sizeof(opts)); #ifdef USE_PERFTOOLS @@ -471,10 +469,6 @@ int main(int argc, char** argv) interfaces.append(optarg); break; - case 'l': - print_loaded_scripts = 1; - break; - case 'p': prefixes.append(optarg); break; @@ -666,7 +660,7 @@ int main(int argc, char** argv) // seed the PRNG. We should do this here (but at least Linux, FreeBSD // and Solaris provide /dev/urandom). - if ( (interfaces.length() > 0 || netflows.length() > 0) && + if ( (interfaces.length() > 0 || netflows.length() > 0) && (read_files.length() > 0 || flow_files.length() > 0 )) usage(); @@ -801,7 +795,7 @@ int main(int argc, char** argv) // ### Add support for debug command file. dbg_init_debugger(0); - if ( (flow_files.length() == 0 || read_files.length() == 0) && + if ( (flow_files.length() == 0 || read_files.length() == 0) && (netflows.length() == 0 || interfaces.length() == 0) ) { Val* interfaces_val = internal_val("interfaces"); @@ -965,6 +959,15 @@ int main(int argc, char** argv) if ( override_ignore_checksums ) ignore_checksums = 1; + // Queue events reporting loaded scripts. + for ( std::list::iterator i = files_scanned.begin(); i != files_scanned.end(); i++ ) + { + val_list* vl = new val_list; + vl->append(new StringVal(i->name.c_str())); + vl->append(new Val(i->include_level, TYPE_COUNT)); + mgr.QueueEvent(bro_script_loaded, vl); + } + dpm->PostScriptInit(); reporter->ReportViaEvents(true); diff --git a/src/scan.l b/src/scan.l index 3590cc26fc..8f5fcee1d8 100644 --- a/src/scan.l +++ b/src/scan.l @@ -36,7 +36,6 @@ ptr_compat_int current_depth = 0; int_list if_stack; int line_number = 1; -int include_level = 0; const char* filename = 0; BroDoc* current_reST_doc = 0; static BroDoc* last_reST_doc = 0; @@ -52,10 +51,6 @@ char last_tok[128]; if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \ reporter->Error(fmt("read failed with \"%s\"", strerror(errno))); -// Files we have already scanned (or are in the process of scanning). They -// are tracked by inode number. -static std::list files_scanned; - // reST documents that we've created (or have at least opened so far). std::list docs_generated; @@ -123,10 +118,6 @@ static PList(FileInfo) file_stack; // Returns true if the file is new, false if it's already been scanned. static int load_files_with_prefix(const char* file); -// If print_loaded_files is true, print current filename if we haven't -// reported it already. -static void report_file(); - // ### TODO: columns too - use yyless with '.' action? %} @@ -219,7 +210,6 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) {WS} /* eat whitespace */ \n { - report_file(); ++line_number; ++yylloc.first_line; ++yylloc.last_line; @@ -349,11 +339,13 @@ when return TOK_WHEN; if ( f ) { - ino_t i = get_inode_num(f, full_filename); + ScannedFile sf(get_inode_num(f, full_filename), file_stack.length(), full_filename); + files_scanned.push_back(sf); + fclose(f); delete [] full_filename; - files_scanned.push_back(i); } + else reporter->Error("failed find file associated with @unload %s", new_file); } @@ -566,11 +558,11 @@ static int load_files_with_prefix(const char* orig_file) if ( f ) { ino_t i = get_inode_num(f, full_filename); - std::list::const_iterator it; + std::list::const_iterator it; for ( it = files_scanned.begin(); it != files_scanned.end(); ++it ) { - if ( *it == i ) + if ( it->inode == i ) { fclose(f); delete [] full_filename; @@ -579,7 +571,8 @@ static int load_files_with_prefix(const char* orig_file) } } - files_scanned.push_back(i); + ScannedFile sf(i, file_stack.length(), full_filename); + files_scanned.push_back(sf); if ( g_policy_debug ) { @@ -783,8 +776,6 @@ int yywrap() if ( reporter->Errors() > 0 ) return 1; - --include_level; - if ( ! did_builtin_init && file_stack.length() == 1 ) { // ### This is a gross hack - we know that the first file @@ -901,7 +892,6 @@ FileInfo::FileInfo(string arg_restore_module) restore_module = arg_restore_module; name = ::filename; line = ::line_number; - level = ::include_level; doc = ::current_reST_doc; } @@ -913,7 +903,6 @@ FileInfo::~FileInfo() yy_switch_to_buffer(buffer_state); yylloc.filename = filename = name; yylloc.first_line = yylloc.last_line = line_number = line; - include_level = level; last_reST_doc = current_reST_doc; current_reST_doc = doc; @@ -921,27 +910,6 @@ FileInfo::~FileInfo() current_module = restore_module; } -static void report_file() - { - if ( ! print_loaded_scripts || ! filename ) - return; - - static PList(char) files_reported; - - loop_over_list(files_reported, i) - { - if ( streq(files_reported[i], filename) ) - return; - } - - for ( int i = include_level - 1; i >= 0; --i ) - fprintf(stderr, " "); - fprintf(stderr, "loading %s\n", filename); - - ++include_level; - files_reported.append(copy_string(filename)); - } - static void check_capture_filter_changes() { if ( ! generate_documentation ) diff --git a/testing/btest/Baseline/policy.misc.loaded-scripts/output b/testing/btest/Baseline/policy.misc.loaded-scripts/output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/policy/misc/loaded-scripts.bro b/testing/btest/policy/misc/loaded-scripts.bro new file mode 100644 index 0000000000..775a939196 --- /dev/null +++ b/testing/btest/policy/misc/loaded-scripts.bro @@ -0,0 +1,7 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +event bro_script_loaded(path: string, level: count) +{ + print level, path; +}