diff --git a/CHANGES b/CHANGES index d12cd02ebb..bfa5ab77f7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,40 @@ +1.6-dev.53 Fri Feb 25 17:03:05 PST 2011 + +- Fixing file detector leak in remote communication module. (Scott + Campbell) + +- Updating independent-state tests to work with new setup. (Robin + Sommer) + +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..6cbd1b507c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6-dev.45 +1.6-dev.53 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/policy/bro.init b/policy/bro.init index dd28ef25c0..2f193e0cf7 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); @@ -499,12 +500,12 @@ const tunnel_port = 0/udp &redef; # true these values are returned in the connection's endpoint # record val. # Defined in const.bif -redef use_conn_size_analyzer = F; +const use_conn_size_analyzer = F &redef; # Whether to include connection state history in the logs generated # by record_connection. # Defined in const.bif -redef record_state_history = F; +const record_state_history = F &redef; const UDP_INACTIVE = 0; const UDP_ACTIVE = 1; # means we've seen something from this endpoint @@ -1403,3 +1404,48 @@ const trace_output_file = ""; # packets out before we actually process them, which can be helpful # for debugging in case the analysis triggers a crash. const record_all_packets = F &redef; + +# Some connections (e.g., SSH) retransmit the acknowledged last +# byte to keep the connection alive. If ignore_keep_alive_rexmit +# is set to T, such retransmissions will be excluded in the rexmit +# counter in conn_stats. +const ignore_keep_alive_rexmit = F &redef; + +# Skip HTTP data portions for performance considerations (the skipped +# portion will not go through TCP reassembly). +const skip_http_data = F &redef; + +# Whether the analysis engine parses IP packets encapsulated in +# UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro. +const parse_udp_tunnels = F &redef; + +# Whether a commitment is required before writing the transformed +# trace for a connection into the dump file. +const requires_trace_commitment = F &redef; + +# Whether IP address anonymization is enabled. +const anonymize_ip_addr = F &redef; + +# Whether to omit place holder packets when rewriting. +const omit_rewrite_place_holder = T &redef; + +# Whether trace of various protocols is being rewritten. +const rewriting_http_trace = F &redef; +const rewriting_smtp_trace = F &redef; +const rewriting_ftp_trace = F &redef; +const rewriting_ident_trace = F &redef; +const rewriting_finger_trace = F &redef; +const rewriting_dns_trace = F &redef; +const rewriting_smb_trace = F &redef; + +# Whether we dump selected original packets to the output trace. +const dump_selected_source_packets = F &redef; + +# If true, we dump original packets to the output trace *if and only if* +# the connection is not rewritten; if false, the policy script can decide +# whether to dump a particular connection by calling dump_packets_of_connection. +# +# NOTE: DO NOT SET THIS TO TRUE WHEN ANONYMIZING A TRACE! +# (TODO: this variable should be disabled when using '-A' option) +const dump_original_packets_if_not_rewriting = F &redef; + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c869e9d4f..da7b1ca3a6 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/Conn.cc b/src/Conn.cc index d6f93f879a..7a6204b994 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -361,7 +361,7 @@ RecordVal* Connection::BuildConnVal() conn_val->Assign(5, new TableVal(string_set)); // service conn_val->Assign(6, new StringVal("")); // addl conn_val->Assign(7, new Val(0, TYPE_COUNT)); // hot - if (record_state_history) + if (BifConst::record_state_history) conn_val->Assign(8, new StringVal("")); // history. else conn_val->Assign(8, NULL); @@ -373,7 +373,7 @@ RecordVal* Connection::BuildConnVal() conn_val->Assign(3, new Val(start_time, TYPE_TIME)); // ### conn_val->Assign(4, new Val(last_time - start_time, TYPE_INTERVAL)); - if (record_state_history) + if (BifConst::record_state_history) conn_val->Assign(8, new StringVal(history.c_str())); conn_val->SetOrigin(this); diff --git a/src/ConnSizeAnalyzer.h b/src/ConnSizeAnalyzer.h index a7d8203d1b..753dd85c99 100644 --- a/src/ConnSizeAnalyzer.h +++ b/src/ConnSizeAnalyzer.h @@ -24,7 +24,7 @@ public: static Analyzer* InstantiateAnalyzer(Connection* conn) { return new ConnSize_Analyzer(conn); } - static bool Available() { return use_conn_size_analyzer ; } + static bool Available() { return BifConst::use_conn_size_analyzer ; } protected: virtual void DeliverPacket(int len, const u_char* data, bool is_orig, 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 5d71be2b0f..e4984d9788 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -496,6 +496,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" @@ -523,7 +534,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 0af742ef3e..a8644fc059 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -261,6 +261,7 @@ RecordType* script_id; TableType* id_table; #include "const.bif.netvar_def" +#include "types.bif.netvar_def" #include "event.bif.netvar_def" void init_event_handlers() @@ -297,7 +298,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"); @@ -316,6 +317,7 @@ void init_general_global_var() void init_net_var() { #include "const.bif.netvar_init" +#include "types.bif.netvar_init" conn_id = internal_type("conn_id")->AsRecordType(); endpoint = internal_type("endpoint")->AsRecordType(); diff --git a/src/NetVar.h b/src/NetVar.h index 7461ec8be0..2de1962f4d 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -271,6 +271,7 @@ extern void init_event_handlers(); extern void init_net_var(); #include "const.bif.netvar_h" +#include "types.bif.netvar_h" #include "event.bif.netvar_h" #endif diff --git a/src/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/RemoteSerializer.cc b/src/RemoteSerializer.cc index 15b1872680..ebf7157a3a 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -3582,6 +3582,7 @@ bool SocketComm::Listen(uint32 ip, uint16 port, bool expect_ssl) if ( bind(*listen_fd, (sockaddr*) &server, sizeof(server)) < 0 ) { Error(fmt("can't bind to port %d, %s", port, strerror(errno))); + close(*listen_fd); *listen_fd = -1; if ( errno == EADDRINUSE ) 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/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 6c0d566f16..be9c43a176 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 = @@ -91,7 +91,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() @@ -2113,7 +2113,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 55794dfce5..ce3bbc52af 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1082,10 +1082,9 @@ bool FileType::DoUnserialize(UnserialInfo* info) return yield != 0; } -EnumType::EnumType(bool arg_is_export) +EnumType::EnumType() : BroType(TYPE_ENUM) { - is_export = arg_is_export; counter = 0; } @@ -1095,9 +1094,46 @@ 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 */ + 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); @@ -1106,31 +1142,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()); @@ -1141,7 +1162,7 @@ int EnumType::Lookup(const string& module_name, const char* name) return pos->second; } -const char* EnumType::Lookup(int value) +const char* EnumType::Lookup(bro_int_t value) { for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter ) @@ -1157,9 +1178,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(); @@ -1177,15 +1198,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 ff4d3df9e6..fe4f7a5eb5 100644 --- a/src/Type.h +++ b/src/Type.h @@ -452,31 +452,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 2a53a32674..eab7842e74 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -517,7 +517,7 @@ Val* Val::SizeVal() const case TYPE_INTERNAL_INT: // 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) + if ( val.int_val < 0 ) return new Val(-val.int_val, TYPE_COUNT); else return new Val(val.int_val, TYPE_COUNT); diff --git a/src/Var.cc b/src/Var.cc index b107156b3a..04ef78c14c 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -343,6 +343,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 9e2074f1ac..bea34b575e 100644 --- a/src/XDR.cc +++ b/src/XDR.cc @@ -17,7 +17,7 @@ uint32 extract_XDR_uint32(const u_char*& buf, int& len) return 0; } - // takes care of alignment and endianess differences. + // Takes care of alignment and endianess differences. uint32 bits32 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; buf += 4; 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 ca7923b852..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]* + /* 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 7eba7c2291..2e6887bb65 100644 --- a/src/const.bif +++ b/src/const.bif @@ -1,107 +1,21 @@ # $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; - -# Whether to use the ConnSize analyzer to count the number of -# packets and IP-level bytes transfered by each endpoint. If -# true these values are returned in the connection's endpoint -# record val. -const use_conn_size_analyzer = F &redef; - -# Whether to include connection state history in the logs generated -# by record_connection. -const record_state_history = 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; +const use_conn_size_analyzer: bool; +const record_state_history: 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, +%} diff --git a/testing/istate/base/persistence-read/vars.log b/testing/istate/base/persistence-read/vars.log index 9a7d2c771e..129c730768 100644 --- a/testing/istate/base/persistence-read/vars.log +++ b/testing/istate/base/persistence-read/vars.log @@ -20,9 +20,9 @@ file "test" of string 2 } { -[3, GHI] = 103, [2, DEF] = 102, -[1, ABC] = 101 +[1, ABC] = 101, +[3, GHI] = 103 } { [12345] = /^?(12345)$?/, diff --git a/testing/istate/base/persistence-write/vars.log b/testing/istate/base/persistence-write/vars.log index 9a7d2c771e..129c730768 100644 --- a/testing/istate/base/persistence-write/vars.log +++ b/testing/istate/base/persistence-write/vars.log @@ -20,9 +20,9 @@ file "test" of string 2 } { -[3, GHI] = 103, [2, DEF] = 102, -[1, ABC] = 101 +[1, ABC] = 101, +[3, GHI] = 103 } { [12345] = /^?(12345)$?/, diff --git a/testing/istate/base/sync-rcv/remote.log b/testing/istate/base/sync-rcv/remote.log index 4feea4ccc3..01c0aa34cc 100644 --- a/testing/istate/base/sync-rcv/remote.log +++ b/testing/istate/base/sync-rcv/remote.log @@ -1,4 +1,4 @@ -xxxxxxxxxx.xxxxxx [info] [parent] pipe's socket buffer size is 8192, setting to 1048576 +xxxxxxxxxx.xxxxxx [info] [parent] raised pipe's socket buffer size from 126K to 1024K xxxxxxxxxx.xxxxxx [info] [parent] communication started, parent xxxxxxxxxx.xxxxxx [info] [parent] [#1/127.0.0.1:47757] added peer xxxxxxxxxx.xxxxxx [info] [child] [#1/127.0.0.1:47757] connected diff --git a/testing/istate/base/sync-rcv/vars.log b/testing/istate/base/sync-rcv/vars.log index 428ac7929d..a86d2a82da 100644 --- a/testing/istate/base/sync-rcv/vars.log +++ b/testing/istate/base/sync-rcv/vars.log @@ -20,9 +20,9 @@ file "test2" of string 2 } { -[3, GHI] = 103, [4, JKL] = 104, -[2, DEF] = 103 +[2, DEF] = 103, +[3, GHI] = 103 } { [12345] = /^?(12345)$?/, diff --git a/testing/istate/base/sync-send/vars.log b/testing/istate/base/sync-send/vars.log index 428ac7929d..a86d2a82da 100644 --- a/testing/istate/base/sync-send/vars.log +++ b/testing/istate/base/sync-send/vars.log @@ -20,9 +20,9 @@ file "test2" of string 2 } { -[3, GHI] = 103, [4, JKL] = 104, -[2, DEF] = 103 +[2, DEF] = 103, +[3, GHI] = 103 } { [12345] = /^?(12345)$?/, diff --git a/testing/istate/istate.py b/testing/istate/istate.py index 8c7b28fe4a..72b3eb4288 100755 --- a/testing/istate/istate.py +++ b/testing/istate/istate.py @@ -1,5 +1,5 @@ #! /usr/bin/env python -# +# # Tests persistence. # # $Id: istate.py,v 1.1.2.4 2005/10/11 22:31:42 sommer Exp $ @@ -14,82 +14,82 @@ import subprocess import tests optparser = optparse.OptionParser( usage = "%prog [options]", version = "0.1" ) -optparser.add_option( "-s", "--show-diff", action = "store_true", dest = "showdiff", +optparser.add_option( "-s", "--show-diff", action = "store_true", dest = "showdiff", default = False, help = "show diffs of mismatches" ) -optparser.add_option( "-b", "--new-base", action = "store_true", dest = "newbase", +optparser.add_option( "-b", "--new-base", action = "store_true", dest = "newbase", default = False, help = "create new baseline" ) -optparser.add_option( "-d", "--debug", action = "store_true", dest = "debug", +optparser.add_option( "-d", "--debug", action = "store_true", dest = "debug", default = False, help = "enable debug output" ) -optparser.add_option( "-t", "--set", action = "store", type = "string", dest = "set", +optparser.add_option( "-t", "--set", action = "store", type = "string", dest = "set", default = None, help = "only do given test set" ) - + ( tests.Options, args ) = optparser.parse_args() if len(args) != 0: optparser.error( "Wrong number of arguments" ) -########################################## +########################################## # Write persistent data and read it back. ########################################## if tests.testSet("persistence"): - tests.spawnBro("persistence-write", - ["-r", os.path.join(tests.Traces, "empty.trace"), + tests.spawnBro("persistence-write", + ["-r", os.path.join(tests.Traces, "empty.trace"), os.path.join(tests.Scripts, "vars-init.bro"), os.path.join(tests.Scripts, "vars-print.bro")]) tests.waitProc("persistence-write") tests.finishTest("persistence-write", ["stdout.log", "stderr.log", "vars.log"]) - tests.spawnBro("persistence-read", + tests.spawnBro("persistence-read", [os.path.join(tests.Scripts, "vars-declare.bro"), - os.path.join(tests.Scripts, "vars-print.bro")], + os.path.join(tests.Scripts, "vars-print.bro")], copy=[os.path.join(tests.workDir("persistence-write"), ".state")]) tests.waitProc("persistence-read") tests.finishTest("persistence-read", ["stdout.log", "stderr.log", "vars.log"]) tests.compareFiles("persistence-write", "persistence-read", ["vars.log"]) -########################################## +########################################## # Exchange events (clear-text). # -# The used trace contains two connections separated by a silence of a -# couple of seconds. We start the processes so that the events for the +# The used trace contains two connections separated by a silence of a +# couple of seconds. We start the processes so that the events for the # *second* one (which is a full HTTP connection) are exchanged. -########################################## +########################################## if tests.testSet("events"): - tests.spawnBro("events-send", - ["-r", os.path.join(tests.Scripts, os.path.join(tests.Traces, "web.trace")), - "--pseudo-realtime", + tests.spawnBro("events-send", + ["-r", os.path.join(tests.Scripts, os.path.join(tests.Traces, "web.trace")), + "--pseudo-realtime", "-C", os.path.join(tests.Scripts, "events-send.bro")]) time.sleep(2) - tests.spawnBro("events-rcv", + tests.spawnBro("events-rcv", [os.path.join(tests.Scripts, "events-rcv.bro")]) tests.waitProc("events-send") tests.killProc("events-rcv") tests.finishTest("events-send", ["stdout.log", "stderr.log", "http.log", "conn.log"], ignoreTime=True) tests.finishTest("events-rcv", ["stdout.log", "stderr.log", "http.log", "conn.log"], ignoreTime=True) - tests.spawnBro("events-display", + tests.spawnBro("events-display", ["-x", os.path.join(tests.workDir("events-rcv"), "events.bst")]) tests.waitProc("events-display") tests.finishTest("events-display", ["stdout.log"], ignoreTime=True, sort=True, delete=['127.0.0.1:[0-9]*',"Event.*remote_.*"]) tests.compareFiles("events-send", "events-rcv", ["http.log"], ignoreTime=True, ignoreSessionID=True) -########################################## +########################################## # Exchange synchronized state -########################################## +########################################## if tests.testSet("sync"): - tests.spawnBro("sync-send", + tests.spawnBro("sync-send", [os.path.join(tests.Scripts, "vars-sync-send.bro")]) - tests.spawnBro("sync-rcv", + tests.spawnBro("sync-rcv", [os.path.join(tests.Scripts, "vars-sync-rcv.bro")]) tests.waitProc("sync-send") time.sleep(1) @@ -99,10 +99,10 @@ if tests.testSet("sync"): tests.compareFiles("sync-send", "sync-rcv", ["vars.log"], ignoreTime=True) -# Old version -# tests.spawnBro("sync-send", -# ["-r", os.path.join(tests.Scripts, os.path.join(tests.Traces, "web.trace")), -# "--pseudo-realtime", +# Old version +# tests.spawnBro("sync-send", +# ["-r", os.path.join(tests.Scripts, os.path.join(tests.Traces, "web.trace")), +# "--pseudo-realtime", # "-C", # os.path.join(tests.Scripts, "vars-sync-send.bro")]) @@ -113,22 +113,22 @@ if tests.testSet("sync"): if tests.testSet("broccoli"): - broctest = os.path.join(tests.Bro, "aux/broccoli/test") - broclib = os.path.join(tests.Bro, "aux/broccoli/src/.libs") - broping = os.path.join(broctest, "broping") + broctest = os.path.join(tests.BroBase, "aux/broccoli/test") + broclib = os.path.join(tests.BroBase, "build/aux/broccoli/src/") + broping = os.path.join(tests.BroBase, "build/aux/broccoli/test/broping") - brocpy = os.path.join(tests.Bro, "aux/broccoli/bindings/python") + brocpy = os.path.join(tests.BroBase, "build/aux/broccoli/bindings/broccoli-python") broccoli = True - + # Test if Broccoli was compiled. if not os.path.exists(broping): print " Broccoli was not compiled, skipping tests." broccoli = False - - # Test if this is a IPv6 Bro. + + # Test if this is a IPv6 Bro. if broccoli: - v6 = subprocess.call(["grep", "-q", "#define BROv6", os.path.join(tests.Bro, "config.h")]) + v6 = subprocess.call(["grep", "-q", "#define BROv6", os.path.join(tests.BroBase, "build/config.h")]) if v6 == 0: print " Bro built with IPv6 support not compatible with Broccoli, skipping tests." broccoli = False @@ -136,21 +136,21 @@ if tests.testSet("broccoli"): if broccoli: tests.spawnBro("bro-ping", [os.path.join(broctest, "broping-record.bro")]) time.sleep(1) - tests.spawnProc("broccoli-ping", - [broping, - "-r", - "-c", "5", + tests.spawnProc("broccoli-ping", + [broping, + "-r", + "-c", "5", "127.0.0.1"]) tests.waitProc("broccoli-ping") tests.killProc("bro-ping") - - tests.finishTest("bro-ping", ["stdout.log", "stderr.log", "remote.log"], - ignoreTime=True, delete=["127.0.0.1:[0-9]*", "pid.*pid.*", - ".*Resource temporarily unavailable.*", ".*connection closed.*", + + tests.finishTest("bro-ping", ["stdout.log", "stderr.log", "remote.log"], + ignoreTime=True, delete=["127.0.0.1:[0-9]*", "pid.*pid.*", + ".*Resource temporarily unavailable.*", ".*connection closed.*", ".*peer disconnected.*"]) tests.finishTest("broccoli-ping", ["stdout.log", "stderr.log"], delete=["time=.* s$"]) - + # Test if Python binding are installed. sopath = subprocess.Popen(["find", brocpy, "-name", "_broccoli_intern.so"], stdout=subprocess.PIPE).communicate()[0] if sopath != "": @@ -158,7 +158,7 @@ if tests.testSet("broccoli"): os.environ["LD_LIBRARY_PATH"] = broclib os.environ["DYLD_LIBRARY_PATH"] = broclib os.environ["PYTHONPATH"] = os.path.dirname(sopath) - + tests.spawnBro("python-bro", [os.path.join(brocpy, "tests/test.bro")]) time.sleep(1) tests.spawnProc("python-script", [os.path.join(brocpy, "tests/test.py")]) @@ -169,6 +169,6 @@ if tests.testSet("broccoli"): else: print " Python bindings not built, skipping test." print " (To build: cd %s && python setup.py build)" % brocpy - - + + diff --git a/testing/istate/tests.py b/testing/istate/tests.py index a8bbb5172a..0673108563 100644 --- a/testing/istate/tests.py +++ b/testing/istate/tests.py @@ -13,11 +13,11 @@ import subprocess Testing = os.path.abspath(".") # Path to top-level Bro directory. -if os.path.exists("../../src/bro"): - Bro = os.path.abspath("../..") +if os.path.exists("../../build/src/bro"): + BroBase = os.path.abspath("../..") else: - Bro = os.path.abspath("../../bro") - + error("cannot find build directory") + # Path where tmp files are created. Tmp = os.path.join(Testing, "tmp") @@ -32,7 +32,7 @@ Traces = os.path.join(Testing, "traces") # Where the base files to compare against are stored. Base = os.path.join(os.getcwd(), "./base") - + # Process ID of all processes we've spawned, indexed by textual tag *and* pid. Running = {} @@ -46,40 +46,40 @@ def error(str): print >>sys.stderr, "Error:", str sys.exit(1) -def debug(str): +def debug(str): if Options.debug: print >>sys.stderr, "Debug:", str -def log(str): +def log(str): print >>sys.stderr, str # Returns full path of given process' working directory. -def workDir(tag): +def workDir(tag): return os.path.join(Tmp, tag) # Intializes work dir for given process. def initWorkDir(tag): - + try: os.mkdir(Tmp) except OSError, e: if e.errno != errno.EEXIST: raise - + os.system("rm -rf " + workDir(tag)) os.mkdir(workDir(tag)) # Spawns process identified by the given tag. Enters process into RunningBro. -def spawnProc(tag, cmdline, copy=[]): +def spawnProc(tag, cmdline, copy=[]): initWorkDir(tag) os.chdir(workDir(tag)) for i in copy: debug("Copying %s into workdir of %s" % (i, tag)) os.system("cp -r %s %s" % (i, workDir(tag))) - + debug("Spawning '%s' as %s" % (" ".join(cmdline), tag)) - + saved_stdin = os.dup(0) saved_stdout = os.dup(1) saved_stderr = os.dup(2) @@ -93,31 +93,34 @@ def spawnProc(tag, cmdline, copy=[]): os.dup2(saved_stdin, 0) os.dup2(saved_stdout, 1) os.dup2(saved_stderr, 2) - + Running[tag] = pid Running[pid] = tag -# Spaws a Bro process. +# Spaws a Bro process. def spawnBro(tag, args, copy=[]): - os.putenv("BROPATH", os.path.join(Bro, "policy") + ":" + Scripts) + bropath = os.path.join(BroBase, "policy") + bropath += ":" + os.path.join(BroBase, "build/src") + + os.putenv("BROPATH", bropath + ":" + Scripts) os.unsetenv("BRO_LOG_SUFFIX") args += ["--load-seeds", BroSeed, "-B", "state,comm"] - spawnProc(tag, [os.path.join(Bro, "src/bro")] + args, copy=copy) - -# Examines a process' exit code. -def parseExitCode(tag, result): + spawnProc(tag, [os.path.join(BroBase, "build/src/bro")] + args, copy=copy) + +# Examines a process' exit code. +def parseExitCode(tag, result): if os.WCOREDUMP(result): error("process %s core dumped." % tag) if os.WIFSIGNALED(result): error("process %s got signal %d." % (tag, os.WTERMSIG(result))) - + if not os.WIFEXITED(result): error("process %s exited abnormally (%d)." % (tag, result)) result = os.WEXITSTATUS(result) - debug("process %s exited with %d" % (tag, result)) - + debug("process %s exited with %d" % (tag, result)) + return result # Waits for process to finish. @@ -126,7 +129,7 @@ def waitProc(tag): result = parseExitCode(tag, result) if result != 0: error("Execution of %s failed." % tag) - + del Running[pid] del Running[tag] @@ -147,43 +150,43 @@ def killProc(tag): parseExitCode(tag, result) del Running[pid] del Running[tag] - + # Cleans up temporary stuff def cleanup(): os.system("rm -rf " + Tmp) # Canonicalizes file content for diffing. def canonicalizeFile(file, ignoreTime, ignoreSessionID, sort, delete): - + cmd = [] - + if delete: for i in delete: cmd += ["sed 's/%s//g' | grep -v '^$'" % i] - + if ignoreTime: cmd += ["sed 's/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\.[0-9][0-9]\{0,6\}/xxxxxxxxxx.xxxxxx/g'"] if ignoreSessionID: # A session is either "%1" or "%my-peer-description-1" cmd += ["sed 's/%\([^ ]*-\)\{0,1\}[0-9][0-9]*/%XXX/g'"] - + if sort: cmd += ["LC_ALL=c sort"] - + if not cmd: return - + tmp = file + ".tmp" - cmd = "cat %s | %s >%s" % (file, " | ".join(cmd), tmp) + cmd = "cat %s | %s >%s" % (file, " | ".join(cmd), tmp) debug("Canonicalizing '%s'" % cmd) os.system(cmd) os.system("mv %s %s" % (tmp, file)) -# Diffs the two files, If mismatch, prints "FAILED" and returns true. +# Diffs the two files, If mismatch, prints "FAILED" and returns true. def diff(file1, file2): - + quiet = ">/dev/null" if Options.showdiff: quiet = "" @@ -192,37 +195,37 @@ def diff(file1, file2): if not os.path.exists(f): print "FAILED (%s does not exist)" % f return False - + diff = "diff -u %s %s %s" % (file1, file2, quiet) - + debug("Executing '%s'" % diff) result = os.system(diff) - + if os.WEXITSTATUS(result) != 0: print "FAILED" return False - + return True - + # Compares files of process against base version. Returns false if mismatch found. def checkFiles(tag, files, ignoreTime, sort, delete): base = os.path.join(Base, tag) work = workDir(tag) - + print " Checking %s..." % tag, - + failed = False - + for file in files: oldfile = os.path.join(base, file) newfile = os.path.join(work, file) canonicalizeFile(newfile, ignoreTime, False, sort, delete) - + if not diff(oldfile, newfile): failed = True break - + if not failed: print "ok" else: @@ -234,25 +237,25 @@ def compareFiles(tag1, tag2, files, ignoreTime=False, ignoreSessionID=False, sor work2 = workDir(tag2) print " Comparing %s with %s..." % (tag1, tag2), - + failed = False - + for file in files: file1 = os.path.join(work1, file) file2 = os.path.join(work2, file) canonicalizeFile(file1, ignoreTime, ignoreSessionID, sort, delete) canonicalizeFile(file2, ignoreTime, ignoreSessionID, sort, delete) - + if not diff(file1, file2): failed = True break - + if not failed: print "ok" else: Failed = failed - + # Make the result of process new baseline. def makeNewBase(tag, files, ignoreTime, sort, delete): @@ -261,21 +264,21 @@ def makeNewBase(tag, files, ignoreTime, sort, delete): except OSError, e: if e.errno != errno.EEXIST: raise - + base = os.path.join(Base, tag) work = workDir(tag) print " Copying files for %s..." % tag - + try: os.mkdir(base) except OSError, e: if e.errno != errno.EEXIST: raise - + # Delete all files but those belonging to CVS. os.system("find %s -type f -not -path '*/CVS/*' -not -path '*/.svn/*' -exec rm '{}' ';'" % base) - + for file in files: oldfile = os.path.join(work, file) newfile = os.path.join(base, file) @@ -285,13 +288,13 @@ def makeNewBase(tag, files, ignoreTime, sort, delete): def testSet(set): if Options.set and set != Options.set: return False - + print "Running set '%s' ..." % set return True - + # Either check given files or make it new baseline, depending on options. def finishTest(tag, files, ignoreTime=False, sort=False, delete=None): if Options.newbase: makeNewBase(tag, files, ignoreTime, sort, delete) else: - checkFiles(tag, files, ignoreTime, sort, delete) + checkFiles(tag, files, ignoreTime, sort, delete)