diff --git a/doc b/doc index 218907b650..df503b4794 160000 --- a/doc +++ b/doc @@ -1 +1 @@ -Subproject commit 218907b6500d627904f6ba0767f7ba362bf825f7 +Subproject commit df503b479446b7b42f51edda67652453290a5dc5 diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 82993bfb03..ec067be6de 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -296,6 +296,39 @@ type endpoint_stats: record { endian_type: count; }; +module TCP; +export { + ## A TCP Option field parsed from a TCP header. + type Option: record { + ## The kind number associated with the option. Other optional fields + ## of this record may be set depending on this value. + kind: count; + ## The total length of the option in bytes, including the kind byte and + ## length byte (if present). + length: count; + ## This field is set to the raw option bytes if the kind is not + ## otherwise known/parsed. It's also set for known kinds whose length + ## was invalid. + data: string &optional; + ## Kind 2: Maximum Segment Size. + mss: count &optional; + ## Kind 3: Window scale. + window_scale: count &optional; + ## Kind 5: Selective ACKnowledgement (SACK). This is a list of 2, 4, + ## 6, or 8 numbers with each consecutive pair being a 32-bit + ## begin-pointer and 32-bit end pointer. + sack: index_vec &optional; + ## Kind 8: 4-byte sender timestamp value. + send_timestamp: count &optional; + ## Kind 8: 4-byte echo reply timestamp value. + echo_timestamp: count &optional; + }; + + ## The full list of TCP Option fields parsed from a TCP header. + type OptionList: vector of Option; +} +module GLOBAL; + module Tunnel; export { ## Records the identity of an encapsulating parent of a tunneled connection. diff --git a/src/analyzer/protocol/tcp/CMakeLists.txt b/src/analyzer/protocol/tcp/CMakeLists.txt index c00f3e5379..270beb36d8 100644 --- a/src/analyzer/protocol/tcp/CMakeLists.txt +++ b/src/analyzer/protocol/tcp/CMakeLists.txt @@ -6,5 +6,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI zeek_plugin_begin(Zeek TCP) zeek_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Stats.cc Plugin.cc) zeek_plugin_bif(events.bif) +zeek_plugin_bif(types.bif) zeek_plugin_bif(functions.bif) zeek_plugin_end() diff --git a/src/analyzer/protocol/tcp/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc index a03c36b2a1..b170801f16 100644 --- a/src/analyzer/protocol/tcp/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -11,6 +11,7 @@ #include "analyzer/protocol/tcp/TCP_Reassembler.h" #include "events.bif.h" +#include "types.bif.h" using namespace analyzer::tcp; @@ -1186,8 +1187,8 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, GeneratePacketEvent(rel_seq, rel_ack, data, len, caplen, is_orig, flags); - if ( tcp_option && tcp_hdr_len > sizeof(*tp) ) - ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0); + if ( (tcp_option || tcp_options) && tcp_hdr_len > sizeof(*tp) ) + ParseTCPOptions(tp, is_orig); if ( DEBUG_tcp_data_sent ) { @@ -1286,14 +1287,12 @@ void TCP_Analyzer::UpdateConnVal(RecordVal *conn_val) (*i)->UpdateConnVal(conn_val); } -int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp, - proc_tcp_option_t proc, - TCP_Analyzer* analyzer, - bool is_orig, void* cookie) +int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp, bool is_orig) { // Parse TCP options. const u_char* options = (const u_char*) tcp + sizeof(struct tcphdr); const u_char* opt_end = (const u_char*) tcp + tcp->th_off * 4; + std::vector opts; while ( options < opt_end ) { @@ -1306,21 +1305,19 @@ int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp, else if ( options + 1 >= opt_end ) // We've run off the end, no room for the length. - return -1; + break; else opt_len = options[1]; if ( opt_len == 0 ) - return -1; // trashed length field + break; // trashed length field if ( options + opt_len > opt_end ) // No room for rest of option. - return -1; - - if ( (*proc)(opt, opt_len, options, analyzer, is_orig, cookie) == -1 ) - return -1; + break; + opts.emplace_back(options); options += opt_len; if ( opt == TCPOPT_EOL ) @@ -1328,25 +1325,112 @@ int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp, break; } - return 0; - } - -int TCP_Analyzer::TCPOptionEvent(unsigned int opt, - unsigned int optlen, - const u_char* /* option */, - TCP_Analyzer* analyzer, - bool is_orig, void* cookie) - { if ( tcp_option ) + for ( const auto& o : opts ) + { + auto kind = o[0]; + auto length = kind < 2 ? 1 : o[1]; + ConnectionEventFast(tcp_option, { + BuildConnVal(), + val_mgr->GetBool(is_orig), + val_mgr->GetCount(kind), + val_mgr->GetCount(length), + }); + } + + if ( tcp_options ) { - analyzer->ConnectionEventFast(tcp_option, { - analyzer->BuildConnVal(), + auto option_list = new VectorVal(BifType::Vector::TCP::OptionList); + + for ( const auto& o : opts ) + { + auto kind = o[0]; + auto length = kind < 2 ? 1 : o[1]; + auto option_record = new RecordVal(BifType::Record::TCP::Option); + option_list->Assign(option_list->Size(), option_record); + option_record->Assign(0, val_mgr->GetCount(kind)); + option_record->Assign(1, val_mgr->GetCount(length)); + + auto handled_option = false; + + switch ( kind ) { + case 2: + // MSS + if ( length == 4 ) + { + auto mss = ntohs(*reinterpret_cast(o + 2)); + option_record->Assign(3, val_mgr->GetCount(mss)); + handled_option = true; + } + break; + + case 3: + // window scale + if ( length == 3 ) + { + auto scale = o[2]; + option_record->Assign(4, val_mgr->GetCount(scale)); + handled_option = true; + } + break; + + case 4: + // sack permitted (implicit boolean) + break; + + case 5: + // SACK blocks (1-4 pairs of 32-bit begin+end pointers) + if ( length == 10 || length == 18 || + length == 26 || length == 34 ) + { + auto p = reinterpret_cast(o + 2); + auto num_pointers = (length - 2) / 4; + auto vt = internal_type("index_vec")->AsVectorType(); + auto sack = new VectorVal(vt); + + for ( auto i = 0; i < num_pointers; ++i ) + sack->Assign(sack->Size(), val_mgr->GetCount(ntohl(p[i]))); + + option_record->Assign(5, sack); + handled_option = true; + } + break; + + case 8: + // timestamps + if ( length == 10 ) + { + auto send = ntohl(*reinterpret_cast(o + 2)); + auto echo = ntohl(*reinterpret_cast(o + 6)); + option_record->Assign(6, val_mgr->GetCount(send)); + option_record->Assign(7, val_mgr->GetCount(echo)); + handled_option = true; + } + break; + + default: + break; + } + + if ( ! handled_option && length > 2 ) + { + // unknown option or invalid option length + auto data_len = length - 2; + auto data = reinterpret_cast(o + 2); + option_record->Assign(2, new StringVal(data_len, data)); + } + } + + ConnectionEventFast(tcp_options, { + BuildConnVal(), val_mgr->GetBool(is_orig), - val_mgr->GetCount(opt), - val_mgr->GetCount(optlen), - }); + option_list, + }); } + if ( options < opt_end ) + return -1; + return 0; } diff --git a/src/analyzer/protocol/tcp/TCP.h b/src/analyzer/protocol/tcp/TCP.h index 7eeff0bd49..1204f56916 100644 --- a/src/analyzer/protocol/tcp/TCP.h +++ b/src/analyzer/protocol/tcp/TCP.h @@ -64,19 +64,10 @@ public: void SetContentsFile(unsigned int direction, BroFile* f) override; BroFile* GetContentsFile(unsigned int direction) const override; - // Callback to process a TCP option. - typedef int (*proc_tcp_option_t)(unsigned int opt, unsigned int optlen, - const u_char* option, TCP_Analyzer* analyzer, - bool is_orig, void* cookie); - // From Analyzer.h void UpdateConnVal(RecordVal *conn_val) override; - // Needs to be static because it's passed as a pointer-to-function - // rather than pointer-to-member-function. - static int ParseTCPOptions(const struct tcphdr* tcp, - proc_tcp_option_t proc, TCP_Analyzer* analyzer, - bool is_orig, void* cookie); + int ParseTCPOptions(const struct tcphdr* tcp, bool is_orig); static analyzer::Analyzer* Instantiate(Connection* conn) { return new TCP_Analyzer(conn); } @@ -168,12 +159,6 @@ protected: void SetReassembler(tcp::TCP_Reassembler* rorig, tcp::TCP_Reassembler* rresp); - // Needs to be static because it's passed as a pointer-to-function - // rather than pointer-to-member-function. - static int TCPOptionEvent(unsigned int opt, unsigned int optlen, - const u_char* option, TCP_Analyzer* analyzer, - bool is_orig, void* cookie); - // A couple utility functions that may also be useful to derived analyzers. static uint64_t get_relative_seq(const TCP_Endpoint* endpoint, uint32_t cur_base, uint32_t last, diff --git a/src/analyzer/protocol/tcp/events.bif b/src/analyzer/protocol/tcp/events.bif index 032e8f614f..2450df1828 100644 --- a/src/analyzer/protocol/tcp/events.bif +++ b/src/analyzer/protocol/tcp/events.bif @@ -250,11 +250,23 @@ event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: ## ## optlen: The length of the options value. ## -## .. zeek:see:: tcp_packet tcp_contents tcp_rexmit +## .. zeek:see:: tcp_packet tcp_contents tcp_rexmit tcp_options ## -## .. note:: There is currently no way to get the actual option value, if any. +## .. note:: To inspect the actual option values, if any, use :zeek:see:`tcp_options`. event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%); +## Generated for each TCP header that contains TCP options. This is a very +## low-level event and potentially expensive as it may be raised very often. +## +## c: The connection the packet is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## options: The list of options parsed out of the TCP header. +## +## .. zeek:see:: tcp_packet tcp_contents tcp_rexmit tcp_option +event tcp_options%(c: connection, is_orig: bool, options: TCP::OptionList%); + ## Generated for each chunk of reassembled TCP payload. When content delivery is ## enabled for a TCP connection (via :zeek:id:`tcp_content_delivery_ports_orig`, ## :zeek:id:`tcp_content_delivery_ports_resp`, diff --git a/src/analyzer/protocol/tcp/types.bif b/src/analyzer/protocol/tcp/types.bif new file mode 100644 index 0000000000..8da29b900a --- /dev/null +++ b/src/analyzer/protocol/tcp/types.bif @@ -0,0 +1,2 @@ +type TCP::Option: record; +type TCP::OptionList: vector; diff --git a/testing/btest/Baseline/core.tcp.options/out b/testing/btest/Baseline/core.tcp.options/out index 9c8ef6956c..d85b2c9bf7 100644 --- a/testing/btest/Baseline/core.tcp.options/out +++ b/testing/btest/Baseline/core.tcp.options/out @@ -3,14 +3,48 @@ [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 8, 10 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 3, 3 +[orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T + kind: 2, length: 4 + mss: 1460 + kind: 4, length: 2 + sack permitted + kind: 8, length: 10 + send ts: 4294923497 + echo ts: 0 + kind: 1, length: 1 + kind: 3, length: 3 + window scale: 6 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F, 2, 4 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F, 4, 2 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F, 8, 10 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F, 3, 3 +[orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], F + kind: 2, length: 4 + mss: 1380 + kind: 4, length: 2 + sack permitted + kind: 8, length: 10 + send ts: 419445911 + echo ts: 4294923497 + kind: 1, length: 1 + kind: 3, length: 3 + window scale: 7 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 8, 10 +[orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T + kind: 1, length: 1 + kind: 1, length: 1 + kind: 8, length: 10 + send ts: 4294923545 + echo ts: 419445911 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 1, 1 [orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T, 8, 10 +[orig_h=192.168.1.102, orig_p=36861/tcp, resp_h=193.1.193.64, resp_p=80/tcp], T + kind: 1, length: 1 + kind: 1, length: 1 + kind: 8, length: 10 + send ts: 4294923545 + echo ts: 419445911 diff --git a/testing/btest/Baseline/core.tcp.options/out-sack b/testing/btest/Baseline/core.tcp.options/out-sack new file mode 100644 index 0000000000..625b68ed29 --- /dev/null +++ b/testing/btest/Baseline/core.tcp.options/out-sack @@ -0,0 +1,24 @@ +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 5, 10 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 0, 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T + kind: 5, length: 10 + sack: [1, 16] + kind: 0, length: 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 5, 18 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 0, 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T + kind: 5, length: 18 + sack: [1, 16, 256, 4096] + kind: 0, length: 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 5, 26 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 0, 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T + kind: 5, length: 26 + sack: [1, 16, 256, 4096, 65536, 1048576] + kind: 0, length: 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 5, 34 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T, 0, 1 +[orig_h=127.0.0.1, orig_p=20/tcp, resp_h=127.0.0.1, resp_p=80/tcp], T + kind: 5, length: 34 + sack: [1, 16, 256, 4096, 65536, 1048576, 16777216, 268435456] + kind: 0, length: 1 diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 072b83ffe0..350f284c8a 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -154,6 +154,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_SteppingStone.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Syslog.events.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek + build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 42dbfbd772..6311a1ef8f 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -154,6 +154,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_SteppingStone.events.bif.zeek build/scripts/base/bif/plugins/Zeek_Syslog.events.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek + build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek build/scripts/base/bif/plugins/Zeek_Teredo.events.bif.zeek build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 94cb9c0d34..1eb582c2d4 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -274,7 +274,7 @@ 0.000000 MetaHookPost CallFunction(Log::__create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql])) -> -0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T])) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Broker::LOG)) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Cluster::LOG)) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, , (Config::LOG)) -> @@ -455,7 +455,7 @@ 0.000000 MetaHookPost CallFunction(Log::create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql])) -> -0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T])) -> 0.000000 MetaHookPost CallFunction(NetControl::check_plugins, , ()) -> 0.000000 MetaHookPost CallFunction(NetControl::init, , ()) -> 0.000000 MetaHookPost CallFunction(Notice::want_pp, , ()) -> @@ -679,6 +679,7 @@ 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_Syslog.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_TCP.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_TCP.functions.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_TCP.types.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_Teredo.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_UDP.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, .<...>/Zeek_Unified2.events.bif.zeek) -> -1 @@ -1169,7 +1170,7 @@ 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql])) -0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Broker::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Cluster::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, , (Config::LOG)) @@ -1350,7 +1351,7 @@ 0.000000 MetaHookPre CallFunction(Log::create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird])) 0.000000 MetaHookPre CallFunction(Log::create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509])) 0.000000 MetaHookPre CallFunction(Log::create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql])) -0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(NetControl::check_plugins, , ()) 0.000000 MetaHookPre CallFunction(NetControl::init, , ()) 0.000000 MetaHookPre CallFunction(Notice::want_pp, , ()) @@ -1574,6 +1575,7 @@ 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_Syslog.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_TCP.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_TCP.functions.bif.zeek) +0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_TCP.types.bif.zeek) 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_Teredo.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_UDP.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, .<...>/Zeek_Unified2.events.bif.zeek) @@ -2063,7 +2065,7 @@ 0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird]) 0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509]) 0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql]) -0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction Log::add_default_filter(Broker::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Cluster::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Config::LOG) @@ -2244,7 +2246,7 @@ 0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird]) 0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509]) 0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql]) -0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction NetControl::check_plugins() 0.000000 | HookCallFunction NetControl::init() 0.000000 | HookCallFunction Notice::want_pp() @@ -2468,6 +2470,7 @@ 0.000000 | HookLoadFile .<...>/Zeek_Syslog.events.bif.zeek 0.000000 | HookLoadFile .<...>/Zeek_TCP.events.bif.zeek 0.000000 | HookLoadFile .<...>/Zeek_TCP.functions.bif.zeek +0.000000 | HookLoadFile .<...>/Zeek_TCP.types.bif.zeek 0.000000 | HookLoadFile .<...>/Zeek_Teredo.events.bif.zeek 0.000000 | HookLoadFile .<...>/Zeek_UDP.events.bif.zeek 0.000000 | HookLoadFile .<...>/Zeek_Unified2.events.bif.zeek @@ -2678,7 +2681,7 @@ 0.000000 | HookLoadFile base<...>/xmpp 0.000000 | HookLoadFile base<...>/zeek.bif.zeek 0.000000 | HookLogInit packet_filter 1/1 {ts (time), node (string), filter (string), init (bool), success (bool)} -0.000000 | HookLogWrite packet_filter [ts=1565053246.404549, node=zeek, filter=ip or not ip, init=T, success=T] +0.000000 | HookLogWrite packet_filter [ts=1570153649.029308, node=zeek, filter=ip or not ip, init=T, success=T] 0.000000 | HookQueueEvent NetControl::init() 0.000000 | HookQueueEvent filter_change_tracking() 0.000000 | HookQueueEvent zeek_init() diff --git a/testing/btest/Traces/tcp/option-sack.pcap b/testing/btest/Traces/tcp/option-sack.pcap new file mode 100644 index 0000000000..22d7118fc8 Binary files /dev/null and b/testing/btest/Traces/tcp/option-sack.pcap differ diff --git a/testing/btest/core/tcp/options.zeek b/testing/btest/core/tcp/options.zeek index 6a52f3bda2..4a561c988d 100644 --- a/testing/btest/core/tcp/options.zeek +++ b/testing/btest/core/tcp/options.zeek @@ -1,7 +1,44 @@ # @TEST-EXEC: zeek -b -r $TRACES/tcp/options.pcap %INPUT > out +# @TEST-EXEC: zeek -b -r $TRACES/tcp/option-sack.pcap %INPUT > out-sack # @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff out-sack event tcp_option(c: connection, is_orig: bool, opt: count, optlen: count) { print c$id, is_orig, opt, optlen; } + +event tcp_options(c: connection, is_orig: bool, options: TCP::OptionList) + { + print c$id, is_orig; + + for ( i in options ) + { + local o = options[i]; + print fmt(" kind: %s, length: %s", o$kind, o$length); + + if ( o?$data ) + print fmt(" data (%s): %s", |o$data|, o$data); + else + { + switch ( o$kind ) { + case 2: + print fmt(" mss: %s", o$mss); + break; + case 3: + print fmt(" window scale: %s", o$window_scale); + break; + case 4: + print fmt(" sack permitted"); + break; + case 5: + print fmt(" sack: %s", o$sack); + break; + case 8: + print fmt(" send ts: %s", o$send_timestamp); + print fmt(" echo ts: %s", o$echo_timestamp); + break; + } + } + } + }