From a5632aff4e971b89f216c6a1b0b19fa3ea1a7a73 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Wed, 12 Jan 2011 09:38:13 -0800 Subject: [PATCH 01/23] TCP Reassembler hotfix for conns > 2GB. The TCP Reassembler does not deliver any data to analyzers after the first 2GB due to signed integer overflow (Actually it will deliver again between 4--6GB, etc.) This happens silently, i.e., without content_gap events or Undelivered calls. See Comments in TCP_Reassembler.cc for more details. As a hotfix that seems to work I disabled the seq_to_skip features. It wasn't used by any analyzer or policy script (Note, that seq_to_skip is different from skip_deliveries). See also ticket #348 --- src/Reassem.cc | 4 ++- src/Reassem.h | 2 +- src/TCP_Reassembler.cc | 70 ++++++++++++++++++++++++++++++++++-------- src/TCP_Reassembler.h | 14 ++++++++- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/Reassem.cc b/src/Reassem.cc index c6ec6a3420..51e39ce83d 100644 --- a/src/Reassem.cc +++ b/src/Reassem.cc @@ -195,8 +195,10 @@ void Reassembler::Describe(ODesc* d) const d->Add("reassembler"); } -void Reassembler::Undelivered(int /* up_to_seq */) +void Reassembler::Undelivered(int up_to_seq) { + // TrimToSeq() expects this. + last_reassem_seq = up_to_seq; } DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper, diff --git a/src/Reassem.h b/src/Reassem.h index 0200f8577b..ee70d70b15 100644 --- a/src/Reassem.h +++ b/src/Reassem.h @@ -11,7 +11,7 @@ class DataBlock { public: DataBlock(const u_char* data, int size, int seq, - DataBlock* next, DataBlock* prev); + DataBlock* prev, DataBlock* next); ~DataBlock(); diff --git a/src/TCP_Reassembler.cc b/src/TCP_Reassembler.cc index c6adec2294..e4fd7077c7 100644 --- a/src/TCP_Reassembler.cc +++ b/src/TCP_Reassembler.cc @@ -9,6 +9,30 @@ // Only needed for gap_report events. #include "Event.h" +// Note, sequence numbers are relative. I.e., they start with 1. + +// The Reassembler uses 32 bit ints for keeping track of sequence numbers. +// This means that the seq numbers will become negative once we exceed +// 2 GB of data. The Reassembler seems to mostly work despite negative +// sequence numbers, since seq_delta() will handle them gracefully. +// However, there are a couple of issues. E.g., seq_to_skip doesn't work +// (which is now disabled with an ifdef, since it wasn't used) +// Also, a check in Undelivered() had a problem with negative sequence +// numbers. +// +// There are numerous counters (e.g., number of total bytes, etc.) that are +// incorrect due to overflow too. However, these seem to be for informative +// purposes only, so we currently ignore them. +// +// There might be other problems hidden somewhere, that I haven't discovered +// yet...... +// +// Ideally the Reassembler should start using 64 bit ints for keeping track +// of sequence numbers +// +// Reassem.{cc|h} and other "Reassemblers" that inherit from it (e.g., Frag) +// need to be updated too. + const bool DEBUG_tcp_contents = false; const bool DEBUG_tcp_connection_close = false; const bool DEBUG_tcp_match_undelivered = false; @@ -35,7 +59,9 @@ TCP_Reassembler::TCP_Reassembler(Analyzer* arg_dst_analyzer, deliver_tcp_contents = 0; skip_deliveries = 0; did_EOF = 0; +#ifdef XXX_USE_SEQ_TO_SKIP seq_to_skip = 0; +#endif in_delivery = false; if ( tcp_contents ) @@ -120,7 +146,7 @@ void TCP_Reassembler::Undelivered(int up_to_seq) TCP_Endpoint* endpoint = endp; TCP_Endpoint* peer = endpoint->peer; - if ( up_to_seq <= 2 && tcp_analyzer->IsPartial() ) + if ( up_to_seq <= 2 && tcp_analyzer->IsPartial() ) { // Since it was a partial connection, we faked up its // initial sequence numbers as though we'd seen a SYN. // We've now received the first ack and are getting a @@ -129,7 +155,17 @@ void TCP_Reassembler::Undelivered(int up_to_seq) // (if up_to_seq is 2). The latter can occur when the // first packet we saw instantiating the partial connection // was a keep-alive. So, in either case, just ignore it. - return; + + // TODO: Don't we need to update last_reassm_seq ???? + + if (up_to_seq >=0 ) + // Since seq are currently only 32 bit signed integers, they + // will become negative if a connection has more than 2GB of + // data..... + // Remove the above if and always return here, + // once we're using 64 bit ints + return; + } #if 0 if ( endpoint->FIN_cnt > 0 ) @@ -144,16 +180,20 @@ void TCP_Reassembler::Undelivered(int up_to_seq) if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f Undelivered: up_to_seq=%d, last_reassm=%d, " + DEBUG_MSG("%.6f Undelivered: is_orig=%d up_to_seq=%d, last_reassm=%d, " "endp: FIN_cnt=%d, RST_cnt=%d, " "peer: FIN_cnt=%d, RST_cnt=%d\n", - network_time, up_to_seq, last_reassem_seq, + network_time, is_orig, up_to_seq, last_reassem_seq, endpoint->FIN_cnt, endpoint->RST_cnt, peer->FIN_cnt, peer->RST_cnt); } if ( seq_delta(up_to_seq, last_reassem_seq) <= 0 ) + { + // This should never happen. + internal_error("Calling Undelivered for data that has already been delivered (or has already been marked as undelivered"); return; + } if ( last_reassem_seq == 1 && (endpoint->FIN_cnt > 0 || endpoint->RST_cnt > 0 || @@ -177,9 +217,9 @@ void TCP_Reassembler::Undelivered(int up_to_seq) { if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f Undelivered: seq=%d, len=%d, " + DEBUG_MSG("%.6f Undelivered: is_orig=%d, seq=%d, len=%d, " "skip_deliveries=%d\n", - network_time, last_reassem_seq, + network_time, is_orig, last_reassem_seq, seq_delta(up_to_seq, last_reassem_seq), skip_deliveries); } @@ -376,7 +416,7 @@ void TCP_Reassembler::BlockInserted(DataBlock* start_block) void TCP_Reassembler::Overlap(const u_char* b1, const u_char* b2, int n) { if ( DEBUG_tcp_contents ) - DEBUG_MSG("%.6f TCP contents overlap: %d\n", network_time, n); + DEBUG_MSG("%.6f TCP contents overlap: %d is_orig=%d\n", network_time, n, is_orig); if ( rexmit_inconsistency && memcmp((const void*) b1, (const void*) b2, n) && @@ -419,8 +459,8 @@ int TCP_Reassembler::DataSent(double t, int seq, int len, if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f DataSent: seq=%d upper=%d ack=%d\n", - network_time, seq, upper_seq, ack); + DEBUG_MSG("%.6f DataSent: is_orig=%d seq=%d upper=%d ack=%d\n", + network_time, is_orig, seq, upper_seq, ack); } if ( skip_deliveries ) @@ -477,8 +517,7 @@ void TCP_Reassembler::AckReceived(int seq) // Zero, or negative in sequence-space terms. Nothing to do. return; - bool test_active = - ! skip_deliveries && ! tcp_analyzer->Skipping() && + bool test_active = ! skip_deliveries && ! tcp_analyzer->Skipping() && endp->state == TCP_ENDPOINT_ESTABLISHED && endp->peer->state == TCP_ENDPOINT_ESTABLISHED; @@ -569,7 +608,8 @@ void TCP_Reassembler::CheckEOF() void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) { - if ( seq_delta(seq + len, seq_to_skip) <= 0 ) +#ifdef XXX_USE_SEQ_TO_SKIP + if ( seq_delta(seq + len, seq_to_skip) <= 0 ) return; if ( seq_delta(seq, seq_to_skip) < 0 ) @@ -579,6 +619,7 @@ void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) data += to_skip; seq = seq_to_skip; } +#endif if ( deliver_tcp_contents ) { @@ -603,11 +644,13 @@ void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) in_delivery = true; Deliver(seq, len, data); in_delivery = false; - +#ifdef XXX_USE_SEQ_TO_SKIP if ( seq_delta(seq + len, seq_to_skip) < 0 ) SkipToSeq(seq_to_skip); +#endif } +#ifdef XXX_USE_SEQ_TO_SKIP void TCP_Reassembler::SkipToSeq(int seq) { if ( seq_delta(seq, seq_to_skip) > 0 ) @@ -617,6 +660,7 @@ void TCP_Reassembler::SkipToSeq(int seq) TrimToSeq(seq); } } +#endif int TCP_Reassembler::DataPending() const { diff --git a/src/TCP_Reassembler.h b/src/TCP_Reassembler.h index 3e8426c9fb..e6c9e35d16 100644 --- a/src/TCP_Reassembler.h +++ b/src/TCP_Reassembler.h @@ -6,6 +6,13 @@ #include "Reassem.h" #include "TCP_Endpoint.h" +// The skip_to_seq feature does not work correctly with +// connections >2GB due to use of 32 bit signed ints (see +// comments in TCP_Reassembler.cc) +// Since it's not used by any analyzer or policy script we disable +// it. Could be added back in once we start using 64bit integers. +// #define XXX_USE_SEQ_TO_SKIP + class BroFile; class Connection; class TCP_Analyzer; @@ -60,9 +67,11 @@ public: void MatchUndelivered(int up_to_seq = -1); +#ifdef XXX_USE_SEQ_TO_SKIP // Skip up to seq, as if there's a content gap. // Can be used to skip HTTP data for performance considerations. void SkipToSeq(int seq); +#endif int DataSent(double t, int seq, int len, const u_char* data, bool replaying=true); @@ -85,9 +94,10 @@ public: const TCP_Endpoint* Endpoint() const { return endp; } int IsOrig() const { return endp->IsOrig(); } - +#ifdef XXX_USE_SEQ_TO_SKIP bool IsSkippedContents(int seq, int length) const { return seq + length <= seq_to_skip; } +#endif private: TCP_Reassembler() { } @@ -110,7 +120,9 @@ private: unsigned int did_EOF:1; unsigned int skip_deliveries:1; +#ifdef XXX_USE_SEQ_TO_SKIP int seq_to_skip; +#endif bool in_delivery; BroFile* record_contents_file; // file on which to reassemble contents From 104c7da205189fd060e5c63a0cacb574ea39a32b Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Wed, 9 Feb 2011 15:40:36 -0800 Subject: [PATCH 02/23] Revert "Fix for OS X 10.5 compile error wrt llabs()" This reverts commit 3f6aa735e96fcfd91e8fe187b26b74bf2c82bc9d. Using abs() does not work if the integer is >2^32 (or <2^32). Will add a new fix in next commit. --- cmake/OSSpecific.cmake | 27 +-------------------------- config.h.in | 3 --- src/Val.cc | 4 ---- 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/cmake/OSSpecific.cmake b/cmake/OSSpecific.cmake index b63ce54f6d..03788813c3 100644 --- a/cmake/OSSpecific.cmake +++ b/cmake/OSSpecific.cmake @@ -1,6 +1,3 @@ -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) - if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") # alternate malloc is faster for FreeBSD, but needs more testing # need to add way to set this from the command line @@ -10,28 +7,6 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") set(USE_NMALLOC true) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # The following may have a greater scope than just Darwin - # (i.e. any platform w/ GCC < 4.1.0), but I've only seen - # it on OS X 10.5, which has GCC 4.0.1, so the workaround - # will be stuck here for now. - # - # See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13943 - - check_cxx_source_compiles(" - #include - #include - using namespace std; - int main() { - llabs(1); - return 0; - } - " darwin_llabs_works) - - if (NOT darwin_llabs_works) - # abs() should be used in this case, the long long version should - # exist in the __gnu_cxx namespace - set(DARWIN_NO_LLABS true) - endif () elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(HAVE_LINUX true) @@ -50,7 +25,7 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "irix") elseif (${CMAKE_SYSTEM_NAME} MATCHES "ultrix") list(APPEND CMAKE_C_FLAGS -std1 -g3) list(APPEND CMAKE_CXX_FLAGS -std1 -g3) - + include(CheckCSourceCompiles) check_c_source_compiles(" #include int main() { diff --git a/config.h.in b/config.h.in index 46915563a8..f1405813fc 100644 --- a/config.h.in +++ b/config.h.in @@ -146,6 +146,3 @@ /* Define u_int8_t */ #define u_int8_t @U_INT8_T@ - -/* Whether llabs will be ambiguous in stdlib.h and cstdlib headers */ -#cmakedefine DARWIN_NO_LLABS diff --git a/src/Val.cc b/src/Val.cc index 4519d76f30..4cb9d78023 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -515,11 +515,7 @@ Val* Val::SizeVal() const { switch ( type->InternalType() ) { case TYPE_INTERNAL_INT: -#ifdef DARWIN_NO_LLABS - return new Val(abs(val.int_val), TYPE_COUNT); -#else return new Val(llabs(val.int_val), TYPE_COUNT); -#endif case TYPE_INTERNAL_UNSIGNED: return new Val(val.uint_val, TYPE_COUNT); From 2aae4eaf91693b67eea6eae22138aef89d2e8aee Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Wed, 9 Feb 2011 15:52:32 -0800 Subject: [PATCH 03/23] New fix for OS X 10.5 compile error wrt llabs() --- src/Val.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Val.cc b/src/Val.cc index 4cb9d78023..2a53a32674 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -515,7 +515,12 @@ Val* Val::SizeVal() const { switch ( type->InternalType() ) { case TYPE_INTERNAL_INT: - return new Val(llabs(val.int_val), TYPE_COUNT); + // Return abs value. However abs() only works on ints and llabs + // doesn't work on Mac OS X 10.5. So we do it by hand + if (val.int_val < 0) + return new Val(-val.int_val, TYPE_COUNT); + else + return new Val(val.int_val, TYPE_COUNT); case TYPE_INTERNAL_UNSIGNED: return new Val(val.uint_val, TYPE_COUNT); From 2ced4839e9e459fe21d13271f89220b8ee5194af Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Wed, 9 Feb 2011 15:53:49 -0800 Subject: [PATCH 04/23] Fix for Val constructor with new int64 typedefs. Val::Val had prototypes for int, long, int64, etc. But depending on the architecture some of those might be the same (int64 and long) thus yielding a compile error. Fix: only use int32, int64, etc. for prototype. ints and longs can still be passed, since they will match one of these fixed-width types regardless of platform. Also fix some more compiler warnings with format strings. --- src/SerializationFormat.cc | 8 ++++---- src/Val.h | 24 ++---------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index d49233ec92..55e35eb30e 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -369,25 +369,25 @@ bool XMLSerializationFormat::Write(char v, const char* tag) bool XMLSerializationFormat::Write(uint16 v, const char* tag) { - const char* tmp = fmt("%u", v); + const char* tmp = fmt("%"PRIu16, v); return WriteElem(tag, "uint16", tmp, strlen(tmp)); } bool XMLSerializationFormat::Write(uint32 v, const char* tag) { - const char* tmp = fmt("%u", v); + const char* tmp = fmt("%"PRIu32, v); return WriteElem(tag, "uint32", tmp, strlen(tmp)); } bool XMLSerializationFormat::Write(uint64 v, const char* tag) { - const char* tmp = fmt("%llu", v); + const char* tmp = fmt("%"PRIu64, v); return WriteElem(tag, "uint64", tmp, strlen(tmp)); } bool XMLSerializationFormat::Write(int64 v, const char* tag) { - const char* tmp = fmt("%lld", v); + const char* tmp = fmt("%"PRId64, v); return WriteElem(tag, "int64", tmp, strlen(tmp)); } diff --git a/src/Val.h b/src/Val.h index d21562c907..39be5f0e6a 100644 --- a/src/Val.h +++ b/src/Val.h @@ -87,7 +87,7 @@ public: #endif } - Val(int i, TypeTag t) + Val(int32 i, TypeTag t) { val.int_val = bro_int_t(i); type = base_type(t); @@ -97,27 +97,7 @@ public: #endif } - Val(long i, TypeTag t) - { - val.int_val = bro_int_t(i); - type = base_type(t); - attribs = 0; -#ifdef DEBUG - bound_id = 0; -#endif - } - - Val(unsigned int u, TypeTag t) - { - val.uint_val = bro_uint_t(u); - type = base_type(t); - attribs = 0; -#ifdef DEBUG - bound_id = 0; -#endif - } - - Val(unsigned long u, TypeTag t) + Val(uint32 u, TypeTag t) { val.uint_val = bro_uint_t(u); type = base_type(t); From d6e6d6b650b3331d87ac9940ad170bb53a7d6990 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Wed, 15 Dec 2010 07:58:58 -0800 Subject: [PATCH 05/23] Fixing endianess error in XDR when data is not 4-byte aligned. --- src/XDR.cc | 6 +++--- src/XDR.h | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/XDR.cc b/src/XDR.cc index 4e6a05ff10..9e2074f1ac 100644 --- a/src/XDR.cc +++ b/src/XDR.cc @@ -17,13 +17,13 @@ uint32 extract_XDR_uint32(const u_char*& buf, int& len) return 0; } - uint32 bits32 = XDR_aligned(buf) ? *(uint32*) buf : - ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + // takes care of alignment and endianess differences. + uint32 bits32 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; buf += 4; len -= 4; - return ntohl(bits32); + return bits32; } double extract_XDR_uint64_as_double(const u_char*& buf, int& len) diff --git a/src/XDR.h b/src/XDR.h index 070e13ee6c..047acd90f5 100644 --- a/src/XDR.h +++ b/src/XDR.h @@ -10,11 +10,6 @@ #include "util.h" -inline int XDR_aligned(const u_char* buf) - { - return (((unsigned long) buf) & 0x3) == 0; - } - extern uint32 extract_XDR_uint32(const u_char*& buf, int& len); extern double extract_XDR_uint64_as_double(const u_char*& buf, int& len); extern double extract_XDR_time(const u_char*& buf, int& len); From 72454c230b19f799327ea9da373b034bb01a644c Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Thu, 9 Dec 2010 18:29:47 -0800 Subject: [PATCH 06/23] Add support for enum with explicit enumerator values. * Adding support for enums with explicit enumerator values (see doc below) to bifcl and policy layer. * Bifcl: remove (partially written) output files on error and do a nice exit(1) instead of harsh abort() on parse errors. * CMakeText: if bifcl fails, remove output files (failsafe, in case bifcl fails to clean up after itself). Enum description ---------------- Enum's are supported in .bif and .bro scripts. An enum in a bif will become available in the event engine and the policy layer. Enums are "C-style". The first element in an enum will have a value of 0, the next value will be 1, etc. It is possible to assign an enumerator value to an element. If next element does not have an explicit value, its values will be the value of the last element + 1 Example:: type foo: enum { BAR_A, # value will be 0 BAR_B, # value will be 1 BAR_C = 10, # value will be 10 BAR_D, # value will be 11 }; Enumerator values can only by positive integer literals. The literals can be specified in (0x....), but not in octal (bro policy layer limitation). So, do not use 0123 as value in bifs! Each enumerator value can only be used once per enum (C allows to use the same value multiple times). This makes reverse mapping from value to name (e.g., in %s format strings) unambigious. This is enforced in by the policy script. Enums can be redef'ed, i.e., extended. Enumerator values will continue to increment. If there are multiple redefs in different policy scripts, then name <-> value mappings will obviously depend on the order in which scripts are loaded (which might not be obvious). Example:: redef enum foo += { BAR_E, # value will be 12 BAR_F = 5, # value will be 5 BAR_G, # value will be 6 }; --- src/CMakeLists.txt | 2 +- src/Type.cc | 54 +++++++++-------------- src/Type.h | 27 ++++++------ src/builtin-func.l | 84 ++++++++++++++++++++++++++++------- src/builtin-func.y | 16 +++++-- src/parse.y | 108 ++++++++++++++++++++++++++++++--------------- 6 files changed, 188 insertions(+), 103 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9aab94cc6c..856e8cad4d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -101,7 +101,7 @@ macro(BIF_TARGET bifInput) get_bif_output_files(${bifInput} bifOutputs) add_custom_command(OUTPUT ${bifOutputs} COMMAND bifcl - ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} + ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} || (rm -f ${bifOutputs} && exit 1) DEPENDS ${bifInput} COMMENT "[BIFCL] Processing ${bifInput}" ) diff --git a/src/Type.cc b/src/Type.cc index 55794dfce5..cb595a4428 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1082,10 +1082,9 @@ bool FileType::DoUnserialize(UnserialInfo* info) return yield != 0; } -EnumType::EnumType(bool arg_is_export) +EnumType::EnumType() : BroType(TYPE_ENUM) { - is_export = arg_is_export; counter = 0; } @@ -1095,9 +1094,18 @@ EnumType::~EnumType() delete [] iter->first; } -int EnumType::AddName(const string& module_name, const char* name) +bro_int_t EnumType::AddName(const string& module_name, const char* name, bool is_export) { - ID* id = lookup_ID(name, module_name.c_str()); + return AddName(module_name, name, counter, is_export); + } + +bro_int_t EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export) + { + ID *id; + if ( Lookup(val) ) + return -1; + + id = lookup_ID(name, module_name.c_str()); if ( ! id ) { id = install_ID(name, module_name.c_str(), true, is_export); @@ -1105,32 +1113,15 @@ int EnumType::AddName(const string& module_name, const char* name) id->SetEnumConst(); } else - { - debug_msg("identifier already exists: %s\n", name); - return -1; - } + return -1; string fullname = make_full_var_name(module_name.c_str(), name); - names[copy_string(fullname.c_str())] = counter; - return counter++; + names[copy_string(fullname.c_str())] = val; + counter = val + 1; + return val; } -int EnumType::AddNamesFrom(const string& module_name, EnumType* et) - { - int last_added = counter; - for ( NameMap::iterator iter = et->names.begin(); - iter != et->names.end(); ++iter ) - { - ID* id = lookup_ID(iter->first, module_name.c_str()); - id->SetType(this->Ref()); - names[copy_string(id->Name())] = counter; - last_added = counter++; - } - - return last_added; - } - -int EnumType::Lookup(const string& module_name, const char* name) +bro_int_t EnumType::Lookup(const string& module_name, const char* name) { NameMap::iterator pos = names.find(make_full_var_name(module_name.c_str(), name).c_str()); @@ -1141,7 +1132,7 @@ int EnumType::Lookup(const string& module_name, const char* name) return pos->second; } -const char* EnumType::Lookup(int value) +const char* EnumType::Lookup(bro_int_t value) { for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter ) @@ -1157,9 +1148,7 @@ bool EnumType::DoSerialize(SerialInfo* info) const { DO_SERIALIZE(SER_ENUM_TYPE, BroType); - // I guess we don't really need both ... - if ( ! (SERIALIZE(counter) && SERIALIZE((unsigned int) names.size()) && - SERIALIZE(is_export)) ) + if ( ! (SERIALIZE(counter) && SERIALIZE((unsigned int) names.size())) ) return false; for ( NameMap::const_iterator iter = names.begin(); @@ -1178,14 +1167,13 @@ bool EnumType::DoUnserialize(UnserialInfo* info) unsigned int len; if ( ! UNSERIALIZE(&counter) || - ! UNSERIALIZE(&len) || - ! UNSERIALIZE(&is_export) ) + ! UNSERIALIZE(&len) ) return false; while ( len-- ) { const char* name; - int val; + bro_int_t val; if ( ! (UNSERIALIZE_STR(&name, 0) && UNSERIALIZE(&val)) ) return false; diff --git a/src/Type.h b/src/Type.h index ff4d3df9e6..7865946a1d 100644 --- a/src/Type.h +++ b/src/Type.h @@ -452,31 +452,30 @@ protected: class EnumType : public BroType { public: - EnumType(bool arg_is_export); + EnumType(); ~EnumType(); // The value of this name is next counter value, which is returned. - // A return value of -1 means that the identifier already existed - // (and thus could not be used). - int AddName(const string& module_name, const char* name); + // A return value of -1 means that the identifier or the counter values + // already existed (and thus could not be used). + bro_int_t AddName(const string& module_name, const char* name, bool is_export); - // Add in names from the suppled EnumType; the return value is - // the value of the last enum added. - int AddNamesFrom(const string& module_name, EnumType* et); + // The value of this name is set to val, which is return. The counter will + // be updated, so the next name (without val) will have val+1 + // A return value of -1 means that the identifier or val + // already existed (and thus could not be used). + bro_int_t AddName(const string& module_name, const char* name, bro_int_t val, bool is_export); // -1 indicates not found. - int Lookup(const string& module_name, const char* name); - const char* Lookup(int value); // Returns 0 if not found + bro_int_t Lookup(const string& module_name, const char* name); + const char* Lookup(bro_int_t value); // Returns 0 if not found protected: - EnumType() {} - DECLARE_SERIAL(EnumType) - typedef std::map< const char*, int, ltstr > NameMap; + typedef std::map< const char*, bro_int_t, ltstr > NameMap; NameMap names; - int counter; - bool is_export; + bro_int_t counter; }; class VectorType : public BroType { diff --git a/src/builtin-func.l b/src/builtin-func.l index ca7923b852..cbd925819b 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -2,6 +2,7 @@ // $Id: builtin-func.l 6015 2008-07-23 05:42:37Z vern $ #include +#include #include "bif_arg.h" #include "bif_parse.h" @@ -29,6 +30,7 @@ int check_c_mode(int t) WS [ \t]+ ID [A-Za-z_][A-Za-z_0-9]* ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) +INT [[:digit:]]+ %option nodefault @@ -78,6 +80,11 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) "T" yylval.val = 1; return TOK_BOOL; "F" yylval.val = 0; return TOK_BOOL; +{INT} { + yylval.str = copy_string(yytext); + return TOK_INT; + } + {ID} { yylval.str = copy_string(yytext); return TOK_ID; @@ -111,6 +118,7 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) } %% + int yywrap() { yy_delete_buffer(YY_CURRENT_BUFFER); @@ -120,13 +128,21 @@ int yywrap() extern int yyparse(); char* input_filename = 0; -FILE* fp_bro_init; -FILE* fp_func_def; -FILE* fp_func_h; -FILE* fp_func_init; -FILE* fp_netvar_h; -FILE* fp_netvar_def; -FILE* fp_netvar_init; +FILE* fp_bro_init = 0; +FILE* fp_func_def = 0; +FILE* fp_func_h = 0; +FILE* fp_func_init = 0; +FILE* fp_netvar_h = 0; +FILE* fp_netvar_def = 0; +FILE* fp_netvar_init = 0; + + +void remove_file(const char *surfix); +void err_exit(void); +FILE* open_output_file(const char* surfix); +void close_if_open(FILE **fpp); +void close_all_output_files(void); + FILE* open_output_file(const char* surfix) { @@ -137,12 +153,13 @@ FILE* open_output_file(const char* surfix) if ( (fp = fopen(fn, "w")) == NULL ) { fprintf(stderr, "Error: cannot open file: %s\n", fn); - exit(1); + err_exit(); } return fp; } + int main(int argc, char* argv[]) { for ( int i = 1; i < argc; i++ ) @@ -156,6 +173,7 @@ int main(int argc, char* argv[]) if ( (fp_input = fopen(input_filename, "r")) == NULL ) { fprintf(stderr, "Error: cannot open file: %s\n", input_filename); + /* no output files open. can simply exit */ exit(1); } @@ -174,12 +192,48 @@ int main(int argc, char* argv[]) yyparse(); fclose(fp_input); - fclose(fp_bro_init); - fclose(fp_func_h); - fclose(fp_func_def); - fclose(fp_func_init); - fclose(fp_netvar_h); - fclose(fp_netvar_def); - fclose(fp_netvar_init); + close_all_output_files(); + } } + +void close_if_open(FILE **fpp) + { + if (*fpp) + fclose(*fpp); + *fpp = NULL; + } + +void close_all_output_files(void) + { + close_if_open(&fp_bro_init); + close_if_open(&fp_func_h); + close_if_open(&fp_func_def); + close_if_open(&fp_func_init); + close_if_open(&fp_netvar_h); + close_if_open(&fp_netvar_def); + close_if_open(&fp_netvar_init); + } + +void remove_file(const char *surfix) + { + char fn[1024]; + + snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix); + unlink(fn); + } + +void err_exit(void) + { + close_all_output_files(); + /* clean up. remove all output files we've generated so far */ + remove_file("bro"); + remove_file("func_h"); + remove_file("func_def"); + remove_file("func_init"); + remove_file("netvar_h"); + remove_file("netvar_def"); + remove_file("netvar_init"); + exit(1); + } + diff --git a/src/builtin-func.y b/src/builtin-func.y index 268288bc39..b3db17f82a 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -158,11 +158,11 @@ void print_event_c_body(FILE *fp) %token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE %token TOK_ARGS TOK_ARG TOK_ARGC %token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT -%token TOK_ATOM TOK_C_TOKEN +%token TOK_ATOM TOK_INT TOK_C_TOKEN %left ',' ':' -%type TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR opt_ws +%type TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR TOK_INT opt_ws %type TOK_ATOM TOK_BOOL %union { @@ -257,6 +257,11 @@ enum_list: enum_list TOK_ID opt_ws ',' opt_ws fprintf(fp_bro_init, "%s%s,%s", $2, $3, $5); fprintf(fp_netvar_h, "\t%s,\n", $2); } + | enum_list TOK_ID opt_ws '=' opt_ws TOK_INT opt_ws ',' opt_ws + { + fprintf(fp_bro_init, "%s = %s%s,%s", $2, $6, $7, $9); + fprintf(fp_netvar_h, "\t%s = %s,\n", $2, $6); + } | /* nothing */ ; @@ -543,6 +548,9 @@ c_atom: TOK_ID { fprintf(fp_func_def, "%s", $1); } | TOK_ATOM { fprintf(fp_func_def, "%c", $1); } + | TOK_INT + { fprintf(fp_func_def, "%s", $1); } + ; opt_ws: opt_ws TOK_WS @@ -566,6 +574,7 @@ extern char* yytext; extern char* input_filename; extern int line_number; const char* decl_name; +void err_exit(void); void print_msg(const char msg[]) { @@ -605,7 +614,6 @@ int yyerror(const char msg[]) { print_msg(msg); - abort(); - exit(1); + err_exit(); return 0; } diff --git a/src/parse.y b/src/parse.y index 82ee3cadfb..4338f6d788 100644 --- a/src/parse.y +++ b/src/parse.y @@ -51,7 +51,7 @@ %type expr init anonymous_function %type event %type stmt stmt_list func_body for_head -%type type opt_type refined_type enum_id_list +%type type opt_type refined_type enum_body %type func_hdr func_params %type type_list %type type_decl formal_args_decl @@ -104,6 +104,29 @@ bool in_debug = false; bool resolving_global_ID = false; ID* func_id = 0; +EnumType *cur_enum_type = 0; + +static void parser_new_enum (void) + { + /* starting a new enum definition. */ + assert(cur_enum_type == NULL); + cur_enum_type = new EnumType(); + } +static void parser_redef_enum (ID *id) + { + /* redef an enum. id points to the enum to be redefined. + let cur_enum_type point to it */ + assert(cur_enum_type == NULL); + if ( ! id->Type() ) + id->Error("unknown identifier"); + else + { + cur_enum_type = id->Type()->AsEnumType(); + if ( ! cur_enum_type ) + id->Error("not an enum"); + } + } + %} %union { @@ -546,27 +569,52 @@ single_pattern: { $$ = $3; } ; -enum_id_list: - TOK_ID +enum_body: + enum_body_list opt_comma { - set_location(@1); - - EnumType* et = new EnumType(is_export); - if ( et->AddName(current_module, $1) < 0 ) - error("identifier in enumerated type definition already exists"); - $$ = et; - } - - | enum_id_list ',' TOK_ID - { - set_location(@1, @3); - - if ( $1->AsEnumType()->AddName(current_module, $3) < 1 ) - error("identifier in enumerated type definition already exists"); - $$ = $1; + $$ = cur_enum_type; + cur_enum_type = NULL; } ; +enum_body_list: + enum_body_elem /* No action */ + | enum_body_list ',' enum_body_elem /* no action */ + ; + +enum_body_elem: + /* TODO: We could also define this as TOK_ID '=' expr, (or + TOK_ID '=' = TOK_ID) so that we can return more descriptive + error messages if someboy tries to use constant variables as + enumerator. + */ + TOK_ID '=' TOK_CONSTANT + { + set_location(@1, @3); + assert(cur_enum_type); + if ($3->Type()->Tag() != TYPE_COUNT) + error("enumerator is not a count constant"); + if ( cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export) < 0 ) + error("identifier or enumerator value in enumerated type definition already exists"); + } + | TOK_ID '=' '-' TOK_CONSTANT + { + /* We only accept counts as enumerator, but we want to return a nice + error message if users tries to use a negative integer (will also + catch other cases, but that's fine) + */ + error("enumerator is not a count constant"); + } + | TOK_ID + { + set_location(@1); + assert(cur_enum_type); + if ( cur_enum_type->AddName(current_module, $1, is_export) < 0 ) + error("identifier or enumerator value in enumerated type definition already exists"); + } + ; + + type: TOK_BOOL { set_location(@1); @@ -668,10 +716,10 @@ type: $$ = 0; } - | TOK_ENUM '{' enum_id_list opt_comma '}' + | TOK_ENUM '{' { parser_new_enum(); } enum_body '}' { - set_location(@1, @4); - $$ = $3; + set_location(@1, @5); + $$ = $4; } | TOK_LIST @@ -801,21 +849,9 @@ decl: | TOK_REDEF global_id opt_type init_class opt_init opt_attr ';' { add_global($2, $3, $4, $5, $6, VAR_REDEF); } - | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO - '{' enum_id_list opt_comma '}' ';' - { - if ( ! $3->Type() ) - $3->Error("unknown identifier"); - else - { - EnumType* add_to = $3->Type()->AsEnumType(); - if ( ! add_to ) - $3->Error("not an enum"); - else - add_to->AddNamesFrom(current_module, - $6->AsEnumType()); - } - } + | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO + '{' { parser_redef_enum($3); } enum_body '}' ';' + { /* no action */ } | TOK_TYPE global_id ':' refined_type opt_attr ';' { From fdaeea0ea923d7ff9c29a0cea5086ffd039b85e6 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Sat, 11 Dec 2010 11:57:27 -0800 Subject: [PATCH 07/23] enum type: don't allow mixing of explicit value and auto-increment. Updated enum type. New description: Enum's are supported in .bif and .bro scripts. An enum in a bif will become available in the event engine and the policy layer. It is possible to assign an explicit value to an enum enumerator element, or the enum type can automatically assign values. However, the styles cannot be mixed. If automatic assignement is used, the first element will have a value of 0, the next will have a value of 1, etc. Enum type variables and identifiers can be formated using the "%s" format specifier, in which case the symbolic name will be printed. If the "%d" format specifier is used, the numerical value is printed. Example automatic assignment: type foo: enum { BAR_A, # value will be 0 BAR_B, # value will be 1 BAR_C, # value will be 2 }; Example with explicit assignment: type foobar: enum { BAR_X = 10, # value will be 10 BAR_Y = 23, # value will be 23 BAR_Z = 42, # value will be 42 }; Enumerator values can only by positive integer literals. The literals can be specified in (0x....), but not in octal (bro policy layer limitation). So, do not use 0123 as value in bifs! Each enumerator value can only be used once per enum (C allows to use the same value multiple times). All these restrictions are enforced by the policy script layer and not the bif compiler! Enums can be redef'ed, i.e., extended. If the enum is automatic increment assignment, then the value will continue to increment. If the enum uses explicit assignment, then the redef need to use explicit assignments as well. Example 1:: redef enum foo += { BAR_D, # value will be 3 BAR_E, # value will be 4 BAR_F, # value will be 5 }; Example 2:: redef enum foobar += { BAR_W = 100, }; --- src/Type.cc | 41 ++++++++++++++++++++++++++++++++++------- src/Type.h | 22 +++++++++++++--------- src/parse.y | 10 +++++----- 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/Type.cc b/src/Type.cc index cb595a4428..99debc3c9c 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1094,16 +1094,42 @@ EnumType::~EnumType() delete [] iter->first; } -bro_int_t EnumType::AddName(const string& module_name, const char* name, bool is_export) +// Note, we don't use Error() and SetError(( for EnumType because EnumTypes can +// be redefined, the location associated with it is ill-defined and might result +// in error messaging with confusing line numbers. +void EnumType::AddName(const string& module_name, const char* name, bool is_export) + { + /* implicit, auto-increment */ + if ( counter < 0) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + return; + } + AddNameInternal(module_name, name, counter, is_export); + counter++; + } + +void EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export) { - return AddName(module_name, name, counter, is_export); + /* explicit value specified */ + error_t rv; + if ( counter > 0 ) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + return; + } + counter = -1; + AddNameInternal(module_name, name, val, is_export); } -bro_int_t EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export) +void EnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export) { ID *id; if ( Lookup(val) ) - return -1; + { + error("enumerator value in enumerated type definition already exists"); + return; + } id = lookup_ID(name, module_name.c_str()); if ( ! id ) @@ -1113,12 +1139,13 @@ bro_int_t EnumType::AddName(const string& module_name, const char* name, bro_int id->SetEnumConst(); } else - return -1; + { + error("identifier or enumerator value in enumerated type definition already exists"); + return; + } string fullname = make_full_var_name(module_name.c_str(), name); names[copy_string(fullname.c_str())] = val; - counter = val + 1; - return val; } bro_int_t EnumType::Lookup(const string& module_name, const char* name) diff --git a/src/Type.h b/src/Type.h index 7865946a1d..dca122eadf 100644 --- a/src/Type.h +++ b/src/Type.h @@ -455,16 +455,12 @@ public: EnumType(); ~EnumType(); - // The value of this name is next counter value, which is returned. - // A return value of -1 means that the identifier or the counter values - // already existed (and thus could not be used). - bro_int_t AddName(const string& module_name, const char* name, bool is_export); + // The value of this name is next counter value. The counter is incremented + void AddName(const string& module_name, const char* name, bool is_export); - // The value of this name is set to val, which is return. The counter will - // be updated, so the next name (without val) will have val+1 - // A return value of -1 means that the identifier or val - // already existed (and thus could not be used). - bro_int_t AddName(const string& module_name, const char* name, bro_int_t val, bool is_export); + // The value of this name is set to val. The counter will + // be set to -1 to indicate that we are assigning explicit values + void AddName(const string& module_name, const char* name, bro_int_t val, bool is_export); // -1 indicates not found. bro_int_t Lookup(const string& module_name, const char* name); @@ -473,8 +469,16 @@ public: protected: DECLARE_SERIAL(EnumType) + void AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export); + typedef std::map< const char*, bro_int_t, ltstr > NameMap; NameMap names; + // counter is initialized to 0 and incremented on every implicit + // auto-increment name that gets added (thus its > 0 if auto-increment + // is used). + // If an explicit value is specified, the counter is set to -1 + // This way counter can be used to prevent mixing of auto-increment + // and explicit enumerator specification bro_int_t counter; }; diff --git a/src/parse.y b/src/parse.y index 4338f6d788..e9de07eb8f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -594,8 +594,8 @@ enum_body_elem: assert(cur_enum_type); if ($3->Type()->Tag() != TYPE_COUNT) error("enumerator is not a count constant"); - if ( cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export) < 0 ) - error("identifier or enumerator value in enumerated type definition already exists"); + else + cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export); } | TOK_ID '=' '-' TOK_CONSTANT { @@ -609,8 +609,7 @@ enum_body_elem: { set_location(@1); assert(cur_enum_type); - if ( cur_enum_type->AddName(current_module, $1, is_export) < 0 ) - error("identifier or enumerator value in enumerated type definition already exists"); + cur_enum_type->AddName(current_module, $1, is_export); } ; @@ -716,9 +715,10 @@ type: $$ = 0; } - | TOK_ENUM '{' { parser_new_enum(); } enum_body '}' + | TOK_ENUM '{' { set_location(@1); parser_new_enum(); } enum_body '}' { set_location(@1, @5); + $4->UpdateLocationEndInfo(@5); $$ = $4; } From a9f28fab749452bf7b056b9a93c1d1f2f4495ee5 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 17 Dec 2010 13:20:38 -0800 Subject: [PATCH 08/23] Minor tweaks for bif language. * Bif language: Can now specify hex constants as explicit enumerators. * Bifcl output files new also depend on the bifcl binary. --- src/CMakeLists.txt | 1 + src/builtin-func.l | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 856e8cad4d..3b371e1cd7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,6 +103,7 @@ macro(BIF_TARGET bifInput) COMMAND bifcl ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} || (rm -f ${bifOutputs} && exit 1) DEPENDS ${bifInput} + DEPENDS bifcl COMMENT "[BIFCL] Processing ${bifInput}" ) list(APPEND ALL_BIF_OUTPUTS ${bifOutputs}) diff --git a/src/builtin-func.l b/src/builtin-func.l index cbd925819b..aa5a281856 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -30,7 +30,8 @@ int check_c_mode(int t) WS [ \t]+ ID [A-Za-z_][A-Za-z_0-9]* ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) -INT [[:digit:]]+ +D [[:digit:]]+ +HEX [0-9a-fA-F]+ %option nodefault @@ -80,11 +81,17 @@ INT [[:digit:]]+ "T" yylval.val = 1; return TOK_BOOL; "F" yylval.val = 0; return TOK_BOOL; -{INT} { +{D} { yylval.str = copy_string(yytext); return TOK_INT; } +"0x"{HEX} { + yylval.str = copy_string(yytext); + return TOK_INT; + } + + {ID} { yylval.str = copy_string(yytext); return TOK_ID; From 1e2aa14a0234f7bc8f7182035182ee2c2370ba57 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 17 Dec 2010 13:42:27 -0800 Subject: [PATCH 09/23] Bif: add record type declaration. One can now declare (but not define) a record type in bif: type : record; This adds the netvar glue so that the event engine knows about the type. One still has to define the type in bro.init. Would be nice, if we could just define the record type here and then copy to the .bif.bro file, but type delcarations in bro can be quite powerful. Don't know whether it's worth it extend the bif-language to be able to handle that all.... Or we just support a simple form of record type definitions The type has be called in bro.init and it will be availabe as a RecordType * rectype_ in the event engine. TODO: add other types (tables, sets) --- src/builtin-func.l | 2 ++ src/builtin-func.y | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/builtin-func.l b/src/builtin-func.l index aa5a281856..5d07a18fdb 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -68,6 +68,8 @@ HEX [0-9a-fA-F]+ "const" return check_c_mode(TOK_CONST); "enum" return check_c_mode(TOK_ENUM); "declare" return check_c_mode(TOK_DECLARE); +"type" return check_c_mode(TOK_TYPE); +"record" return check_c_mode(TOK_RECORD); "@ARG@" return TOK_ARG; "@ARGS@" return TOK_ARGS; diff --git a/src/builtin-func.y b/src/builtin-func.y index b3db17f82a..3d914e66d6 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -155,6 +155,7 @@ void print_event_c_body(FILE *fp) %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG %token TOK_BOOL %token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM TOK_DECLARE +%token TOK_TYPE TOK_RECORD %token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE %token TOK_ARGS TOK_ARG TOK_ARGC %token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT @@ -202,6 +203,7 @@ definition: event_def | enum_def | const_def | declare_def + | type_def ; declare_def: TOK_DECLARE opt_ws TOK_ENUM opt_ws TOK_ID opt_ws ';' @@ -210,6 +212,26 @@ declare_def: TOK_DECLARE opt_ws TOK_ENUM opt_ws TOK_ID opt_ws ';' } ; + // XXX: Add the netvar glue so that the event engine knows about + // the type. One still has to define the type in bro.init. + // Would be nice, if we could just define the record type here + // and then copy to the .bif.bro file, but type delcarations in + // bro can be quite powerful. Don't know whether it's worth it + // extend the bif-language to be able to handle that all.... + // Or we just support a simple form of record type definitions + // TODO: add other types (tables, sets) +type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws TOK_RECORD opt_ws ';' + { + fprintf(fp_netvar_h, + "extern RecordType* rectype_%s;\n", $3); + fprintf(fp_netvar_def, + "RecordType* rectype_%s;\n", $3); + fprintf(fp_netvar_init, + "\trectype_%s = internal_type(\"%s\")->AsRecordType();\n", + $3, $3); + } + ; + event_def: event_prefix opt_ws plain_head opt_attr end_of_head ';' { print_event_c_prototype(fp_func_h); From 43a84866a014c67fe140d15949bf4b8e785f11c3 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Thu, 10 Feb 2011 13:49:09 -0800 Subject: [PATCH 10/23] Remove unused and unnecessary "declare enum" from bifcl --- src/bif_arg.cc | 4 ---- src/builtin-func.l | 1 - src/builtin-func.y | 11 +---------- src/event.bif | 5 ----- src/portmap-analyzer.pac | 2 +- 5 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/bif_arg.cc b/src/bif_arg.cc index 2befed495a..9ef1594fd8 100644 --- a/src/bif_arg.cc +++ b/src/bif_arg.cc @@ -24,7 +24,6 @@ static struct { }; extern const char* arg_list_name; -extern set enum_types; BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) { @@ -45,9 +44,6 @@ BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str) type = i; type_str = ""; } - - if ( enum_types.find(type_str) != enum_types.end() ) - type = TYPE_ENUM; } void BuiltinFuncArg::PrintBro(FILE* fp) diff --git a/src/builtin-func.l b/src/builtin-func.l index 5d07a18fdb..14b0eb52a6 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -67,7 +67,6 @@ HEX [0-9a-fA-F]+ "event" return check_c_mode(TOK_EVENT); "const" return check_c_mode(TOK_CONST); "enum" return check_c_mode(TOK_ENUM); -"declare" return check_c_mode(TOK_DECLARE); "type" return check_c_mode(TOK_TYPE); "record" return check_c_mode(TOK_RECORD); diff --git a/src/builtin-func.y b/src/builtin-func.y index 3d914e66d6..44d63ad5db 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -67,9 +67,6 @@ extern const char* decl_name; int var_arg; // whether the number of arguments is variable std::vector args; -// enum types declared by "declare enum " -set enum_types; - extern int yyerror(const char[]); extern int yywarn(const char msg[]); extern int yylex(); @@ -154,7 +151,7 @@ void print_event_c_body(FILE *fp) %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG %token TOK_BOOL -%token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM TOK_DECLARE +%token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM %token TOK_TYPE TOK_RECORD %token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE %token TOK_ARGS TOK_ARG TOK_ARGC @@ -202,15 +199,9 @@ definition: event_def | c_code_segment | enum_def | const_def - | declare_def | type_def ; -declare_def: TOK_DECLARE opt_ws TOK_ENUM opt_ws TOK_ID opt_ws ';' - { - enum_types.insert($5); - } - ; // XXX: Add the netvar glue so that the event engine knows about // the type. One still has to define the type in bro.init. diff --git a/src/event.bif b/src/event.bif index 3171b02dde..270f1b0d0b 100644 --- a/src/event.bif +++ b/src/event.bif @@ -1,10 +1,5 @@ # $Id: event.bif 6942 2009-11-16 03:54:08Z vern $ -# Declare to bifcl the following types as enum types. -declare enum dce_rpc_ptype; -declare enum dce_rpc_if_id; -declare enum rpc_status; - event bro_init%(%); event bro_done%(%); diff --git a/src/portmap-analyzer.pac b/src/portmap-analyzer.pac index 1e7921a9ff..6ad03f23d4 100644 --- a/src/portmap-analyzer.pac +++ b/src/portmap-analyzer.pac @@ -150,7 +150,7 @@ function PortmapCallFailed(connection: RPC_Conn, status: EnumRPCStatus): bool %{ // BroEnum::rpc_status st = static_cast(status); - BroEnum::rpc_status st = (BroEnum::rpc_status) status; + Val *st = new EnumVal((BroEnum::rpc_status) status, enum_rpc_status); switch ( call->proc() ) { case PMAPPROC_NULL: From 9c39abffef7d6800f6b62549a0fe506bf258d26b Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Thu, 10 Feb 2011 14:11:33 -0800 Subject: [PATCH 11/23] Use namespaces for NetVar type pointers. Enums defined in bifs and records declared in bifs are now available in the C++ layer in namespaces (before they were in the global namespace with enum_* and rectype_* prefixes). Namespaces are now BroTypePtr::Enum:: and BroTypePtr::Record:: --- src/DCE_RPC.cc | 4 ++-- src/Portmap.cc | 2 +- src/builtin-func.y | 12 ++++++------ src/portmap-analyzer.pac | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/DCE_RPC.cc b/src/DCE_RPC.cc index 62f7806c51..5b5b1b0e8a 100644 --- a/src/DCE_RPC.cc +++ b/src/DCE_RPC.cc @@ -234,7 +234,7 @@ void DCE_RPC_Session::DeliverPDU(int is_orig, int len, const u_char* data) val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new Val(is_orig, TYPE_BOOL)); - vl->append(new EnumVal(data[2], enum_dce_rpc_ptype)); + vl->append(new EnumVal(data[2], BroTypePtr::Enum::dce_rpc_ptype)); vl->append(new StringVal(len, (const char*) data)); analyzer->ConnectionEvent(dce_rpc_message, vl); @@ -296,7 +296,7 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new StringVal(if_uuid.to_string())); - // vl->append(new EnumVal(if_id, enum_dce_rpc_if_id)); + // vl->append(new EnumVal(if_id, BroTypePtr::Enum::dce_rpc_if_id)); analyzer->ConnectionEvent(dce_rpc_bind, vl); } diff --git a/src/Portmap.cc b/src/Portmap.cc index af9383297f..46d79b712c 100644 --- a/src/Portmap.cc +++ b/src/Portmap.cc @@ -288,7 +288,7 @@ void PortmapperInterp::Event(EventHandlerPtr f, Val* request, int status, Val* r } else { - vl->append(new EnumVal(status, enum_rpc_status)); + vl->append(new EnumVal(status, BroTypePtr::Enum::rpc_status)); if ( request ) vl->append(request); } diff --git a/src/builtin-func.y b/src/builtin-func.y index 44d63ad5db..fafcdea76a 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -214,11 +214,11 @@ definition: event_def type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws TOK_RECORD opt_ws ';' { fprintf(fp_netvar_h, - "extern RecordType* rectype_%s;\n", $3); + "namespace BroTypePtr { namespace Record { extern RecordType* %s; } }\n", $3); fprintf(fp_netvar_def, - "RecordType* rectype_%s;\n", $3); + "namespace BroTypePtr { namespace Record { RecordType* %s; } }\n", $3); fprintf(fp_netvar_init, - "\trectype_%s = internal_type(\"%s\")->AsRecordType();\n", + "\tBroTypePtr::Record::%s = internal_type(\"%s\")->AsRecordType();\n", $3, $3); } ; @@ -247,11 +247,11 @@ enum_def: enum_def_1 enum_list TOK_RPB // Now generate the netvar's. fprintf(fp_netvar_h, - "extern EnumType* enum_%s;\n", decl_name); + "namespace BroTypePtr { namespace Enum { extern EnumType* %s;\n } }", decl_name); fprintf(fp_netvar_def, - "EnumType* enum_%s;\n", decl_name); + "namespace BroTypePtr { namespace Enum { EnumType* %s; } }\n", decl_name); fprintf(fp_netvar_init, - "\tenum_%s = internal_type(\"%s\")->AsEnumType();\n", + "\tBroTypePtr::Enum::%s = internal_type(\"%s\")->AsEnumType();\n", decl_name, decl_name); } ; diff --git a/src/portmap-analyzer.pac b/src/portmap-analyzer.pac index 6ad03f23d4..3c7b00cd32 100644 --- a/src/portmap-analyzer.pac +++ b/src/portmap-analyzer.pac @@ -150,7 +150,7 @@ function PortmapCallFailed(connection: RPC_Conn, status: EnumRPCStatus): bool %{ // BroEnum::rpc_status st = static_cast(status); - Val *st = new EnumVal((BroEnum::rpc_status) status, enum_rpc_status); + Val *st = new EnumVal(status, BroTypePtr::Enum::rpc_status); switch ( call->proc() ) { case PMAPPROC_NULL: From 600e3b5214da15dc573cf99db7c9f69d9132a898 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Thu, 10 Feb 2011 15:09:25 -0800 Subject: [PATCH 12/23] Remove leftovers from removing "declare enum" from bifcl --- src/bif_arg.cc | 12 +----------- src/bif_type.def | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/bif_arg.cc b/src/bif_arg.cc index 9ef1594fd8..5900c117eb 100644 --- a/src/bif_arg.cc +++ b/src/bif_arg.cc @@ -71,21 +71,11 @@ void BuiltinFuncArg::PrintCArg(FILE* fp, int n) { const char* ctype = builtin_func_arg_type[type].c_type; char buf[1024]; - if ( type == TYPE_ENUM ) - { - snprintf(buf, sizeof(buf), - builtin_func_arg_type[type].c_type, type_str); - ctype = buf; - } fprintf(fp, "%s %s", ctype, name); } void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) { - if ( type == TYPE_ENUM ) - fprintf(fp, builtin_func_arg_type[type].constructor, - name, type_str); - else - fprintf(fp, builtin_func_arg_type[type].constructor, name); + fprintf(fp, builtin_func_arg_type[type].constructor, name); } diff --git a/src/bif_type.def b/src/bif_type.def index 94e12997e8..84179be1c3 100644 --- a/src/bif_type.def +++ b/src/bif_type.def @@ -22,5 +22,4 @@ DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVa // DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "new StringVal(%s)") DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "%s") DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "new Val(%s, TYPE_TIME)") -DEFINE_BIF_TYPE(TYPE_ENUM, "", "", "BroEnum::%s", "%s->InternalInt()", "new EnumVal(%s, enum_%s)") DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "%s") From 86fdd1dcf338bee3e16ee482f6e101a5c087179e Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 09:31:22 -0800 Subject: [PATCH 13/23] Support namespaces / modules in bif. Checkpoint. This change is actually two-fold: a) bif's now accept module XYZ; statements and module::ID for function, const, event, enum, etc. declartation b) Added C++-namespaces to variables, functions, etc. that are declared in bif but accessed from C++ This required some (lightweight) re-factoring of the C++ codes. Note, event's don't have their own C++ namespace yet, since this would require a rather huge re-factoring. Compiles and passes test suite. New namespace feature not tested yet. Documentation to follow. --- src/module_util.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/module_util.h | 14 ++++++++++ 2 files changed, 79 insertions(+) create mode 100644 src/module_util.cc create mode 100644 src/module_util.h diff --git a/src/module_util.cc b/src/module_util.cc new file mode 100644 index 0000000000..f30f3db938 --- /dev/null +++ b/src/module_util.cc @@ -0,0 +1,65 @@ +// +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include +#include "module_util.h" + +static int streq(const char* s1, const char* s2) + { + return ! strcmp(s1, s2); + } + +// Returns it without trailing "::". +string extract_module_name(const char* name) + { + string module_name = name; + string::size_type pos = module_name.rfind("::"); + + if ( pos == string::npos ) + return string(GLOBAL_MODULE_NAME); + + module_name.erase(pos); + + return module_name; + } + +string extract_var_name(const char *name) + { + string var_name = name; + string::size_type pos = var_name.rfind("::"); + + if ( pos == string::npos ) + return var_name; + + if ( pos + 2 > var_name.size() ) + return string(""); + + return var_name.substr(pos+2); + } + + + +string normalized_module_name(const char* module_name) + { + int mod_len; + if ( (mod_len = strlen(module_name)) >= 2 && + streq(module_name + mod_len - 2, "::") ) + mod_len -= 2; + + return string(module_name, mod_len); + } + +string make_full_var_name(const char* module_name, const char* var_name) + { + if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || + strstr(var_name, "::") ) + return string(var_name); + + string full_name = normalized_module_name(module_name); + full_name += "::"; + full_name += var_name; + + return full_name; + } + diff --git a/src/module_util.h b/src/module_util.h new file mode 100644 index 0000000000..ec82ac0b77 --- /dev/null +++ b/src/module_util.h @@ -0,0 +1,14 @@ + +#include + +using namespace std; + +static const char* GLOBAL_MODULE_NAME = "GLOBAL"; + +extern string extract_module_name(const char* name); +extern string extract_var_name(const char* name); +extern string normalized_module_name(const char* module_name); // w/o :: + +// Concatenates module_name::var_name unless var_name is already fully +// qualified, in which case it is returned unmodified. +extern string make_full_var_name(const char* module_name, const char* var_name); From f79ea244fafdd42d9863b1bd8ceb8083f47a5bb5 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 09:37:23 -0800 Subject: [PATCH 14/23] Support namespaces / modules in bif. Checkpoint. (now actually commiting all the files) This change is actually two-fold: a) bif's now accept module XYZ; statements and module::ID for function, const, event, enum, etc. declartation b) Added C++-namespaces to variables, functions, etc. that are declared in bif but accessed from C++ This required some (lightweight) re-factoring of the C++ codes. Note, event's don't have their own C++ namespace yet, since this would require a rather huge re-factoring. Compiles and passes test suite. New namespace feature not tested yet. Documentation to follow. --- src/CMakeLists.txt | 3 +- src/DCE_RPC.cc | 18 +-- src/DCE_RPC.h | 6 +- src/DNS.h | 2 +- src/FTP.h | 2 +- src/Finger.h | 2 +- src/Func.cc | 14 +- src/HTTP.cc | 2 +- src/HTTP.h | 2 +- src/Ident.h | 2 +- src/Net.cc | 2 +- src/Portmap.cc | 2 +- src/RPC.cc | 14 +- src/SMB.h | 2 +- src/SMTP.h | 2 +- src/Scope.cc | 36 ----- src/Scope.h | 10 +- src/Sessions.cc | 8 +- src/TCP.cc | 6 +- src/TCP_Rewriter.cc | 12 +- src/UDP_Rewriter.cc | 4 +- src/bittorrent-analyzer.pac | 26 ++-- src/builtin-func.l | 7 +- src/builtin-func.y | 266 ++++++++++++++++++++++++++---------- src/dce_rpc-analyzer.pac | 6 +- src/dhcp-analyzer.pac | 16 +-- src/dns-analyzer.pac | 18 +-- src/http-analyzer.pac | 14 +- src/portmap-analyzer.pac | 28 ++-- src/rpc-analyzer.pac | 2 +- src/ssl-analyzer.pac | 26 ++-- 31 files changed, 332 insertions(+), 228 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b371e1cd7..b71dab5c25 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,7 +83,7 @@ flex_target(Scanner scan.l ${CMAKE_CURRENT_BINARY_DIR}/scan.cc set(bifcl_SRCS ${BISON_BIFParser_OUTPUTS} ${FLEX_BIFScanner_OUTPUTS} - bif_arg.cc + bif_arg.cc module_util.cc ) add_executable(bifcl ${bifcl_SRCS}) @@ -240,6 +240,7 @@ set(bro_SRCS main.cc net_util.cc util.cc + module_util.cc Active.cc Analyzer.cc Anon.cc diff --git a/src/DCE_RPC.cc b/src/DCE_RPC.cc index 5b5b1b0e8a..c8b715351c 100644 --- a/src/DCE_RPC.cc +++ b/src/DCE_RPC.cc @@ -85,7 +85,7 @@ UUID::UUID(const char* str) internal_error("invalid UUID string: %s", str); } -typedef map uuid_map_t; +typedef map uuid_map_t; static uuid_map_t& well_known_uuid_map() { @@ -95,7 +95,7 @@ static uuid_map_t& well_known_uuid_map() if ( initialized ) return the_map; - using namespace BroEnum; + using namespace BifEnum; the_map[UUID("e1af8308-5d1f-11c9-91a4-08002b14a0fa")] = DCE_RPC_epmapper; @@ -186,14 +186,14 @@ DCE_RPC_Header::DCE_RPC_Header(Analyzer* a, const u_char* b) else fragmented = 0; - ptype = (BroEnum::dce_rpc_ptype) bytes[2]; + ptype = (BifEnum::dce_rpc_ptype) bytes[2]; frag_len = extract_uint16(LittleEndian(), bytes + 8); } DCE_RPC_Session::DCE_RPC_Session(Analyzer* a) : analyzer(a), if_uuid("00000000-0000-0000-0000-000000000000"), - if_id(BroEnum::DCE_RPC_unknown_if) + if_id(BifEnum::DCE_RPC_unknown_if) { opnum = -1; } @@ -234,7 +234,7 @@ void DCE_RPC_Session::DeliverPDU(int is_orig, int len, const u_char* data) val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new Val(is_orig, TYPE_BOOL)); - vl->append(new EnumVal(data[2], BroTypePtr::Enum::dce_rpc_ptype)); + vl->append(new EnumVal(data[2], BifTypePtr::Enum::dce_rpc_ptype)); vl->append(new StringVal(len, (const char*) data)); analyzer->ConnectionEvent(dce_rpc_message, vl); @@ -286,7 +286,7 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu // conn->Weird(fmt("Unknown DCE_RPC interface %s", // if_uuid.to_string())); #endif - if_id = BroEnum::DCE_RPC_unknown_if; + if_id = BifEnum::DCE_RPC_unknown_if; } else if_id = uuid_it->second; @@ -296,7 +296,7 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new StringVal(if_uuid.to_string())); - // vl->append(new EnumVal(if_id, BroTypePtr::Enum::dce_rpc_if_id)); + // vl->append(new EnumVal(if_id, BifTypePtr::Enum::dce_rpc_if_id)); analyzer->ConnectionEvent(dce_rpc_bind, vl); } @@ -321,7 +321,7 @@ void DCE_RPC_Session::DeliverRequest(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* } switch ( if_id ) { - case BroEnum::DCE_RPC_epmapper: + case BifEnum::DCE_RPC_epmapper: DeliverEpmapperRequest(pdu, req); break; @@ -345,7 +345,7 @@ void DCE_RPC_Session::DeliverResponse(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* } switch ( if_id ) { - case BroEnum::DCE_RPC_epmapper: + case BifEnum::DCE_RPC_epmapper: DeliverEpmapperResponse(pdu, resp); break; diff --git a/src/DCE_RPC.h b/src/DCE_RPC.h index 4e13443148..a856599b19 100644 --- a/src/DCE_RPC.h +++ b/src/DCE_RPC.h @@ -91,7 +91,7 @@ class DCE_RPC_Header { public: DCE_RPC_Header(Analyzer* a, const u_char* bytes); - BroEnum::dce_rpc_ptype PTYPE() const { return ptype; } + BifEnum::dce_rpc_ptype PTYPE() const { return ptype; } int FragLen() const { return frag_len; } int LittleEndian() const { return bytes[4] >> 4; } bool Fragmented() const { return fragmented; } @@ -102,7 +102,7 @@ public: protected: Analyzer* analyzer; const u_char* bytes; - BroEnum::dce_rpc_ptype ptype; + BifEnum::dce_rpc_ptype ptype; int frag_len; bool fragmented; }; @@ -138,7 +138,7 @@ protected: Analyzer* analyzer; UUID if_uuid; - BroEnum::dce_rpc_if_id if_id; + BifEnum::dce_rpc_if_id if_id; int opnum; struct { dce_rpc_endpoint_addr addr; diff --git a/src/DNS.h b/src/DNS.h index 6a68bf5dbd..5e339eea5a 100644 --- a/src/DNS.h +++ b/src/DNS.h @@ -267,7 +267,7 @@ public: TCP_Endpoint* peer, int gen_event); virtual int RewritingTrace() { - return rewriting_dns_trace || + return BifConst::rewriting_dns_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } diff --git a/src/FTP.h b/src/FTP.h index f5d60fdf3b..6db97f8f8f 100644 --- a/src/FTP.h +++ b/src/FTP.h @@ -16,7 +16,7 @@ public: virtual void DeliverStream(int len, const u_char* data, bool orig); virtual int RewritingTrace() { - return rewriting_ftp_trace || + return BifConst::rewriting_ftp_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } diff --git a/src/Finger.h b/src/Finger.h index 92fc5e6f82..b64e1ac66c 100644 --- a/src/Finger.h +++ b/src/Finger.h @@ -18,7 +18,7 @@ public: // Line-based input. virtual void DeliverStream(int len, const u_char* data, bool orig); virtual int RewritingTrace() - { return rewriting_finger_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } + { return BifConst::rewriting_finger_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } static Analyzer* InstantiateAnalyzer(Connection* conn) { return new Finger_Analyzer(conn); } diff --git a/src/Func.cc b/src/Func.cc index 5d71be2b0f..077d878bd9 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -496,6 +496,18 @@ void builtin_run_time(const char* msg, BroObj* arg) run_time(msg, arg); } +#include "bro.bif.func_h" + +#include "common-rw.bif.func_h" +#include "finger-rw.bif.func_h" +#include "ftp-rw.bif.func_h" +#include "http-rw.bif.func_h" +#include "ident-rw.bif.func_h" +#include "smtp-rw.bif.func_h" +#include "strings.bif.func_h" +#include "dns-rw.bif.func_h" + + #include "bro.bif.func_def" #include "strings.bif.func_def" @@ -523,7 +535,7 @@ void init_builtin_funcs() bool check_built_in_call(BuiltinFunc* f, CallExpr* call) { - if ( f->TheFunc() != bro_fmt ) + if ( f->TheFunc() != BifFunc::bro_fmt ) return true; const expr_list& args = call->Args()->Exprs(); diff --git a/src/HTTP.cc b/src/HTTP.cc index a8f4481216..934b96cc32 100644 --- a/src/HTTP.cc +++ b/src/HTTP.cc @@ -633,7 +633,7 @@ void HTTP_Message::SetPlainDelivery(int length) { content_line->SetPlainDelivery(length); - if ( length > 0 && skip_http_data ) + if ( length > 0 && BifConst::skip_http_data ) content_line->SkipBytesAfterThisLine(length); if ( ! data_buffer ) diff --git a/src/HTTP.h b/src/HTTP.h index 2faa1791d1..4f1ea6883b 100644 --- a/src/HTTP.h +++ b/src/HTTP.h @@ -170,7 +170,7 @@ public: virtual void DeliverStream(int len, const u_char* data, bool orig); virtual void Undelivered(int seq, int len, bool orig); virtual int RewritingTrace() - { return rewriting_http_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } + { return BifConst::rewriting_http_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } // Overriden from TCP_ApplicationAnalyzer virtual void EndpointEOF(bool is_orig); diff --git a/src/Ident.h b/src/Ident.h index 63bc64f560..9bdcfdb747 100644 --- a/src/Ident.h +++ b/src/Ident.h @@ -16,7 +16,7 @@ public: virtual void DeliverStream(int length, const u_char* data, bool is_orig); virtual int RewritingTrace() { - return rewriting_ident_trace || + return BifConst::rewriting_ident_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } diff --git a/src/Net.cc b/src/Net.cc index 80ad234b64..bc56556ee5 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -346,7 +346,7 @@ void net_init(name_list& interfaces, name_list& readfiles, transformed_pkt_dump = new PacketDumper(pkt_dumper->PcapDumper()); - if ( anonymize_ip_addr ) + if ( BifConst::anonymize_ip_addr ) init_ip_addr_anonymizers(); else for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i ) diff --git a/src/Portmap.cc b/src/Portmap.cc index 46d79b712c..7e2c06c9a6 100644 --- a/src/Portmap.cc +++ b/src/Portmap.cc @@ -288,7 +288,7 @@ void PortmapperInterp::Event(EventHandlerPtr f, Val* request, int status, Val* r } else { - vl->append(new EnumVal(status, BroTypePtr::Enum::rpc_status)); + vl->append(new EnumVal(status, BifTypePtr::Enum::rpc_status)); if ( request ) vl->append(request); } diff --git a/src/RPC.cc b/src/RPC.cc index 278f8bfee5..ef9a925fea 100644 --- a/src/RPC.cc +++ b/src/RPC.cc @@ -137,14 +137,14 @@ int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig) if ( ! buf ) return 0; - uint32 status = BroEnum::RPC_UNKNOWN_ERROR; + uint32 status = BifEnum::RPC_UNKNOWN_ERROR; if ( reply_stat == RPC_MSG_ACCEPTED ) { (void) skip_XDR_opaque_auth(buf, n); uint32 accept_stat = extract_XDR_uint32(buf, n); - // The first members of BroEnum::RPC_* correspond + // The first members of BifEnum::RPC_* correspond // to accept_stat. if ( accept_stat <= RPC_SYSTEM_ERR ) status = accept_stat; @@ -171,7 +171,7 @@ int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig) if ( reject_stat == RPC_MISMATCH ) { // Note that RPC_MISMATCH == 0 == RPC_SUCCESS. - status = BroEnum::RPC_VERS_MISMATCH; + status = BifEnum::RPC_VERS_MISMATCH; (void) extract_XDR_uint32(buf, n); (void) extract_XDR_uint32(buf, n); @@ -182,7 +182,7 @@ int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig) else if ( reject_stat == RPC_AUTH_ERROR ) { - status = BroEnum::RPC_AUTH_ERROR; + status = BifEnum::RPC_AUTH_ERROR; (void) extract_XDR_uint32(buf, n); if ( ! buf ) @@ -191,7 +191,7 @@ int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig) else { - status = BroEnum::RPC_UNKNOWN_ERROR; + status = BifEnum::RPC_UNKNOWN_ERROR; Weird("bad_RPC"); } } @@ -264,7 +264,7 @@ void RPC_Interpreter::Timeout() while ( (c = calls.NextEntry(cookie)) ) { - RPC_Event(c, BroEnum::RPC_TIMEOUT, 0); + RPC_Event(c, BifEnum::RPC_TIMEOUT, 0); if ( c->IsValidCall() ) { const u_char* buf; @@ -276,7 +276,7 @@ void RPC_Interpreter::Timeout() else { Event(event, c->TakeRequestVal(), - BroEnum::RPC_TIMEOUT, reply); + BifEnum::RPC_TIMEOUT, reply); } } } diff --git a/src/SMB.h b/src/SMB.h index d41ef7f9e0..14c43a1f3d 100644 --- a/src/SMB.h +++ b/src/SMB.h @@ -206,7 +206,7 @@ public: DCE_RPC_Session::any_dce_rpc_event(); } - int RewritingTrace() { return rewriting_smb_trace; } + int RewritingTrace() { return BifConst::rewriting_smb_trace; } protected: SMB_Session* smb_session; diff --git a/src/SMTP.h b/src/SMTP.h index 6e3ad6cc29..7bede1d9d1 100644 --- a/src/SMTP.h +++ b/src/SMTP.h @@ -47,7 +47,7 @@ public: virtual void ConnectionFinished(int half_finished); virtual void Undelivered(int seq, int len, bool orig); virtual int RewritingTrace() - { return rewriting_smtp_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } + { return BifConst::rewriting_smtp_trace || TCP_ApplicationAnalyzer::RewritingTrace(); } void SkipData() { skip_data = 1; } // skip delivery of data lines diff --git a/src/Scope.cc b/src/Scope.cc index 9b75f5f22b..64cf61080f 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -11,42 +11,6 @@ static scope_list scopes; static Scope* top_scope; -// Returns it without trailing "::". -string extract_module_name(const char* name) - { - string module_name = name; - string::size_type pos = module_name.rfind("::"); - - if ( pos == string::npos ) - return string(GLOBAL_MODULE_NAME); - - module_name.erase(pos); - - return module_name; - } - -string normalized_module_name(const char* module_name) - { - int mod_len; - if ( (mod_len = strlen(module_name)) >= 2 && - ! strcmp(module_name + mod_len - 2, "::") ) - mod_len -= 2; - - return string(module_name, mod_len); - } - -string make_full_var_name(const char* module_name, const char* var_name) - { - if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || - strstr(var_name, "::") ) - return string(var_name); - - string full_name = normalized_module_name(module_name); - full_name += "::"; - full_name += var_name; - - return full_name; - } Scope::Scope(ID* id) { diff --git a/src/Scope.h b/src/Scope.h index ffc695210a..660e24668e 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -1,5 +1,6 @@ // $Id: Scope.h 6219 2008-10-01 05:39:07Z vern $ // +// // See the file "COPYING" in the main distribution directory for copyright. #ifndef scope_h @@ -11,6 +12,7 @@ #include "Obj.h" #include "BroList.h" #include "TraverseTypes.h" +#include "module_util.h" class ID; class BroType; @@ -59,14 +61,6 @@ protected: id_list* inits; }; -static const char* GLOBAL_MODULE_NAME = "GLOBAL"; - -extern string extract_module_name(const char* name); -extern string normalized_module_name(const char* module_name); // w/o :: - -// Concatenates module_name::var_name unless var_name is already fully -// qualified, in which case it is returned unmodified. -extern string make_full_var_name(const char* module_name, const char* var_name); extern bool in_debug; diff --git a/src/Sessions.cc b/src/Sessions.cc index fd443d4dcc..b29192a471 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -201,7 +201,7 @@ void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr, // // Should we discourage the use of encap_hdr_size for UDP // tunnneling? It is probably better handled by enabling - // parse_udp_tunnels instead of specifying a fixed + // BifConst::parse_udp_tunnels instead of specifying a fixed // encap_hdr_size. if ( udp_tunnel_port > 0 ) { @@ -228,7 +228,7 @@ void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr, // Check IP packets encapsulated through UDP tunnels. // Specifying a udp_tunnel_port is optional but recommended (to avoid // the cost of checking every UDP packet). - else if ( parse_udp_tunnels && ip_data && ip_hdr->ip_p == IPPROTO_UDP ) + else if ( BifConst::parse_udp_tunnels && ip_data && ip_hdr->ip_p == IPPROTO_UDP ) { const struct udphdr* udp_hdr = reinterpret_cast(ip_data); @@ -663,9 +663,9 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // Override content record setting according to // flags set by the policy script. - if ( dump_original_packets_if_not_rewriting ) + if ( BifConst::dump_original_packets_if_not_rewriting ) record_packet = record_content = 1; - if ( dump_selected_source_packets ) + if ( BifConst::dump_selected_source_packets ) record_packet = record_content = 0; if ( f ) diff --git a/src/TCP.cc b/src/TCP.cc index ec84df9720..e470a07f55 100644 --- a/src/TCP.cc +++ b/src/TCP.cc @@ -56,7 +56,7 @@ TCP_Analyzer::TCP_Analyzer(Connection* conn) orig->SetPeer(resp); resp->SetPeer(orig); - if ( dump_selected_source_packets ) + if ( BifConst::dump_selected_source_packets ) { if ( source_pkt_dump ) src_pkt_writer = @@ -87,7 +87,7 @@ void TCP_Analyzer::Init() if ( transformed_pkt_dump && Conn()->RewritingTrace() ) SetTraceRewriter(new TCP_Rewriter(this, transformed_pkt_dump, transformed_pkt_dump_MTU, - requires_trace_commitment)); + BifConst::requires_trace_commitment)); } void TCP_Analyzer::Done() @@ -2090,7 +2090,7 @@ int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, int seq_delta = top_seq - max_top_seq; if ( seq_delta <= 0 ) { - if ( ! ignore_keep_alive_rexmit || len > 1 || data_in_flight > 0 ) + if ( ! BifConst::ignore_keep_alive_rexmit || len > 1 || data_in_flight > 0 ) { ++num_rxmit; num_rxmit_bytes += len; diff --git a/src/TCP_Rewriter.cc b/src/TCP_Rewriter.cc index 3a8ca8b7b6..734d3abbde 100644 --- a/src/TCP_Rewriter.cc +++ b/src/TCP_Rewriter.cc @@ -288,7 +288,7 @@ int TCP_TracePacket::Finish(struct pcap_pkthdr*& hdr, // tp->th_urp = 0; // clear urgent pointer // Fix IP addresses before computing the TCP checksum - if ( anonymize_ip_addr ) + if ( BifConst::anonymize_ip_addr ) { ip->ip_src.s_addr = anon_src; ip->ip_dst.s_addr = anon_dst; @@ -726,7 +726,7 @@ void TCP_RewriterEndpoint::PushPacket() #endif if ( ! IsPlaceHolderPacket(next_packet) || - ! omit_rewrite_place_holder ) + ! BifConst::omit_rewrite_place_holder ) { if ( next_packet->PredictedAsEmptyPlaceHolder() ) { @@ -798,7 +798,7 @@ TCP_Rewriter::TCP_Rewriter(TCP_Analyzer* arg_analyzer, PacketDumper* arg_dumper, anon_addr[0] = anon_addr[1] = 0; - if ( anonymize_ip_addr ) + if ( BifConst::anonymize_ip_addr ) { anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()), ORIG_ADDR); @@ -909,7 +909,7 @@ void TCP_Rewriter::NextPacket(int is_orig, double t, // Before setting current_packet to p, first clean up empty // place holders to save memory space. - if ( omit_rewrite_place_holder && holding_packets ) + if ( BifConst::omit_rewrite_place_holder && holding_packets ) CleanUpEmptyPlaceHolders(); current_packet = p; @@ -1562,7 +1562,7 @@ TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer) { if ( ! pkt_dumper ) return 0; // don't complain if no output file - else if ( ! dump_selected_source_packets ) + else if ( ! BifConst::dump_selected_source_packets ) builtin_run_time("flag dump_source_packets is not set"); else internal_error("source packet writer not initialized"); @@ -1571,5 +1571,5 @@ TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer) return writer; } - +#include "common-rw.bif.func_h" #include "common-rw.bif.func_def" diff --git a/src/UDP_Rewriter.cc b/src/UDP_Rewriter.cc index 967f2087f1..458d25992d 100644 --- a/src/UDP_Rewriter.cc +++ b/src/UDP_Rewriter.cc @@ -26,7 +26,7 @@ UDP_Rewriter::UDP_Rewriter(Analyzer* arg_analyzer, int arg_MTU, packets_rewritten = 0; current_packet = next_packet = 0; - if ( anonymize_ip_addr ) + if ( BifConst::anonymize_ip_addr ) { anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()), ORIG_ADDR); @@ -73,7 +73,7 @@ int UDP_TracePacket::BuildPacket(struct pcap_pkthdr*& hdr, uint32 sum = 0; // Fix IP addresses before computing the UDP checksum - if ( anonymize_ip_addr ) + if ( BifConst::anonymize_ip_addr ) { ip->ip_src.s_addr = anon_src; ip->ip_dst.s_addr = anon_dst; diff --git a/src/bittorrent-analyzer.pac b/src/bittorrent-analyzer.pac index f159588f0b..7e8678b7de 100644 --- a/src/bittorrent-analyzer.pac +++ b/src/bittorrent-analyzer.pac @@ -64,7 +64,7 @@ flow BitTorrent_Flow(is_orig: bool) { handshake_ok = true; if ( ::bittorrent_peer_handshake ) { - bro_event_bittorrent_peer_handshake( + BifEvent::generate_bittorrent_peer_handshake( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -82,7 +82,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_keep_alive ) { - bro_event_bittorrent_peer_keep_alive( + BifEvent::generate_bittorrent_peer_keep_alive( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); @@ -95,7 +95,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_choke ) { - bro_event_bittorrent_peer_choke( + BifEvent::generate_bittorrent_peer_choke( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); @@ -108,7 +108,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_unchoke ) { - bro_event_bittorrent_peer_unchoke( + BifEvent::generate_bittorrent_peer_unchoke( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); @@ -121,7 +121,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_interested ) { - bro_event_bittorrent_peer_interested( + BifEvent::generate_bittorrent_peer_interested( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); @@ -134,7 +134,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_not_interested ) { - bro_event_bittorrent_peer_not_interested( + BifEvent::generate_bittorrent_peer_not_interested( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); @@ -147,7 +147,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_have ) { - bro_event_bittorrent_peer_have( + BifEvent::generate_bittorrent_peer_have( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -161,7 +161,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_bitfield ) { - bro_event_bittorrent_peer_bitfield( + BifEvent::generate_bittorrent_peer_bitfield( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -176,7 +176,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_request ) { - bro_event_bittorrent_peer_request( + BifEvent::generate_bittorrent_peer_request( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -191,7 +191,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_piece ) { - bro_event_bittorrent_peer_piece( + BifEvent::generate_bittorrent_peer_piece( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -206,7 +206,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_cancel ) { - bro_event_bittorrent_peer_cancel( + BifEvent::generate_bittorrent_peer_cancel( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -220,7 +220,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_port ) { - bro_event_bittorrent_peer_port( + BifEvent::generate_bittorrent_peer_port( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), @@ -234,7 +234,7 @@ flow BitTorrent_Flow(is_orig: bool) { %{ if ( ::bittorrent_peer_unknown ) { - bro_event_bittorrent_peer_unknown( + BifEvent::generate_bittorrent_peer_unknown( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), diff --git a/src/builtin-func.l b/src/builtin-func.l index 14b0eb52a6..a5e37441cf 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -28,7 +28,11 @@ int check_c_mode(int t) %} WS [ \t]+ -ID [A-Za-z_][A-Za-z_0-9]* + /* Note, bifcl only accepts a single :: in IDs while the policy + layer acceptes multiple. (But the policy layer doesn't have + a hierachy */ +IDCOMPONENT [A-Za-z_][A-Za-z_0-9]* +ID {IDCOMPONENT}(::{IDCOMPONENT})? ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) D [[:digit:]]+ HEX [0-9a-fA-F]+ @@ -69,6 +73,7 @@ HEX [0-9a-fA-F]+ "enum" return check_c_mode(TOK_ENUM); "type" return check_c_mode(TOK_TYPE); "record" return check_c_mode(TOK_RECORD); +"module" return check_c_mode(TOK_MODULE); "@ARG@" return TOK_ARG; "@ARGS@" return TOK_ARGS; diff --git a/src/builtin-func.y b/src/builtin-func.y index fafcdea76a..f9117f97fc 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -9,6 +9,10 @@ using namespace std; #include #include +#include "module_util.h" + +using namespace std; + extern int line_number; extern char* input_filename; @@ -23,39 +27,128 @@ extern FILE* fp_netvar_def; extern FILE* fp_netvar_init; int in_c_code = 0; +string current_module = GLOBAL_MODULE_NAME; int definition_type; -const char* bro_prefix; -const char* c_prefix; + enum { C_SEGMENT_DEF, FUNC_DEF, REWRITER_DEF, EVENT_DEF, + ENUM_DEF, + CONST_DEF, + RECORD_DEF, }; +// Holds the name of a declared object (function, enum, record type, event, +// etc. and information about namespaces, etc. +struct decl_struct { + string module_name; + string bare_name; // name without module or namespace + string c_namespace_start; // "opening" namespace for use in netvar_* + string c_namespace_end; // closing "}" for all the above namespaces + string c_fullname; // fully qualified name (namespace::....) for use in netvar_init + string bro_fullname; // fully qualified bro name, for netvar (and lookup_ID()) + string bro_name; // the name as we read it from input. What we write into the .bro file + + // special cases for events. Events have an EventHandlerPtr + // and a generate_* function. This name is for the generate_* function + string generate_bare_name; + string generate_c_fullname; + string generate_c_namespace_start; + string generate_c_namespace_end; +} decl; + void set_definition_type(int type) { definition_type = type; - switch ( type ) { - case FUNC_DEF: - bro_prefix = ""; - c_prefix = "bro_"; + } + +void set_decl_name(const char *name) + { + decl.module_name = extract_module_name(name); + decl.bare_name = extract_var_name(name); + + decl.c_namespace_start = ""; + decl.c_namespace_end = ""; + decl.c_fullname = ""; + decl.bro_fullname = ""; + decl.bro_name = ""; + + decl.generate_c_fullname = ""; + decl.generate_bare_name = string("generate_") + decl.bare_name; + decl.generate_c_namespace_start = ""; + decl.generate_c_namespace_end = ""; + + switch ( definition_type ) { + case ENUM_DEF: + decl.c_namespace_start = "namespace BifTypePtr { namespace Enum { "; + decl.c_namespace_end = " } }"; + decl.c_fullname = "BifTypePtr::Enum::"; + break; + case RECORD_DEF: + decl.c_namespace_start = "namespace BifTypePtr { namespace Record { "; + decl.c_namespace_end = " } }"; + decl.c_fullname = "BifTypePtr::Record::"; break; + case CONST_DEF: + decl.c_namespace_start = "namespace BifConst { "; + decl.c_namespace_end = " } "; + decl.c_fullname = "BifConst::"; + break; + case REWRITER_DEF: - bro_prefix = "rewrite_"; - c_prefix = "bro_rewrite_"; + // XXX: Legacy. No module names / namespaces supported + // If support for namespaces is desired: add a namespace + // to c_namespace_* and bro_fullname and get rid of + // the hack to bro_name. + decl.c_namespace_start = ""; + decl.c_namespace_end = ""; + decl.bare_name = "rewrite_" + decl.bare_name; + decl.bro_name = "rewrite_"; + break; + + case FUNC_DEF: + decl.c_namespace_start = "namespace BifFunc { "; + decl.c_namespace_end = " } "; + decl.c_fullname = "BifFunc::"; break; case EVENT_DEF: - bro_prefix = ""; - c_prefix = "bro_event_"; + decl.c_namespace_start = ""; + decl.c_namespace_end = ""; + decl.c_fullname = ""; + decl.generate_c_namespace_start = "namespace BifEvent { "; + decl.generate_c_namespace_end = " } "; + decl.generate_c_fullname = "BifEvent::"; break; - case C_SEGMENT_DEF: + default: break; } + + if (decl.module_name != GLOBAL_MODULE_NAME) + { + decl.c_namespace_start += "namespace " + decl.module_name + " { "; + decl.c_namespace_end += string(" }"); + decl.c_fullname += decl.module_name + "::"; + decl.bro_fullname += decl.module_name + "::"; + + decl.generate_c_namespace_start += "namespace " + decl.module_name + " { "; + decl.generate_c_namespace_end += " } "; + decl.generate_c_fullname += decl.module_name + "::"; + } + + decl.bro_fullname += decl.bare_name; + if (definition_type == FUNC_DEF) + decl.bare_name = string("bro_") + decl.bare_name; + + decl.c_fullname += decl.bare_name; + decl.bro_name += name; + decl.generate_c_fullname += decl.generate_bare_name; + } const char* arg_list_name = "BiF_ARGS"; @@ -63,7 +156,6 @@ const char* trace_rewriter_name = "trace_rewriter"; #include "bif_arg.h" -extern const char* decl_name; int var_arg; // whether the number of arguments is variable std::vector args; @@ -87,9 +179,15 @@ char* concat(const char* str1, const char* str2) } // Print the bro_event_* function prototype in C++, without the ending ';' -void print_event_c_prototype(FILE *fp) +void print_event_c_prototype(FILE *fp, bool is_header) { - fprintf(fp, "void %s%s(Analyzer* analyzer%s", c_prefix, decl_name, + if (is_header) + fprintf(fp, "%s void %s(Analyzer* analyzer%s", + decl.generate_c_namespace_start.c_str(), decl.generate_bare_name.c_str(), + args.size() ? ", " : "" ); + else + fprintf(fp, "void %s(Analyzer* analyzer%s", + decl.generate_c_fullname.c_str(), args.size() ? ", " : "" ); for ( int i = 0; i < (int) args.size(); ++i ) { @@ -98,6 +196,10 @@ void print_event_c_prototype(FILE *fp) args[i]->PrintCArg(fp, i); } fprintf(fp, ")"); + if (is_header) + fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); + else + fprintf(fp, "\n"); } // Print the bro_event_* function body in C++. @@ -106,9 +208,9 @@ void print_event_c_body(FILE *fp) fprintf(fp, "\t{\n"); fprintf(fp, "\t// Note that it is intentional that here we do not\n"); fprintf(fp, "\t// check if %s is NULL, which should happen *before*\n", - decl_name); - fprintf(fp, "\t// bro_event_%s is called to avoid unnecessary Val\n", - decl_name); + decl.c_fullname.c_str()); + fprintf(fp, "\t// %s is called to avoid unnecessary Val\n", + decl.generate_c_fullname.c_str()); fprintf(fp, "\t// allocation.\n"); fprintf(fp, "\n"); @@ -138,7 +240,7 @@ void print_event_c_body(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "\tmgr.QueueEvent(%s, vl, SOURCE_LOCAL, analyzer->GetID(), timer_mgr", - decl_name); + decl.c_fullname.c_str()); if ( connection_arg ) // Pass the connection to the EventMgr as the "cookie" @@ -146,13 +248,14 @@ void print_event_c_body(FILE *fp) fprintf(fp, ");\n"); fprintf(fp, "\t} // event generation\n"); + //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); } %} %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG %token TOK_BOOL %token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM -%token TOK_TYPE TOK_RECORD +%token TOK_TYPE TOK_RECORD TOK_MODULE %token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE %token TOK_ARGS TOK_ARG TOK_ARGC %token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT @@ -170,7 +273,15 @@ void print_event_c_body(FILE *fp) %% -definitions: definitions definition opt_ws +builtin_lang: definitions + { + fprintf(fp_bro_init, "} # end of export section\n"); + fprintf(fp_bro_init, "module %s;\n", GLOBAL_MODULE_NAME); + } + + + +definitions: definitions definition opt_ws { fprintf(fp_func_def, "%s", $3); } | opt_ws { @@ -189,6 +300,7 @@ definitions: definitions definition opt_ws fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); + fprintf(fp_bro_init, "export {\n"); fprintf(fp_func_def, "%s", $1); } ; @@ -200,9 +312,16 @@ definition: event_def | enum_def | const_def | type_def + | module_def ; +module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' + { + current_module = $2; + fprintf(fp_bro_init, "module %s;\n", $2); + } + // XXX: Add the netvar glue so that the event engine knows about // the type. One still has to define the type in bro.init. // Would be nice, if we could just define the record type here @@ -213,26 +332,26 @@ definition: event_def // TODO: add other types (tables, sets) type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws TOK_RECORD opt_ws ';' { - fprintf(fp_netvar_h, - "namespace BroTypePtr { namespace Record { extern RecordType* %s; } }\n", $3); - fprintf(fp_netvar_def, - "namespace BroTypePtr { namespace Record { RecordType* %s; } }\n", $3); + set_definition_type(RECORD_DEF); + set_decl_name($3); + + fprintf(fp_netvar_h, "%s extern RecordType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s RecordType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tBroTypePtr::Record::%s = internal_type(\"%s\")->AsRecordType();\n", - $3, $3); + "\t%s = internal_type(\"%s\")->AsRecordType();\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); } ; event_def: event_prefix opt_ws plain_head opt_attr end_of_head ';' { - print_event_c_prototype(fp_func_h); - fprintf(fp_func_h, ";\n"); - print_event_c_prototype(fp_func_def); - fprintf(fp_func_def, "\n"); + print_event_c_prototype(fp_func_h, true); + print_event_c_prototype(fp_func_def, false); print_event_c_body(fp_func_def); } - ; - + func_def: func_prefix opt_ws typed_head end_of_head body ; @@ -243,24 +362,34 @@ enum_def: enum_def_1 enum_list TOK_RPB { // First, put an end to the enum type decl. fprintf(fp_bro_init, "};\n"); - fprintf(fp_netvar_h, "}; }\n"); + if (decl.module_name != GLOBAL_MODULE_NAME) + fprintf(fp_netvar_h, "}; } }\n"); + else + fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. - fprintf(fp_netvar_h, - "namespace BroTypePtr { namespace Enum { extern EnumType* %s;\n } }", decl_name); - fprintf(fp_netvar_def, - "namespace BroTypePtr { namespace Enum { EnumType* %s; } }\n", decl_name); + fprintf(fp_netvar_h, "%s extern EnumType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tBroTypePtr::Enum::%s = internal_type(\"%s\")->AsEnumType();\n", - decl_name, decl_name); + "\t%s = internal_type(\"%s\")->AsEnumType();\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); } ; enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws { - decl_name = $3; - fprintf(fp_bro_init, "type %s: enum %s{%s", $3, $4, $6); - fprintf(fp_netvar_h, "namespace BroEnum { "); + set_definition_type(ENUM_DEF); + set_decl_name($3); + fprintf(fp_bro_init, "type %s: enum %s{%s", decl.bro_name.c_str(), $4, $6); + + // this is the namespace were the enumerators are defined, not where + // the type is defined. + // We don't support fully qualified names as enumerators. Use a module name + fprintf(fp_netvar_h, "namespace BifEnum { "); + if (decl.module_name != GLOBAL_MODULE_NAME) + fprintf(fp_netvar_h, "namespace %s { ", decl.module_name.c_str()); fprintf(fp_netvar_h, "enum %s {\n", $3); } ; @@ -281,18 +410,21 @@ enum_list: enum_list TOK_ID opt_ws ',' opt_ws const_def: const_def_1 const_init opt_attr ';' { fprintf(fp_bro_init, ";\n"); - fprintf(fp_netvar_h, "extern int %s;\n", decl_name); - fprintf(fp_netvar_def, "int %s;\n", decl_name); + fprintf(fp_netvar_h, "%s extern int %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s int %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, "\t%s = internal_val(\"%s\")->AsBool();\n", - decl_name, decl_name); + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); } ; const_def_1: TOK_CONST opt_ws TOK_ID opt_ws { - decl_name = $3; + set_definition_type(CONST_DEF); + set_decl_name($3); fprintf(fp_bro_init, "const%s", $2); - fprintf(fp_bro_init, "%s: bool%s", $3, $4); + fprintf(fp_bro_init, "%s: bool%s", decl.bro_name.c_str(), $4); } ; @@ -364,7 +496,7 @@ plain_head: head_1 args arg_end opt_ws head_1: TOK_ID opt_ws arg_begin { const char* method_type = 0; - decl_name = $1; + set_decl_name($1); if ( definition_type == FUNC_DEF || definition_type == REWRITER_DEF ) { @@ -376,40 +508,37 @@ head_1: TOK_ID opt_ws arg_begin if ( method_type ) fprintf(fp_bro_init, - "global %s%s: %s%s(", - bro_prefix, decl_name, method_type, $2); + "global %s: %s%s(", + decl.bro_name.c_str(), method_type, $2); if ( definition_type == FUNC_DEF || definition_type == REWRITER_DEF ) { fprintf(fp_func_init, - "\textern Val* %s%s(Frame* frame, val_list*);\n", - c_prefix, decl_name); - - fprintf(fp_func_init, - "\t(void) new BuiltinFunc(%s%s, \"%s%s\", 0);\n", - c_prefix, decl_name, bro_prefix, decl_name); + "\t(void) new BuiltinFunc(%s, \"%s\", 0);\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_func_h, - "extern Val* %s%s(Frame* frame, val_list*);\n", - c_prefix, decl_name); + "%sextern Val* %s(Frame* frame, val_list*);\n %s", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "Val* %s%s(Frame* frame, val_list* %s)", - c_prefix, decl_name, arg_list_name); + "Val* %s(Frame* frame, val_list* %s)", + decl.c_fullname.c_str(), arg_list_name); } else if ( definition_type == EVENT_DEF ) { + // TODO: add namespace for events here fprintf(fp_netvar_h, - "extern EventHandlerPtr %s;\n", - decl_name); + "%sextern EventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, - "EventHandlerPtr %s;\n", - decl_name); + "%sEventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, "\t%s = internal_handler(\"%s\");\n", - decl_name, decl_name); + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); // C++ prototypes of bro_event_* functions will // be generated later. @@ -455,7 +584,7 @@ return_type: ':' opt_ws TOK_ID opt_ws body: body_start c_body body_end { - fprintf(fp_func_def, " // end of %s\n", decl_name); + fprintf(fp_func_def, " // end of %s\n", decl.c_fullname.c_str()); print_line_directive(fp_func_def); } ; @@ -492,7 +621,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\trun_time(\"%s() takes exactly %d argument(s)\");\n", - decl_name, argc); + decl.bro_fullname.c_str(), argc); fprintf(fp_func_def, "\t\treturn 0;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -502,7 +631,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\trun_time(\"%s() takes at least %d argument(s)\");\n", - decl_name, argc); + decl.bro_fullname.c_str(), argc); fprintf(fp_func_def, "\t\treturn 0;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -586,7 +715,6 @@ opt_ws: opt_ws TOK_WS extern char* yytext; extern char* input_filename; extern int line_number; -const char* decl_name; void err_exit(void); void print_msg(const char msg[]) diff --git a/src/dce_rpc-analyzer.pac b/src/dce_rpc-analyzer.pac index 8f412401f7..353c9f3795 100644 --- a/src/dce_rpc-analyzer.pac +++ b/src/dce_rpc-analyzer.pac @@ -88,7 +88,7 @@ flow DCE_RPC_Flow(is_orig: bool) { bind_elems.p_cont_elem[i].abstract_syntax.if_uuid}; // Queue the event - bro_event_dce_rpc_bind( + BifEvent::generate_dce_rpc_bind( ${connection.bro_analyzer}, ${connection.bro_analyzer}->Conn(), bytestring_to_val(${if_uuid})); @@ -106,7 +106,7 @@ flow DCE_RPC_Flow(is_orig: bool) { %{ if ( dce_rpc_request ) { - bro_event_dce_rpc_request( + BifEvent::generate_dce_rpc_request( ${connection.bro_analyzer}, ${connection.bro_analyzer}->Conn(), ${req.opnum}, @@ -124,7 +124,7 @@ flow DCE_RPC_Flow(is_orig: bool) { %{ if ( dce_rpc_response ) { - bro_event_dce_rpc_response( + BifEvent::generate_dce_rpc_response( ${connection.bro_analyzer}, ${connection.bro_analyzer}->Conn(), ${connection}->get_cont_id_opnum_map(${resp.p_cont_id}), diff --git a/src/dhcp-analyzer.pac b/src/dhcp-analyzer.pac index 4bebc0ba4f..ef8b888330 100644 --- a/src/dhcp-analyzer.pac +++ b/src/dhcp-analyzer.pac @@ -91,31 +91,31 @@ flow DHCP_Flow(is_orig: bool) { switch ( type ) { case DHCPDISCOVER: - bro_event_dhcp_discover(connection()->bro_analyzer(), + BifEvent::generate_dhcp_discover(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref(), req_addr); break; case DHCPREQUEST: - bro_event_dhcp_request(connection()->bro_analyzer(), + BifEvent::generate_dhcp_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref(), req_addr, serv_addr); break; case DHCPDECLINE: - bro_event_dhcp_decline(connection()->bro_analyzer(), + BifEvent::generate_dhcp_decline(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref()); break; case DHCPRELEASE: - bro_event_dhcp_release(connection()->bro_analyzer(), + BifEvent::generate_dhcp_release(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref()); break; case DHCPINFORM: - bro_event_dhcp_inform(connection()->bro_analyzer(), + BifEvent::generate_dhcp_inform(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref()); break; @@ -204,21 +204,21 @@ flow DHCP_Flow(is_orig: bool) { switch ( type ) { case DHCPOFFER: - bro_event_dhcp_offer(connection()->bro_analyzer(), + BifEvent::generate_dhcp_offer(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref(), subnet_mask, router_list, lease, serv_addr); break; case DHCPACK: - bro_event_dhcp_ack(connection()->bro_analyzer(), + BifEvent::generate_dhcp_ack(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref(), subnet_mask, router_list, lease, serv_addr); break; case DHCPNAK: - bro_event_dhcp_nak(connection()->bro_analyzer(), + BifEvent::generate_dhcp_nak(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref()); break; diff --git a/src/dns-analyzer.pac b/src/dns-analyzer.pac index 2e9a6496c3..72bda3165f 100644 --- a/src/dns-analyzer.pac +++ b/src/dns-analyzer.pac @@ -124,7 +124,7 @@ flow DNS_Flow if ( msg->header()->qr() == 0 ) { - bro_event_dns_request( + BifEvent::generate_dns_request( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -137,7 +137,7 @@ flow DNS_Flow msg->header()->nscount() == 0 && msg->header()->arcount() == 0 ) { - bro_event_dns_rejected( + BifEvent::generate_dns_rejected( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -253,7 +253,7 @@ flow DNS_Flow // above fixes for BROv6, we can probably now introduce // their own events. (It's not clear A6 is needed - // do we actually encounter it in practice?) - bro_event_dns_A_reply(connection()->bro_analyzer(), + BifEvent::generate_dns_A_reply(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), build_dns_answer(rr), addr); break; @@ -261,7 +261,7 @@ flow DNS_Flow case TYPE_NS: if ( dns_NS_reply ) { - bro_event_dns_NS_reply(connection()->bro_analyzer(), + BifEvent::generate_dns_NS_reply(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), build_dns_answer(rr), @@ -272,7 +272,7 @@ flow DNS_Flow case TYPE_CNAME: if ( dns_CNAME_reply ) { - bro_event_dns_CNAME_reply( + BifEvent::generate_dns_CNAME_reply( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -284,7 +284,7 @@ flow DNS_Flow case TYPE_SOA: if ( dns_SOA_reply ) { - bro_event_dns_SOA_reply( + BifEvent::generate_dns_SOA_reply( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -296,7 +296,7 @@ flow DNS_Flow case TYPE_PTR: if ( dns_PTR_reply ) { - bro_event_dns_PTR_reply( + BifEvent::generate_dns_PTR_reply( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -308,7 +308,7 @@ flow DNS_Flow case TYPE_MX: if ( dns_MX_reply ) { - bro_event_dns_MX_reply( + BifEvent::generate_dns_MX_reply( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), @@ -321,7 +321,7 @@ flow DNS_Flow case TYPE_EDNS: if ( dns_EDNS_addl ) { - bro_event_dns_EDNS_addl( + BifEvent::generate_dns_EDNS_addl( connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), dns_msg_val_->Ref(), diff --git a/src/http-analyzer.pac b/src/http-analyzer.pac index 38402a9d67..c1a4dd7b26 100644 --- a/src/http-analyzer.pac +++ b/src/http-analyzer.pac @@ -84,7 +84,7 @@ flow HTTP_Flow(is_orig: bool) { if ( ::http_request ) { bytestring unescaped_uri = unescape_uri(uri); - bro_event_http_request(connection()->bro_analyzer(), + BifEvent::generate_http_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(method), bytestring_to_val(uri), @@ -103,7 +103,7 @@ flow HTTP_Flow(is_orig: bool) { %{ if ( ::http_reply ) { - bro_event_http_reply(connection()->bro_analyzer(), + BifEvent::generate_http_reply(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(${vers.vers_str}), code, bytestring_to_val(reason)); @@ -205,7 +205,7 @@ flow HTTP_Flow(is_orig: bool) { if ( ::http_header ) { - bro_event_http_header(connection()->bro_analyzer(), + BifEvent::generate_http_header(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), bytestring_to_val(name)->ToUpper(), @@ -236,7 +236,7 @@ flow HTTP_Flow(is_orig: bool) { %{ if ( ::http_all_headers ) { - bro_event_http_all_headers(connection()->bro_analyzer(), + BifEvent::generate_http_all_headers(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), build_http_headers_val()); @@ -263,7 +263,7 @@ flow HTTP_Flow(is_orig: bool) { msg_start_time_ = network_time(); if ( ::http_begin_entity ) { - bro_event_http_begin_entity(connection()->bro_analyzer(), + BifEvent::generate_http_begin_entity(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); } %} @@ -295,13 +295,13 @@ flow HTTP_Flow(is_orig: bool) { if ( ::http_end_entity ) { - bro_event_http_end_entity(connection()->bro_analyzer(), + BifEvent::generate_http_end_entity(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig()); } if ( ::http_message_done ) { - bro_event_http_message_done(connection()->bro_analyzer(), + BifEvent::generate_http_message_done(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), is_orig(), build_http_message_stat()); } diff --git a/src/portmap-analyzer.pac b/src/portmap-analyzer.pac index 3c7b00cd32..dc02ec1458 100644 --- a/src/portmap-analyzer.pac +++ b/src/portmap-analyzer.pac @@ -100,23 +100,23 @@ refine connection RPC_Conn += { switch ( call->proc() ) { case PMAPPROC_NULL: - bro_event_pm_request_null(bro_analyzer(), bro_analyzer()->Conn()); + BifEvent::generate_pm_request_null(bro_analyzer(), bro_analyzer()->Conn()); break; case PMAPPROC_SET: - bro_event_pm_request_set(bro_analyzer(), + BifEvent::generate_pm_request_set(bro_analyzer(), bro_analyzer()->Conn(), call->call_val(), results->set()); break; case PMAPPROC_UNSET: - bro_event_pm_request_unset(bro_analyzer(), + BifEvent::generate_pm_request_unset(bro_analyzer(), bro_analyzer()->Conn(), call->call_val(), results->unset()); break; case PMAPPROC_GETPORT: - bro_event_pm_request_getport(bro_analyzer(), + BifEvent::generate_pm_request_getport(bro_analyzer(), bro_analyzer()->Conn(), call->call_val(), PortmapBuildPortVal(results->getport(), @@ -124,13 +124,13 @@ refine connection RPC_Conn += { break; case PMAPPROC_DUMP: - bro_event_pm_request_dump(bro_analyzer(), + BifEvent::generate_pm_request_dump(bro_analyzer(), bro_analyzer()->Conn(), PortmapBuildDumpVal(results->dump())); break; case PMAPPROC_CALLIT: - bro_event_pm_request_callit(bro_analyzer(), + BifEvent::generate_pm_request_callit(bro_analyzer(), bro_analyzer()->Conn(), call->call_val(), new PortVal(results->callit()->port(), @@ -149,37 +149,37 @@ function PortmapCallFailed(connection: RPC_Conn, call: RPC_Call, status: EnumRPCStatus): bool %{ - // BroEnum::rpc_status st = static_cast(status); - Val *st = new EnumVal(status, BroTypePtr::Enum::rpc_status); + // BifEnum::rpc_status st = static_cast(status); + Val *st = new EnumVal(status, BifTypePtr::Enum::rpc_status); switch ( call->proc() ) { case PMAPPROC_NULL: - bro_event_pm_attempt_null(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_null(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st); break; case PMAPPROC_SET: - bro_event_pm_attempt_set(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_set(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st, call->call_val()); break; case PMAPPROC_UNSET: - bro_event_pm_attempt_unset(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_unset(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st, call->call_val()); break; case PMAPPROC_GETPORT: - bro_event_pm_attempt_getport(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_getport(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st, call->call_val()); break; case PMAPPROC_DUMP: - bro_event_pm_attempt_dump(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_dump(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st); break; case PMAPPROC_CALLIT: - bro_event_pm_attempt_callit(connection->bro_analyzer(), + BifEvent::generate_pm_attempt_callit(connection->bro_analyzer(), connection->bro_analyzer()->Conn(), st, call->call_val()); break; diff --git a/src/rpc-analyzer.pac b/src/rpc-analyzer.pac index 6c455f7028..86ac81b857 100644 --- a/src/rpc-analyzer.pac +++ b/src/rpc-analyzer.pac @@ -157,7 +157,7 @@ flow RPC_Flow (is_orig: bool) { return false; } - bro_event_rpc_call(connection()->bro_analyzer(), + BifEvent::generate_rpc_call(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), call->prog(), call->vers(), diff --git a/src/ssl-analyzer.pac b/src/ssl-analyzer.pac index 78baecc5cc..9c899ff2b6 100644 --- a/src/ssl-analyzer.pac +++ b/src/ssl-analyzer.pac @@ -165,7 +165,7 @@ refine analyzer SSLAnalyzer += { %{ StringVal* err_str = new StringVal(X509_verify_cert_error_string(err_num)); - bro_event_ssl_X509_error(bro_analyzer_, bro_analyzer_->Conn(), + BifEvent::generate_ssl_X509_error(bro_analyzer_, bro_analyzer_->Conn(), err_num, err_str); %} @@ -189,7 +189,7 @@ refine analyzer SSLAnalyzer += { function proc_alert(level : int, description : int) : bool %{ - bro_event_ssl_conn_alert(bro_analyzer_, bro_analyzer_->Conn(), + BifEvent::generate_ssl_conn_alert(bro_analyzer_, bro_analyzer_->Conn(), current_record_version_, level, description); return true; @@ -217,7 +217,7 @@ refine analyzer SSLAnalyzer += { Unref(ciph); } - bro_event_ssl_conn_attempt(bro_analyzer_, bro_analyzer_->Conn(), + BifEvent::generate_ssl_conn_attempt(bro_analyzer_, bro_analyzer_->Conn(), version, cipher_table); if ( ssl_compare_cipherspecs ) @@ -252,7 +252,7 @@ refine analyzer SSLAnalyzer += { Unref(ciph); } - bro_event_ssl_conn_server_reply(bro_analyzer_, + BifEvent::generate_ssl_conn_server_reply(bro_analyzer_, bro_analyzer_->Conn(), version_, chosen_ciphers); @@ -263,10 +263,10 @@ refine analyzer SSLAnalyzer += { TableVal* tv = to_table_val(session_id); if ( client_session_id_ && *client_session_id_ == *session_id ) - bro_event_ssl_conn_reused(bro_analyzer_, + BifEvent::generate_ssl_conn_reused(bro_analyzer_, bro_analyzer_->Conn(), tv); else - bro_event_ssl_session_insertion(bro_analyzer_, + BifEvent::generate_ssl_session_insertion(bro_analyzer_, bro_analyzer_->Conn(), tv); delete ciphers; @@ -277,13 +277,13 @@ refine analyzer SSLAnalyzer += { if ( client_session_id_ ) { TableVal* tv = to_table_val(client_session_id_); - bro_event_ssl_conn_reused(bro_analyzer_, + BifEvent::generate_ssl_conn_reused(bro_analyzer_, bro_analyzer_->Conn(), tv); } // We don't know the chosen cipher, as there is // no session storage. - bro_event_ssl_conn_established(bro_analyzer_, + BifEvent::generate_ssl_conn_established(bro_analyzer_, bro_analyzer_->Conn(), version_, 0xffffffff); delete ciphers; @@ -316,7 +316,7 @@ refine analyzer SSLAnalyzer += { if ( certificates->size() == 0 ) return true; - bro_event_ssl_certificate_seen(bro_analyzer_, + BifEvent::generate_ssl_certificate_seen(bro_analyzer_, bro_analyzer_->Conn(), ! current_record_is_orig_); @@ -341,7 +341,7 @@ refine analyzer SSLAnalyzer += { pX509Cert->Assign(1, new StringVal(tmp)); pX509Cert->Assign(2, new AddrVal(bro_analyzer_->Conn()->OrigAddr())); - bro_event_ssl_certificate(bro_analyzer_, bro_analyzer_->Conn(), + BifEvent::generate_ssl_certificate(bro_analyzer_, bro_analyzer_->Conn(), pX509Cert, current_record_is_orig_); if ( X509_get_ext_count(pCert) > 0 ) @@ -361,7 +361,7 @@ refine analyzer SSLAnalyzer += { Unref(index); } - bro_event_process_X509_extensions(bro_analyzer_, + BifEvent::generate_process_X509_extensions(bro_analyzer_, bro_analyzer_->Conn(), x509ex); } @@ -442,7 +442,7 @@ refine analyzer SSLAnalyzer += { state_label(old_state_).c_str())); check_cipher(cipher); - bro_event_ssl_conn_established(bro_analyzer_, + BifEvent::generate_ssl_conn_established(bro_analyzer_, bro_analyzer_->Conn(), version_, cipher); return true; @@ -483,7 +483,7 @@ refine analyzer SSLAnalyzer += { if ( state_ == STATE_CONN_ESTABLISHED && old_state_ == STATE_COMM_ENCRYPTED ) { - bro_event_ssl_conn_established(bro_analyzer_, + BifEvent::generate_ssl_conn_established(bro_analyzer_, bro_analyzer_->Conn(), version_, cipher_); } From d95ac545793fa480acf3efada06749e7587d0f24 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 11:48:38 -0800 Subject: [PATCH 15/23] Moving type declarations into its own bif file --- policy/bro.init | 1 + src/CMakeLists.txt | 1 + src/NetVar.cc | 2 ++ src/NetVar.h | 1 + src/const.bif | 51 --------------------------------------------- src/types.bif | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 51 deletions(-) create mode 100644 src/types.bif diff --git a/policy/bro.init b/policy/bro.init index c9fd5213cc..3b3378c5ac 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -1,6 +1,7 @@ # $Id: bro.init 6887 2009-08-20 05:17:33Z vern $ @load const.bif.bro +@load types.bif.bro global bro_signal: event(signal: count); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b71dab5c25..f5c758a517 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -129,6 +129,7 @@ set(BIF_SRCS bro.bif event.bif const.bif + types.bif common-rw.bif finger-rw.bif ident-rw.bif diff --git a/src/NetVar.cc b/src/NetVar.cc index 0af742ef3e..7fb424a03e 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -261,6 +261,7 @@ RecordType* script_id; TableType* id_table; #include "const.bif.netvar_def" +#include "types.bif.netvar_def" #include "event.bif.netvar_def" void init_event_handlers() @@ -316,6 +317,7 @@ void init_general_global_var() void init_net_var() { #include "const.bif.netvar_init" +#include "types.bif.netvar_init" conn_id = internal_type("conn_id")->AsRecordType(); endpoint = internal_type("endpoint")->AsRecordType(); diff --git a/src/NetVar.h b/src/NetVar.h index 7461ec8be0..2de1962f4d 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -271,6 +271,7 @@ extern void init_event_handlers(); extern void init_net_var(); #include "const.bif.netvar_h" +#include "types.bif.netvar_h" #include "event.bif.netvar_h" #endif diff --git a/src/const.bif b/src/const.bif index 2c4f2d1f1c..f6aef299ea 100644 --- a/src/const.bif +++ b/src/const.bif @@ -44,54 +44,3 @@ const dump_selected_source_packets = F &redef; # (TODO: this variable should be disabled when using '-A' option) const dump_original_packets_if_not_rewriting = F &redef; -enum dce_rpc_ptype %{ - DCE_RPC_REQUEST, - DCE_RPC_PING, - DCE_RPC_RESPONSE, - DCE_RPC_FAULT, - DCE_RPC_WORKING, - DCE_RPC_NOCALL, - DCE_RPC_REJECT, - DCE_RPC_ACK, - DCE_RPC_CL_CANCEL, - DCE_RPC_FACK, - DCE_RPC_CANCEL_ACK, - DCE_RPC_BIND, - DCE_RPC_BIND_ACK, - DCE_RPC_BIND_NAK, - DCE_RPC_ALTER_CONTEXT, - DCE_RPC_ALTER_CONTEXT_RESP, - DCE_RPC_SHUTDOWN, - DCE_RPC_CO_CANCEL, - DCE_RPC_ORPHANED, -%} - -enum dce_rpc_if_id %{ - DCE_RPC_unknown_if, - DCE_RPC_epmapper, - DCE_RPC_lsarpc, - DCE_RPC_lsa_ds, - DCE_RPC_mgmt, - DCE_RPC_netlogon, - DCE_RPC_samr, - DCE_RPC_srvsvc, - DCE_RPC_spoolss, - DCE_RPC_drs, - DCE_RPC_winspipe, - DCE_RPC_wkssvc, - DCE_RPC_oxid, - DCE_RPC_ISCMActivator, -%} - -enum rpc_status %{ - RPC_SUCCESS, - RPC_PROG_UNAVAIL, - RPC_PROG_MISMATCH, - RPC_PROC_UNAVAIL, - RPC_GARBAGE_ARGS, - RPC_SYSTEM_ERR, - RPC_TIMEOUT, - RPC_VERS_MISMATCH, - RPC_AUTH_ERROR, - RPC_UNKNOWN_ERROR, -%} diff --git a/src/types.bif b/src/types.bif new file mode 100644 index 0000000000..7b60192155 --- /dev/null +++ b/src/types.bif @@ -0,0 +1,52 @@ + +enum dce_rpc_ptype %{ + DCE_RPC_REQUEST, + DCE_RPC_PING, + DCE_RPC_RESPONSE, + DCE_RPC_FAULT, + DCE_RPC_WORKING, + DCE_RPC_NOCALL, + DCE_RPC_REJECT, + DCE_RPC_ACK, + DCE_RPC_CL_CANCEL, + DCE_RPC_FACK, + DCE_RPC_CANCEL_ACK, + DCE_RPC_BIND, + DCE_RPC_BIND_ACK, + DCE_RPC_BIND_NAK, + DCE_RPC_ALTER_CONTEXT, + DCE_RPC_ALTER_CONTEXT_RESP, + DCE_RPC_SHUTDOWN, + DCE_RPC_CO_CANCEL, + DCE_RPC_ORPHANED, +%} + +enum dce_rpc_if_id %{ + DCE_RPC_unknown_if, + DCE_RPC_epmapper, + DCE_RPC_lsarpc, + DCE_RPC_lsa_ds, + DCE_RPC_mgmt, + DCE_RPC_netlogon, + DCE_RPC_samr, + DCE_RPC_srvsvc, + DCE_RPC_spoolss, + DCE_RPC_drs, + DCE_RPC_winspipe, + DCE_RPC_wkssvc, + DCE_RPC_oxid, + DCE_RPC_ISCMActivator, +%} + +enum rpc_status %{ + RPC_SUCCESS, + RPC_PROG_UNAVAIL, + RPC_PROG_MISMATCH, + RPC_PROC_UNAVAIL, + RPC_GARBAGE_ARGS, + RPC_SYSTEM_ERR, + RPC_TIMEOUT, + RPC_VERS_MISMATCH, + RPC_AUTH_ERROR, + RPC_UNKNOWN_ERROR, +%} From 663552a3cd7de2628efc1cb11aed28f2424d6bcd Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 12:32:24 -0800 Subject: [PATCH 16/23] Enable declaration of set, vector, and table types in bifs. Extends the possibility of declaring record types, e.g., type NAME: set; One can only *declare* but not *define* the type in the bif. --- src/builtin-func.l | 3 +++ src/builtin-func.y | 61 +++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/builtin-func.l b/src/builtin-func.l index a5e37441cf..782bbf5bb9 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -73,6 +73,9 @@ HEX [0-9a-fA-F]+ "enum" return check_c_mode(TOK_ENUM); "type" return check_c_mode(TOK_TYPE); "record" return check_c_mode(TOK_RECORD); +"set" return check_c_mode(TOK_SET); +"table" return check_c_mode(TOK_TABLE); +"vector" return check_c_mode(TOK_VECTOR); "module" return check_c_mode(TOK_MODULE); "@ARG@" return TOK_ARG; diff --git a/src/builtin-func.y b/src/builtin-func.y index f9117f97fc..2a40a661c2 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -29,6 +29,7 @@ extern FILE* fp_netvar_init; int in_c_code = 0; string current_module = GLOBAL_MODULE_NAME; int definition_type; +string type_name; enum { @@ -36,9 +37,8 @@ enum { FUNC_DEF, REWRITER_DEF, EVENT_DEF, - ENUM_DEF, + TYPE_DEF, CONST_DEF, - RECORD_DEF, }; // Holds the name of a declared object (function, enum, record type, event, @@ -60,9 +60,13 @@ struct decl_struct { string generate_c_namespace_end; } decl; -void set_definition_type(int type) +void set_definition_type(int type, const char *arg_type_name) { definition_type = type; + if (type == TYPE_DEF && arg_type_name) + type_name = string(arg_type_name); + else + type_name = ""; } void set_decl_name(const char *name) @@ -82,15 +86,10 @@ void set_decl_name(const char *name) decl.generate_c_namespace_end = ""; switch ( definition_type ) { - case ENUM_DEF: - decl.c_namespace_start = "namespace BifTypePtr { namespace Enum { "; + case TYPE_DEF: + decl.c_namespace_start = "namespace BifTypePtr { namespace " + type_name + "{ "; decl.c_namespace_end = " } }"; - decl.c_fullname = "BifTypePtr::Enum::"; - break; - case RECORD_DEF: - decl.c_namespace_start = "namespace BifTypePtr { namespace Record { "; - decl.c_namespace_end = " } }"; - decl.c_fullname = "BifTypePtr::Record::"; + decl.c_fullname = "BifTypePtr::" + type_name + "::"; break; case CONST_DEF: @@ -255,7 +254,7 @@ void print_event_c_body(FILE *fp) %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG %token TOK_BOOL %token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM -%token TOK_TYPE TOK_RECORD TOK_MODULE +%token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_TABLE TOK_MODULE %token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE %token TOK_ARGS TOK_ARG TOK_ARGC %token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT @@ -330,21 +329,33 @@ module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' // extend the bif-language to be able to handle that all.... // Or we just support a simple form of record type definitions // TODO: add other types (tables, sets) -type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws TOK_RECORD opt_ws ';' +type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' { - set_definition_type(RECORD_DEF); set_decl_name($3); - fprintf(fp_netvar_h, "%s extern RecordType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s RecordType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_h, "%s extern %sType * %s; %s\n", + decl.c_namespace_start.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s %sType * %s; %s\n", + decl.c_namespace_start.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = internal_type(\"%s\")->AsRecordType();\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + "\t%s = internal_type(\"%s\")->As%sType();\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str(), + type_name.c_str()); } ; +type_def_types: TOK_RECORD + { set_definition_type(TYPE_DEF, "Record"); } + | TOK_SET + { set_definition_type(TYPE_DEF, "Set"); } + | TOK_VECTOR + { set_definition_type(TYPE_DEF, "Vector"); } + | TOK_TABLE + { set_definition_type(TYPE_DEF, "Table"); } + ; + event_def: event_prefix opt_ws plain_head opt_attr end_of_head ';' { print_event_c_prototype(fp_func_h, true); @@ -380,7 +391,7 @@ enum_def: enum_def_1 enum_list TOK_RPB enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws { - set_definition_type(ENUM_DEF); + set_definition_type(TYPE_DEF, "Enum"); set_decl_name($3); fprintf(fp_bro_init, "type %s: enum %s{%s", decl.bro_name.c_str(), $4, $6); @@ -421,7 +432,7 @@ const_def: const_def_1 const_init opt_attr ';' const_def_1: TOK_CONST opt_ws TOK_ID opt_ws { - set_definition_type(CONST_DEF); + set_definition_type(CONST_DEF, 0); set_decl_name($3); fprintf(fp_bro_init, "const%s", $2); fprintf(fp_bro_init, "%s: bool%s", decl.bro_name.c_str(), $4); @@ -447,15 +458,15 @@ opt_attr: /* nothing */ ; func_prefix: TOK_FUNCTION - { set_definition_type(FUNC_DEF); } + { set_definition_type(FUNC_DEF, 0); } ; rewriter_prefix: TOK_REWRITER - { set_definition_type(REWRITER_DEF); } + { set_definition_type(REWRITER_DEF, 0); } ; event_prefix: TOK_EVENT - { set_definition_type(EVENT_DEF); } + { set_definition_type(EVENT_DEF, 0); } ; end_of_head: /* nothing */ From b2243109701e8ce08a6b61f6acffd546e1c029bb Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 15:04:36 -0800 Subject: [PATCH 17/23] Fix to bifcl wrt namespaces. --- src/builtin-func.y | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/builtin-func.y b/src/builtin-func.y index 2a40a661c2..9a4ba5cf5b 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -71,8 +71,12 @@ void set_definition_type(int type, const char *arg_type_name) void set_decl_name(const char *name) { - decl.module_name = extract_module_name(name); decl.bare_name = extract_var_name(name); + + // make_full_var_name prepends the correct module, if any + // then we can extract the module name again. + string varname = make_full_var_name(current_module.c_str(), name); + decl.module_name = extract_module_name(varname.c_str()); decl.c_namespace_start = ""; decl.c_namespace_end = ""; @@ -317,8 +321,8 @@ definition: event_def module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' { - current_module = $2; - fprintf(fp_bro_init, "module %s;\n", $2); + current_module = string($3); + fprintf(fp_bro_init, "module %s;\n", $3); } // XXX: Add the netvar glue so that the event engine knows about From fe0ae22eef1c19b9cd10539d569944c04e01c349 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Fri, 11 Feb 2011 22:02:02 -0800 Subject: [PATCH 18/23] Tweak for bifcl --- src/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtin-func.y b/src/builtin-func.y index 9a4ba5cf5b..5b6aa0cec4 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -122,7 +122,7 @@ void set_decl_name(const char *name) case EVENT_DEF: decl.c_namespace_start = ""; decl.c_namespace_end = ""; - decl.c_fullname = ""; + decl.c_fullname = "::"; // need this for namespace qualified events due do event_c_body decl.generate_c_namespace_start = "namespace BifEvent { "; decl.generate_c_namespace_end = " } "; decl.generate_c_fullname = "BifEvent::"; From 782f007b5caa9489b2474c5901b8b964e4f1c0cf Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Mon, 14 Feb 2011 10:10:40 -0800 Subject: [PATCH 19/23] Support any type in bif const declaration. Revamp of const delcaration in bifs: * Can only declare are const in the bif, but we cannot assign a value or attribute to it. One has to do this in a policy file (bro.init) * Type specification in bif is now mandatory * Support any type in bifs (previously only bools were supported). This will also help with automatic documentation generation, since all const are now defined in the policy layer and thus can be documented from there. The bif just gives the C++ layer easy access. --- policy/bro.init | 46 ++++++++++++++++++++++++++++++ src/builtin-func.l | 1 + src/builtin-func.y | 71 +++++++++++++++++++++++++++++++--------------- src/const.bif | 30 ++++++++++---------- 4 files changed, 110 insertions(+), 38 deletions(-) diff --git a/policy/bro.init b/policy/bro.init index 3b3378c5ac..fbc5282a9b 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -1390,3 +1390,49 @@ const trace_output_file = ""; # packets out before we actually process them, which can be helpful # for debugging in case the analysis triggers a crash. const record_all_packets = F &redef; + + +# Some connections (e.g., SSH) retransmit the acknowledged last +# byte to keep the connection alive. If ignore_keep_alive_rexmit +# is set to T, such retransmissions will be excluded in the rexmit +# counter in conn_stats. +const ignore_keep_alive_rexmit = F &redef; + +# Skip HTTP data portions for performance considerations (the skipped +# portion will not go through TCP reassembly). +const skip_http_data = F &redef; + +# Whether the analysis engine parses IP packets encapsulated in +# UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro. +const parse_udp_tunnels = F &redef; + +# Whether a commitment is required before writing the transformed +# trace for a connection into the dump file. +const requires_trace_commitment = F &redef; + +# Whether IP address anonymization is enabled. +const anonymize_ip_addr = F &redef; + +# Whether to omit place holder packets when rewriting. +const omit_rewrite_place_holder = T &redef; + +# Whether trace of various protocols is being rewritten. +const rewriting_http_trace = F &redef; +const rewriting_smtp_trace = F &redef; +const rewriting_ftp_trace = F &redef; +const rewriting_ident_trace = F &redef; +const rewriting_finger_trace = F &redef; +const rewriting_dns_trace = F &redef; +const rewriting_smb_trace = F &redef; + +# Whether we dump selected original packets to the output trace. +const dump_selected_source_packets = F &redef; + +# If true, we dump original packets to the output trace *if and only if* +# the connection is not rewritten; if false, the policy script can decide +# whether to dump a particular connection by calling dump_packets_of_connection. +# +# NOTE: DO NOT SET THIS TO TRUE WHEN ANONYMIZING A TRACE! +# (TODO: this variable should be disabled when using '-A' option) +const dump_original_packets_if_not_rewriting = F &redef; + diff --git a/src/builtin-func.l b/src/builtin-func.l index 782bbf5bb9..972f4aad8f 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -37,6 +37,7 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) D [[:digit:]]+ HEX [0-9a-fA-F]+ + %option nodefault %% diff --git a/src/builtin-func.y b/src/builtin-func.y index 5b6aa0cec4..3fe67db1dd 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -159,6 +159,31 @@ const char* trace_rewriter_name = "trace_rewriter"; #include "bif_arg.h" +/* Map bif/bro type names to C types for use in const declaration */ +static struct { + const char* bif_type; + const char* bro_type; + const char* c_type; + const char* accessor; + const char* constructor; +} builtin_types[] = { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ + {bif_type, bro_type, c_type, accessor, constructor}, +#include "bif_type.def" +#undef DEFINE_BIF_TYPE +}; + +int get_type_index(const char *type_name) + { + for ( int i = 0; builtin_types[i].bif_type[0] != '\0'; ++i ) + { + if (strcmp(builtin_types[i].bif_type, type_name) == 0) + return i; + } + return TYPE_OTHER; + } + + int var_arg; // whether the number of arguments is variable std::vector args; @@ -422,33 +447,33 @@ enum_list: enum_list TOK_ID opt_ws ',' opt_ws | /* nothing */ ; -const_def: const_def_1 const_init opt_attr ';' - { - fprintf(fp_bro_init, ";\n"); - fprintf(fp_netvar_h, "%s extern int %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s int %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = internal_val(\"%s\")->AsBool();\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - } - ; -const_def_1: TOK_CONST opt_ws TOK_ID opt_ws +const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' { set_definition_type(CONST_DEF, 0); set_decl_name($3); - fprintf(fp_bro_init, "const%s", $2); - fprintf(fp_bro_init, "%s: bool%s", decl.bro_name.c_str(), $4); + int typeidx = get_type_index($7); + char accessor[1024]; + + snprintf(accessor, sizeof(accessor), builtin_types[typeidx].accessor, ""); + + + fprintf(fp_netvar_h, "%s extern %s %s; %s\n", + decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s %s %s; %s\n", + decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, "\t%s = internal_val(\"%s\")%s;\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str(), + accessor); } - ; - -opt_const_init: /* nothing */ - | const_init - ; - + + /* Currently support only boolean and string values */ -const_init: '=' opt_ws TOK_BOOL opt_ws +opt_attr_init: '=' opt_ws TOK_BOOL opt_ws { fprintf(fp_bro_init, "=%s%c%s", $2, ($3) ? 'T' : 'F', $4); } @@ -458,7 +483,7 @@ const_init: '=' opt_ws TOK_BOOL opt_ws opt_attr: /* nothing */ | opt_attr TOK_ATTR { fprintf(fp_bro_init, "%s", $2); } - opt_ws opt_const_init + opt_ws opt_attr_init ; func_prefix: TOK_FUNCTION @@ -533,7 +558,7 @@ head_1: TOK_ID opt_ws arg_begin decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_func_h, - "%sextern Val* %s(Frame* frame, val_list*);\n %s", + "%sextern Val* %s(Frame* frame, val_list*);%s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, diff --git a/src/const.bif b/src/const.bif index f6aef299ea..6d757c1cd8 100644 --- a/src/const.bif +++ b/src/const.bif @@ -4,37 +4,37 @@ # byte to keep the connection alive. If ignore_keep_alive_rexmit # is set to T, such retransmissions will be excluded in the rexmit # counter in conn_stats. -const ignore_keep_alive_rexmit = F &redef; +const ignore_keep_alive_rexmit: bool; # Skip HTTP data portions for performance considerations (the skipped # portion will not go through TCP reassembly). -const skip_http_data = F &redef; +const skip_http_data: bool; # Whether the analysis engine parses IP packets encapsulated in # UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro. -const parse_udp_tunnels = F &redef; +const parse_udp_tunnels: bool; # Whether a commitment is required before writing the transformed # trace for a connection into the dump file. -const requires_trace_commitment = F &redef; +const requires_trace_commitment: bool; # Whether IP address anonymization is enabled. -const anonymize_ip_addr = F &redef; +const anonymize_ip_addr: bool; # Whether to omit place holder packets when rewriting. -const omit_rewrite_place_holder = T &redef; +const omit_rewrite_place_holder : bool ; # Whether trace of various protocols is being rewritten. -const rewriting_http_trace = F &redef; -const rewriting_smtp_trace = F &redef; -const rewriting_ftp_trace = F &redef; -const rewriting_ident_trace = F &redef; -const rewriting_finger_trace = F &redef; -const rewriting_dns_trace = F &redef; -const rewriting_smb_trace = F &redef; +const rewriting_http_trace :bool; +const rewriting_smtp_trace: bool; +const rewriting_ftp_trace: bool; +const rewriting_ident_trace: bool; +const rewriting_finger_trace: bool; +const rewriting_dns_trace: bool; +const rewriting_smb_trace: bool; # Whether we dump selected original packets to the output trace. -const dump_selected_source_packets = F &redef; +const dump_selected_source_packets: bool; # If true, we dump original packets to the output trace *if and only if* # the connection is not rewritten; if false, the policy script can decide @@ -42,5 +42,5 @@ const dump_selected_source_packets = F &redef; # # NOTE: DO NOT SET THIS TO TRUE WHEN ANONYMIZING A TRACE! # (TODO: this variable should be disabled when using '-A' option) -const dump_original_packets_if_not_rewriting = F &redef; +const dump_original_packets_if_not_rewriting: bool; From f3aa7b2fac4741541f4865ab7283d8a98511f17e Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Mon, 14 Feb 2011 10:43:26 -0800 Subject: [PATCH 20/23] Bif const: make sure const is indeed a constant. --- src/Var.cc | 11 +++++++++++ src/Var.h | 1 + src/builtin-func.y | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Var.cc b/src/Var.cc index b107156b3a..b7f065044b 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -343,6 +343,17 @@ Val* internal_val(const char* name) return id->ID_Val(); } +Val* internal_const_val(const char* name) + { + ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); + if ( ! id ) + internal_error("internal variable %s missing", name); + if ( ! id->IsConst()) + internal_error("internal variable %s is not constant", name); + + return id->ID_Val(); + } + Val* opt_internal_val(const char* name) { ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); diff --git a/src/Var.h b/src/Var.h index 3be8ecc079..f1cbcda87b 100644 --- a/src/Var.h +++ b/src/Var.h @@ -27,6 +27,7 @@ extern void begin_func(ID* id, const char* module_name, function_flavor flavor, extern void end_func(Stmt* body, attr_list* attrs = 0); extern Val* internal_val(const char* name); +extern Val* internal_const_val(const char* name); // internal error if not const extern Val* opt_internal_val(const char* name); // returns nil if not defined extern double opt_internal_double(const char* name); extern bro_int_t opt_internal_int(const char* name); diff --git a/src/builtin-func.y b/src/builtin-func.y index 3fe67db1dd..cfd5459bb1 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -466,7 +466,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_namespace_start.c_str(), builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = internal_val(\"%s\")%s;\n", + fprintf(fp_netvar_init, "\t%s = internal_const_val(\"%s\")%s;\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), accessor); } From e310119ffa0dd5a741fa1a5f636ab173b91177f0 Mon Sep 17 00:00:00 2001 From: Gregor Maier Date: Tue, 22 Feb 2011 14:52:21 -0800 Subject: [PATCH 21/23] Refactor: BifTypePtr --> BifType As per our mail discussion renaming BifTypePtr namespace to BifType. --- src/DCE_RPC.cc | 4 ++-- src/Portmap.cc | 2 +- src/builtin-func.y | 4 ++-- src/portmap-analyzer.pac | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DCE_RPC.cc b/src/DCE_RPC.cc index c8b715351c..c44b100aa5 100644 --- a/src/DCE_RPC.cc +++ b/src/DCE_RPC.cc @@ -234,7 +234,7 @@ void DCE_RPC_Session::DeliverPDU(int is_orig, int len, const u_char* data) val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new Val(is_orig, TYPE_BOOL)); - vl->append(new EnumVal(data[2], BifTypePtr::Enum::dce_rpc_ptype)); + vl->append(new EnumVal(data[2], BifType::Enum::dce_rpc_ptype)); vl->append(new StringVal(len, (const char*) data)); analyzer->ConnectionEvent(dce_rpc_message, vl); @@ -296,7 +296,7 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(new StringVal(if_uuid.to_string())); - // vl->append(new EnumVal(if_id, BifTypePtr::Enum::dce_rpc_if_id)); + // vl->append(new EnumVal(if_id, BifType::Enum::dce_rpc_if_id)); analyzer->ConnectionEvent(dce_rpc_bind, vl); } diff --git a/src/Portmap.cc b/src/Portmap.cc index 7e2c06c9a6..bcf52daf4e 100644 --- a/src/Portmap.cc +++ b/src/Portmap.cc @@ -288,7 +288,7 @@ void PortmapperInterp::Event(EventHandlerPtr f, Val* request, int status, Val* r } else { - vl->append(new EnumVal(status, BifTypePtr::Enum::rpc_status)); + vl->append(new EnumVal(status, BifType::Enum::rpc_status)); if ( request ) vl->append(request); } diff --git a/src/builtin-func.y b/src/builtin-func.y index cfd5459bb1..e5f5bf74fa 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -91,9 +91,9 @@ void set_decl_name(const char *name) switch ( definition_type ) { case TYPE_DEF: - decl.c_namespace_start = "namespace BifTypePtr { namespace " + type_name + "{ "; + decl.c_namespace_start = "namespace BifType { namespace " + type_name + "{ "; decl.c_namespace_end = " } }"; - decl.c_fullname = "BifTypePtr::" + type_name + "::"; + decl.c_fullname = "BifType::" + type_name + "::"; break; case CONST_DEF: diff --git a/src/portmap-analyzer.pac b/src/portmap-analyzer.pac index dc02ec1458..a7b64ada5d 100644 --- a/src/portmap-analyzer.pac +++ b/src/portmap-analyzer.pac @@ -150,7 +150,7 @@ function PortmapCallFailed(connection: RPC_Conn, status: EnumRPCStatus): bool %{ // BifEnum::rpc_status st = static_cast(status); - Val *st = new EnumVal(status, BifTypePtr::Enum::rpc_status); + Val *st = new EnumVal(status, BifType::Enum::rpc_status); switch ( call->proc() ) { case PMAPPROC_NULL: From 3527daea5b100955242e983c7e4f207302b2fa8d Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 25 Feb 2011 15:48:31 -0800 Subject: [PATCH 22/23] Updating submodule(s). --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aux/binpac b/aux/binpac index 26d02716f9..c3c7ef0dfd 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 26d02716f9090651f319a4bfdf8ede49b3a7b53a +Subproject commit c3c7ef0dfddb0746d3762e41086ba42928e68483 diff --git a/aux/bro-aux b/aux/bro-aux index 7e50bac938..98f92eeb40 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 7e50bac938af1831ecf9660159145a3c2e77e13d +Subproject commit 98f92eeb40281045159097764abddc428fb49bf2 diff --git a/aux/broccoli b/aux/broccoli index a1c6b6e59b..48d473398e 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit a1c6b6e59b3087b6b79a37a847c669b61ae2c522 +Subproject commit 48d473398e577893b6c7f77d605ccdf266a2f93b diff --git a/aux/broctl b/aux/broctl index fc940bbb72..0b8ecaec36 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit fc940bbb72abbaef2e5f10ea4ab616ec9b61fe0a +Subproject commit 0b8ecaec3652ed2ea2bd7580062eabe5a1e051d1 From 226eeb97295cf3eac18d3928b86108b9ab39c68c Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 25 Feb 2011 15:49:08 -0800 Subject: [PATCH 23/23] Updating submodule(s). --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 0b8ecaec36..532dcd5aa5 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 0b8ecaec3652ed2ea2bd7580062eabe5a1e051d1 +Subproject commit 532dcd5aa51c8b29b2d71cd37e1d7c21e33cc715