diff --git a/CHANGES b/CHANGES index d12cd02ebb..cf1a73f9c3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,32 @@ +1.6-dev.49 Fri Feb 25 15:37:28 PST 2011 + +- Enum IDs can have explicitly defined values. (Gregor Maier) + +- Extensions for the built-in function compiler, bifcl. (Gregor Maier) + + * Support for policy-layer namespaces. + * Support for type declarations in bif files (with access them + from C++) + * Extended const declarations in bif files. + + See http://bro.icir.org/devel/bif-doc for more information. + +1.6-dev.48 Fri Feb 25 10:53:04 PST 2011 + +- Preliminary TCP Reassembler fix: deliver data after 2GB by disabling + the unused seq_to_skip feature. (Gregor Maier) + +1.6-dev.47 Fri Feb 25 10:40:22 PST 2011 + +- Fixing endianess error in XDR when data is not 4-byte aligned. + (Gregor Maier) + +- Fix for Val constructor with new int64 typedefs. (Gregor Maier) + +- Updated fix for OS X 10.5 compile error wrt llabs(). (Gregor Maier) + +- Fix more compiler warning wrt printf format strings. (Gregor Maier) + 1.6-dev.45 Tue Feb 8 21:28:01 PST 2011 - Fixing a number of compiler warnings. (Seth Hall and Robin Sommer) diff --git a/VERSION b/VERSION index e80e9b3ff5..d03fa32fe3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6-dev.45 +1.6-dev.49 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..532dcd5aa5 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit fc940bbb72abbaef2e5f10ea4ab616ec9b61fe0a +Subproject commit 532dcd5aa51c8b29b2d71cd37e1d7c21e33cc715 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/policy/bro.init b/policy/bro.init index 16904d91b7..02aad1a0cb 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); @@ -1438,3 +1439,47 @@ const trace_output_file = ""; # 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/CMakeLists.txt b/src/CMakeLists.txt index af34a08b5f..b9ec957ae6 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}) @@ -101,8 +101,9 @@ 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} + DEPENDS bifcl COMMENT "[BIFCL] Processing ${bifInput}" ) list(APPEND ALL_BIF_OUTPUTS ${bifOutputs}) @@ -128,6 +129,7 @@ set(BIF_SRCS bro.bif event.bif const.bif + types.bif common-rw.bif finger-rw.bif ident-rw.bif @@ -239,6 +241,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 62f7806c51..c44b100aa5 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], 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); @@ -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, enum_dce_rpc_if_id)); + // vl->append(new EnumVal(if_id, BifType::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 d9c3aa7bdf..310b61efd2 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -507,6 +507,17 @@ 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" @@ -534,7 +545,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/NetVar.cc b/src/NetVar.cc index 231d2efe78..b164b2cdda 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -263,6 +263,7 @@ TableType* id_table; RecordType* log_filter; #include "const.bif.netvar_def" +#include "types.bif.netvar_def" #include "event.bif.netvar_def" void init_event_handlers() @@ -299,7 +300,7 @@ void init_general_global_var() ssl_passphrase = internal_val("ssl_passphrase")->AsStringVal(); packet_filter_default = opt_internal_int("packet_filter_default"); - + sig_max_group_size = opt_internal_int("sig_max_group_size"); enable_syslog = opt_internal_int("enable_syslog"); @@ -318,6 +319,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 ccd8294882..2ddb855b52 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -273,6 +273,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/Portmap.cc b/src/Portmap.cc index af9383297f..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, enum_rpc_status)); + vl->append(new EnumVal(status, BifType::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/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/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..ca86a5ec1f 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -11,6 +11,7 @@ #include "Obj.h" #include "BroList.h" #include "TraverseTypes.h" +#include "module_util.h" class ID; class BroType; @@ -59,14 +60,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/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/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_Reassembler.cc b/src/TCP_Reassembler.cc index c6adec2294..31e95676d0 100644 --- a/src/TCP_Reassembler.cc +++ b/src/TCP_Reassembler.cc @@ -9,6 +9,13 @@ // Only needed for gap_report events. #include "Event.h" +// Note, sequence numbers are relative. I.e., they start with 1. + +// TODO: The Reassembler should start using 64 bit ints for keeping track of +// sequence numbers; currently they become negative once 2GB are exceeded. +// +// See #348 for more information. + const bool DEBUG_tcp_contents = false; const bool DEBUG_tcp_connection_close = false; const bool DEBUG_tcp_match_undelivered = false; @@ -35,7 +42,9 @@ TCP_Reassembler::TCP_Reassembler(Analyzer* arg_dst_analyzer, deliver_tcp_contents = 0; skip_deliveries = 0; did_EOF = 0; +#ifdef ENABLE_SEQ_TO_SKIP seq_to_skip = 0; +#endif in_delivery = false; if ( tcp_contents ) @@ -120,7 +129,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 +138,16 @@ 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 +162,17 @@ 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 ) - return; + // This should never happen. + internal_error("Calling Undelivered for data that has already been delivered (or has already been marked as undelivered"); if ( last_reassem_seq == 1 && (endpoint->FIN_cnt > 0 || endpoint->RST_cnt > 0 || @@ -177,9 +196,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 +395,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 +438,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 +496,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,6 +587,7 @@ void TCP_Reassembler::CheckEOF() void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) { +#ifdef ENABLE_SEQ_TO_SKIP if ( seq_delta(seq + len, seq_to_skip) <= 0 ) return; @@ -579,6 +598,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 +623,13 @@ void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) in_delivery = true; Deliver(seq, len, data); in_delivery = false; - +#ifdef ENABLE_SEQ_TO_SKIP if ( seq_delta(seq + len, seq_to_skip) < 0 ) SkipToSeq(seq_to_skip); +#endif } +#ifdef ENABLE_SEQ_TO_SKIP void TCP_Reassembler::SkipToSeq(int seq) { if ( seq_delta(seq, seq_to_skip) > 0 ) @@ -617,6 +639,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..772c5f6f9c 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 ENABLE_SEQ_TO_SKIP + class BroFile; class Connection; class TCP_Analyzer; @@ -60,9 +67,11 @@ public: void MatchUndelivered(int up_to_seq = -1); +#ifdef ENABLE_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 ENABLE_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 ENABLE_SEQ_TO_SKIP int seq_to_skip; +#endif bool in_delivery; BroFile* record_contents_file; // file on which to reassemble contents 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/Type.cc b/src/Type.cc index 4c3d5bba8f..ea39f106c2 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1084,10 +1084,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; } @@ -1097,9 +1096,47 @@ EnumType::~EnumType() delete [] iter->first; } -int EnumType::AddName(const string& module_name, const char* name) +// Note, we use error() here (not Error()) to include the current script +// location in the error message, rather than the one where the type was +// originally defined. +void EnumType::AddName(const string& module_name, const char* name, bool is_export) { - ID* id = lookup_ID(name, module_name.c_str()); + /* implicit, auto-increment */ + if ( counter < 0) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + SetError(); + 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) + { + /* explicit value specified */ + error_t rv; + if ( counter > 0 ) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + SetError(); + return; + } + counter = -1; + AddNameInternal(module_name, name, val, is_export); + } + +void EnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export) + { + ID *id; + if ( Lookup(val) ) + { + error("enumerator value in enumerated type definition already exists"); + SetError(); + return; + } + + id = lookup_ID(name, module_name.c_str()); if ( ! id ) { id = install_ID(name, module_name.c_str(), true, is_export); @@ -1108,31 +1145,16 @@ int EnumType::AddName(const string& module_name, const char* name) } else { - debug_msg("identifier already exists: %s\n", name); - return -1; + error("identifier or enumerator value in enumerated type definition already exists"); + SetError(); + return; } 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; } -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()); @@ -1143,7 +1165,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 ) @@ -1159,9 +1181,9 @@ 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)) ) + // Dummy boolean for backwards compatibility. + SERIALIZE(false)) ) return false; for ( NameMap::const_iterator iter = names.begin(); @@ -1179,15 +1201,17 @@ bool EnumType::DoUnserialize(UnserialInfo* info) DO_UNSERIALIZE(BroType); unsigned int len; + bool dummy; if ( ! UNSERIALIZE(&counter) || ! UNSERIALIZE(&len) || - ! UNSERIALIZE(&is_export) ) + // Dummy boolean for backwards compatibility. + ! UNSERIALIZE(&dummy) ) 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 8901380ab7..b93fcaa6d7 100644 --- a/src/Type.h +++ b/src/Type.h @@ -480,31 +480,37 @@ 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); + // The value of this name is next internal counter value, starting + // with zero. The internal counter is incremented. + void 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. Once a value has been + // explicitly assigned using this method, no further names can be + // added that aren't likewise explicitly initalized. + void 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; + 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; - int counter; - bool is_export; + + // The counter is initialized to 0 and incremented on every implicit + // auto-increment name that gets added (thus its > 0 if + // auto-increment is used). Once an explicit value has been + // specified, the counter is set to -1. This way counter can be used + // as a flag to prevent mixing of auto-increment and explicit + // enumerator specifications. + bro_int_t counter; }; class VectorType : public BroType { 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/Val.cc b/src/Val.cc index dbc55856db..f7767714ac 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -515,11 +515,12 @@ 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 + // 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); diff --git a/src/Val.h b/src/Val.h index c056c4e630..75e96cb694 100644 --- a/src/Val.h +++ b/src/Val.h @@ -88,7 +88,7 @@ public: #endif } - Val(int i, TypeTag t) + Val(int32 i, TypeTag t) { val.int_val = bro_int_t(i); type = base_type(t); @@ -98,27 +98,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); diff --git a/src/Var.cc b/src/Var.cc index c9e497d8a5..573356ebdf 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -353,6 +353,18 @@ 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/XDR.cc b/src/XDR.cc index 4e6a05ff10..bea34b575e 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); diff --git a/src/bif_arg.cc b/src/bif_arg.cc index 2befed495a..5900c117eb 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) @@ -75,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") 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 a9459ea4a8..483ee4ee73 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" @@ -27,8 +28,15 @@ int check_c_mode(int t) %} WS [ \t]+ -ID [A-Za-z_](([A-Za-z_0-9]|::)*[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:]]+)) +DEC [[:digit:]]+ +HEX [0-9a-fA-F]+ + %option nodefault @@ -64,7 +72,12 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) "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); +"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; "@ARGS@" return TOK_ARGS; @@ -78,6 +91,17 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) "T" yylval.val = 1; return TOK_BOOL; "F" yylval.val = 0; return TOK_BOOL; +{DEC} { + 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; @@ -120,13 +144,20 @@ 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 +168,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 +188,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 +207,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..cbfb8b9798 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,131 @@ 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; +string type_name; + enum { C_SEGMENT_DEF, FUNC_DEF, REWRITER_DEF, EVENT_DEF, + TYPE_DEF, + CONST_DEF, }; -void set_definition_type(int type) +// 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, const char *arg_type_name) { definition_type = type; - switch ( type ) { - case FUNC_DEF: - bro_prefix = ""; - c_prefix = "bro_"; + if ( type == TYPE_DEF && arg_type_name ) + type_name = string(arg_type_name); + else + type_name = ""; + } + +void set_decl_name(const char *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 = ""; + 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 TYPE_DEF: + decl.c_namespace_start = "namespace BifType { namespace " + type_name + "{ "; + decl.c_namespace_end = " } }"; + decl.c_fullname = "BifType::" + type_name + "::"; + 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 = "::"; // 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::"; 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,13 +159,34 @@ const char* trace_rewriter_name = "trace_rewriter"; #include "bif_arg.h" -extern const char* decl_name; +/* 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; -// enum types declared by "declare enum " -set enum_types; - extern int yyerror(const char[]); extern int yywarn(const char msg[]); extern int yylex(); @@ -90,9 +207,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 ) { @@ -101,6 +224,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++. @@ -109,9 +236,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"); @@ -141,7 +268,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" @@ -149,20 +276,22 @@ 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 TOK_DECLARE +%token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM +%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 -%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 { @@ -172,6 +301,14 @@ void print_event_c_body(FILE *fp) %% +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 @@ -191,6 +328,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); } ; @@ -201,24 +339,58 @@ definition: event_def | c_code_segment | enum_def | const_def - | declare_def + | type_def + | module_def ; -declare_def: TOK_DECLARE opt_ws TOK_ENUM opt_ws TOK_ID opt_ws ';' + +module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' { - enum_types.insert($5); + current_module = string($3); + fprintf(fp_bro_init, "module %s;\n", $3); } + + // 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 declarations 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 type_def_types opt_ws ';' + { + set_decl_name($3); + + 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\")->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); - 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 ; @@ -230,24 +402,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, - "extern EnumType* enum_%s;\n", decl_name); - fprintf(fp_netvar_def, - "EnumType* enum_%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, - "\tenum_%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(TYPE_DEF, "Enum"); + 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); } ; @@ -257,33 +439,41 @@ 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 */ ; -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_init, "\t%s = internal_val(\"%s\")->AsBool();\n", - decl_name, decl_name); - } - ; -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 ';' { - decl_name = $3; - fprintf(fp_bro_init, "const%s", $2); - fprintf(fp_bro_init, "%s: bool%s", $3, $4); - } - ; + set_definition_type(CONST_DEF, 0); + set_decl_name($3); + 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_const_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); } @@ -293,19 +483,19 @@ 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 - { 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 */ @@ -346,7 +536,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 ) { @@ -358,40 +548,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*);%s\n", + 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. @@ -437,7 +624,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); } ; @@ -474,7 +661,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"); } @@ -484,7 +671,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"); } @@ -543,6 +730,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 @@ -565,7 +755,7 @@ 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[]) { @@ -605,7 +795,6 @@ int yyerror(const char msg[]) { print_msg(msg); - abort(); - exit(1); + err_exit(); return 0; } diff --git a/src/const.bif b/src/const.bif index 2c4f2d1f1c..64c99a54ba 100644 --- a/src/const.bif +++ b/src/const.bif @@ -1,97 +1,19 @@ # $Id: const.bif 3929 2007-01-14 00:37:59Z vern $ -# 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; +# Documentation and default values for these are located in policy/bro.dif. -# 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; - -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, -%} +const ignore_keep_alive_rexmit: bool; +const skip_http_data: bool; +const parse_udp_tunnels: bool; +const requires_trace_commitment: bool; +const anonymize_ip_addr: bool; +const omit_rewrite_place_holder: bool; +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; +const dump_selected_source_packets: bool; +const dump_original_packets_if_not_rewriting: bool; 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/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/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/module_util.cc b/src/module_util.cc new file mode 100644 index 0000000000..d9aa1af645 --- /dev/null +++ b/src/module_util.cc @@ -0,0 +1,62 @@ +// +// 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..4f957f2958 --- /dev/null +++ b/src/module_util.h @@ -0,0 +1,17 @@ +// +// These functions are used by both Bro and bifcl. +// + +#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); diff --git a/src/parse.y b/src/parse.y index 82ee3cadfb..a982935b2b 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,30 @@ 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,24 +570,49 @@ 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; + $$ = cur_enum_type; + cur_enum_type = NULL; } + ; - | enum_id_list ',' TOK_ID +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"); + else + cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export); + } - if ( $1->AsEnumType()->AddName(current_module, $3) < 1 ) - error("identifier in enumerated type definition already exists"); - $$ = $1; + | TOK_ID '=' '-' TOK_CONSTANT + { + /* We only accept counts as enumerator, but we want to return a nice + error message if users triy 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); + cur_enum_type->AddName(current_module, $1, is_export); } ; @@ -668,10 +717,11 @@ type: $$ = 0; } - | TOK_ENUM '{' enum_id_list opt_comma '}' + | TOK_ENUM '{' { set_location(@1); parser_new_enum(); } enum_body '}' { - set_location(@1, @4); - $$ = $3; + set_location(@1, @5); + $4->UpdateLocationEndInfo(@5); + $$ = $4; } | TOK_LIST @@ -801,21 +851,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 ';' { @@ -1251,7 +1289,7 @@ global_or_event_id: const char* module_name = resolving_global_ID ? current_module.c_str() : 0; - + $$ = install_ID($1, module_name, true, is_export); } diff --git a/src/portmap-analyzer.pac b/src/portmap-analyzer.pac index 1e7921a9ff..a7b64ada5d 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); - BroEnum::rpc_status st = (BroEnum::rpc_status) status; + // BifEnum::rpc_status st = static_cast(status); + Val *st = new EnumVal(status, BifType::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_); } 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, +%}