diff --git a/.gitignore b/.gitignore index d962c792a4..e0efa6d316 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ tmp # Configuration and build directories for CLion .idea -cmake-build-debug +cmake-build-* # skip DS Store for MacOS .DS_Store diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 9def35753c..5fabc60a3e 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -5341,3 +5341,30 @@ event net_done(t: time) # execution would be another idea. @if ( __init_primary_bifs() ) @endif + +module LLAnalyzer; + +# Defines a mapping for the LLAnalyzer's configuration tree. This +# maps from a parent analyzer to a child analyzer through a numeric +# identifier. +export { + type ConfigEntry : record { + # The parent analyzer. This analyzer will check for the *identifier* in the + # packet data to know whether to call the next analyzer. This field is optional. + # If it is not included, the identifier will attach to the "root" analyzer. This + # means that the identifier will be searched for the initial packet header instead + # of later headers. + parent : LLAnalyzer::Tag &optional; + + # A numeric identifier that can be found in the packet data that denotes an + # analyzer should be called. + identifier : count; + + # The analyzer that corresponds to the above identifier. + analyzer : LLAnalyzer::Tag; + }; + + const config_map : vector of LLAnalyzer::ConfigEntry &redef; +} + +@load base/llprotocols diff --git a/scripts/base/llprotocols/__load__.zeek b/scripts/base/llprotocols/__load__.zeek new file mode 100644 index 0000000000..a6d256338b --- /dev/null +++ b/scripts/base/llprotocols/__load__.zeek @@ -0,0 +1,11 @@ +@load base/llprotocols/default +@load base/llprotocols/ethernet +@load base/llprotocols/fddi +@load base/llprotocols/ieee802_11 +@load base/llprotocols/ieee802_11_radio +@load base/llprotocols/linux_sll +@load base/llprotocols/nflog +@load base/llprotocols/null +@load base/llprotocols/ppp_serial +@load base/llprotocols/pppoe +@load base/llprotocols/vlan diff --git a/scripts/base/llprotocols/default/__load__.zeek b/scripts/base/llprotocols/default/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/default/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/default/main.zeek b/scripts/base/llprotocols/default/main.zeek new file mode 100644 index 0000000000..caf50e6378 --- /dev/null +++ b/scripts/base/llprotocols/default/main.zeek @@ -0,0 +1,6 @@ +module LL_DEFAULT; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_DEFAULTANALYZER, $identifier=4, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_DEFAULTANALYZER, $identifier=6, $analyzer=LLAnalyzer::LLANALYZER_IPV6) +}; diff --git a/scripts/base/llprotocols/ethernet/__load__.zeek b/scripts/base/llprotocols/ethernet/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/ethernet/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/ethernet/main.zeek b/scripts/base/llprotocols/ethernet/main.zeek new file mode 100644 index 0000000000..1227b2fb83 --- /dev/null +++ b/scripts/base/llprotocols/ethernet/main.zeek @@ -0,0 +1,16 @@ +module LL_ETHERNET; + +const DLT_EN10MB : count = 1; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_EN10MB, $analyzer=LLAnalyzer::LLANALYZER_ETHERNET), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x8847, $analyzer=LLAnalyzer::LLANALYZER_MPLS), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x0800, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x86DD, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x0806, $analyzer=LLAnalyzer::LLANALYZER_ARP), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x8035, $analyzer=LLAnalyzer::LLANALYZER_ARP), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x8100, $analyzer=LLAnalyzer::LLANALYZER_VLAN), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x88A8, $analyzer=LLAnalyzer::LLANALYZER_VLAN), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x9100, $analyzer=LLAnalyzer::LLANALYZER_VLAN), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=0x8864, $analyzer=LLAnalyzer::LLANALYZER_PPPOE) +}; diff --git a/scripts/base/llprotocols/fddi/__load__.zeek b/scripts/base/llprotocols/fddi/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/fddi/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/fddi/main.zeek b/scripts/base/llprotocols/fddi/main.zeek new file mode 100644 index 0000000000..68fd691d7f --- /dev/null +++ b/scripts/base/llprotocols/fddi/main.zeek @@ -0,0 +1,7 @@ +module LL_FDDI; + +const DLT_FDDI : count = 10; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_FDDI, $analyzer=LLAnalyzer::LLANALYZER_FDDI) +}; diff --git a/scripts/base/llprotocols/ieee802_11/__load__.zeek b/scripts/base/llprotocols/ieee802_11/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/ieee802_11/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/ieee802_11/main.zeek b/scripts/base/llprotocols/ieee802_11/main.zeek new file mode 100644 index 0000000000..070e3f9eff --- /dev/null +++ b/scripts/base/llprotocols/ieee802_11/main.zeek @@ -0,0 +1,11 @@ +module LL_IEEE802_11; + +const DLT_IEEE802_11 : count = 105; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_IEEE802_11, $analyzer=LLAnalyzer::LLANALYZER_IEEE802_11), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_IEEE802_11, $identifier=0x0800, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_IEEE802_11, $identifier=0x86DD, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_IEEE802_11, $identifier=0x0806, $analyzer=LLAnalyzer::LLANALYZER_ARP), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_IEEE802_11, $identifier=0x8035, $analyzer=LLAnalyzer::LLANALYZER_ARP) +}; diff --git a/scripts/base/llprotocols/ieee802_11_radio/__load__.zeek b/scripts/base/llprotocols/ieee802_11_radio/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/ieee802_11_radio/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/ieee802_11_radio/main.zeek b/scripts/base/llprotocols/ieee802_11_radio/main.zeek new file mode 100644 index 0000000000..0985b0e391 --- /dev/null +++ b/scripts/base/llprotocols/ieee802_11_radio/main.zeek @@ -0,0 +1,9 @@ +module LL_IEEE802_11_RADIO; + +const DLT_IEEE802_11_RADIO : count = 127; +const DLT_IEEE802_11 : count = 105; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_IEEE802_11_RADIO, $analyzer=LLAnalyzer::LLANALYZER_IEEE802_11_RADIO), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_IEEE802_11_RADIO, $identifier=DLT_IEEE802_11, $analyzer=LLAnalyzer::LLANALYZER_IEEE802_11) +}; diff --git a/scripts/base/llprotocols/linux_sll/__load__.zeek b/scripts/base/llprotocols/linux_sll/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/linux_sll/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/linux_sll/main.zeek b/scripts/base/llprotocols/linux_sll/main.zeek new file mode 100644 index 0000000000..601c5ae870 --- /dev/null +++ b/scripts/base/llprotocols/linux_sll/main.zeek @@ -0,0 +1,12 @@ +module LL_LINUX_SLL; + +const DLT_LINUX_SLL : count = 113; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_LINUX_SLL, $analyzer=LLAnalyzer::LLANALYZER_LINUXSLL), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_LINUXSLL, $identifier=0x0800, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_LINUXSLL, $identifier=0x86DD, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_LINUXSLL, $identifier=0x0806, $analyzer=LLAnalyzer::LLANALYZER_ARP), + # RARP + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_LINUXSLL, $identifier=0x8035, $analyzer=LLAnalyzer::LLANALYZER_ARP) +}; diff --git a/scripts/base/llprotocols/nflog/__load__.zeek b/scripts/base/llprotocols/nflog/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/nflog/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/nflog/main.zeek b/scripts/base/llprotocols/nflog/main.zeek new file mode 100644 index 0000000000..d62ccd20c5 --- /dev/null +++ b/scripts/base/llprotocols/nflog/main.zeek @@ -0,0 +1,11 @@ +module LL_NFLOG; + +const DLT_NFLOG : count = 239; +const AF_INET : count = 2; +const AF_INET6 : count = 10; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_NFLOG, $analyzer=LLAnalyzer::LLANALYZER_NFLOG), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NFLOG, $identifier=AF_INET, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NFLOG, $identifier=AF_INET6, $analyzer=LLAnalyzer::LLANALYZER_IPV6) +}; diff --git a/scripts/base/llprotocols/null/__load__.zeek b/scripts/base/llprotocols/null/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/null/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/null/main.zeek b/scripts/base/llprotocols/null/main.zeek new file mode 100644 index 0000000000..f70f40d0e2 --- /dev/null +++ b/scripts/base/llprotocols/null/main.zeek @@ -0,0 +1,19 @@ +module LL_NULL; + +const DLT_NULL : count = 0; +const AF_INET : count = 2; +const AF_INET6 : count = 10; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_NULL, $analyzer=LLAnalyzer::LLANALYZER_NULL), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NULL, $identifier=AF_INET, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + + ## From the Wireshark Wiki: AF_INET6ANALYZER, unfortunately, has different values in + ## {NetBSD,OpenBSD,BSD/OS}, {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6 + ## packet might have a link-layer header with 24, 28, or 30 as the AF_ value. As we + ## may be reading traces captured on platforms other than what we're running on, we + ## accept them all here. + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NULL, $identifier=24, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NULL, $identifier=28, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_NULL, $identifier=30, $analyzer=LLAnalyzer::LLANALYZER_IPV6) +}; diff --git a/scripts/base/llprotocols/ppp_serial/__load__.zeek b/scripts/base/llprotocols/ppp_serial/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/ppp_serial/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/ppp_serial/main.zeek b/scripts/base/llprotocols/ppp_serial/main.zeek new file mode 100644 index 0000000000..cb873a773b --- /dev/null +++ b/scripts/base/llprotocols/ppp_serial/main.zeek @@ -0,0 +1,10 @@ +module LL_PPP_SERIAL; + +const DLT_PPP_SERIAL : count = 50; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($identifier=DLT_PPP_SERIAL, $analyzer=LLAnalyzer::LLANALYZER_PPPSERIAL), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_PPPSERIAL, $identifier=0x0281, $analyzer=LLAnalyzer::LLANALYZER_MPLS), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_PPPSERIAL, $identifier=0x0021, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_PPPSERIAL, $identifier=0x0057, $analyzer=LLAnalyzer::LLANALYZER_IPV6) +}; diff --git a/scripts/base/llprotocols/pppoe/__load__.zeek b/scripts/base/llprotocols/pppoe/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/pppoe/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/pppoe/main.zeek b/scripts/base/llprotocols/pppoe/main.zeek new file mode 100644 index 0000000000..737658d826 --- /dev/null +++ b/scripts/base/llprotocols/pppoe/main.zeek @@ -0,0 +1,6 @@ +module LL_PPPOE; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_PPPOE, $identifier=0x0021, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_PPPOE, $identifier=0x0057, $analyzer=LLAnalyzer::LLANALYZER_IPV6) +}; diff --git a/scripts/base/llprotocols/vlan/__load__.zeek b/scripts/base/llprotocols/vlan/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/llprotocols/vlan/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/llprotocols/vlan/main.zeek b/scripts/base/llprotocols/vlan/main.zeek new file mode 100644 index 0000000000..97e4cdcb09 --- /dev/null +++ b/scripts/base/llprotocols/vlan/main.zeek @@ -0,0 +1,11 @@ +module LL_VLAN; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x8847, $analyzer=LLAnalyzer::LLANALYZER_MPLS), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x0800, $analyzer=LLAnalyzer::LLANALYZER_IPV4), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x86DD, $analyzer=LLAnalyzer::LLANALYZER_IPV6), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x0806, $analyzer=LLAnalyzer::LLANALYZER_ARP), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x8035, $analyzer=LLAnalyzer::LLANALYZER_ARP), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x8100, $analyzer=LLAnalyzer::LLANALYZER_VLAN), + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_VLAN, $identifier=0x8864, $analyzer=LLAnalyzer::LLANALYZER_PPPOE) +}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eb94d4a728..9545236898 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -146,6 +146,7 @@ set(bro_PLUGIN_LIBS CACHE INTERNAL "plugin libraries" FORCE) set(bro_PLUGIN_DEPS CACHE INTERNAL "plugin dependencies" FORCE) add_subdirectory(analyzer) +add_subdirectory(llanalyzer) add_subdirectory(broker) add_subdirectory(zeekygen) add_subdirectory(file_analysis) diff --git a/src/Conn.h b/src/Conn.h index ebd4087a9e..9be0afc8fe 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -349,8 +349,8 @@ protected: TransportProto proto; uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available - u_char orig_l2_addr[Packet::l2_addr_len]; // Link-layer originator address, if available - u_char resp_l2_addr[Packet::l2_addr_len]; // Link-layer responder address, if available + u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available + u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available double start_time, last_time; double inactivity_timeout; RecordValPtr conn_val; diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index 5a4a468847..497bae8230 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -19,18 +19,19 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = { { "string", 0, false }, { "notifiers", 0, false }, { "main-loop", 0, false }, + { "llanalyzer", 0, false }, { "dpd", 0, false }, { "tm", 0, false }, { "logging", 0, false }, - {"input", 0, false }, + { "input", 0, false }, { "threading", 0, false }, { "file_analysis", 0, false }, { "plugins", 0, false }, { "zeekygen", 0, false }, { "pktio", 0, false }, { "broker", 0, false }, - { "scripts", 0, false}, - { "supervisor", 0, false} + { "scripts", 0, false }, + { "supervisor", 0, false } }; DebugLogger::DebugLogger() diff --git a/src/DebugLogger.h b/src/DebugLogger.h index 54257e1a6f..80ec926b1b 100644 --- a/src/DebugLogger.h +++ b/src/DebugLogger.h @@ -30,21 +30,22 @@ namespace zeek { // an entry to DebugLogger::streams in DebugLogger.cc. enum DebugStream { - DBG_SERIAL, // Serialization - DBG_RULES, // Signature matching - DBG_STRING, // String code + DBG_SERIAL, // Serialization + DBG_RULES, // Signature matching + DBG_STRING, // String code DBG_NOTIFIERS, // Notifiers DBG_MAINLOOP, // Main IOSource loop + DBG_LLANALYZER, // Low-Layer Analyzer Proof of Concept DBG_ANALYZER, // Analyzer framework - DBG_TM, // Time-machine packet input via Brocolli + DBG_TM, // Time-machine packet input via Brocolli DBG_LOGGING, // Logging streams - DBG_INPUT, // Input streams + DBG_INPUT, // Input streams DBG_THREADING, // Threading system DBG_FILE_ANALYSIS, // File analysis DBG_PLUGINS, // Plugin system DBG_ZEEKYGEN, // Zeekygen - DBG_PKTIO, // Packet sources and dumpers. - DBG_BROKER, // Broker communication + DBG_PKTIO, // Packet sources and dumpers. + DBG_BROKER, // Broker communication DBG_SCRIPTS, // Script initialization DBG_SUPERVISOR, // Process supervisor diff --git a/src/Sessions.cc b/src/Sessions.cc index afe817e2b5..1b375b0e09 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -188,7 +188,6 @@ void NetSessions::NextPacket(double t, const Packet* pkt) return; } - if ( dump_this_packet && ! zeek::detail::record_all_packets ) DumpPacket(pkt); } diff --git a/src/analyzer/protocol/arp/ARP.cc b/src/analyzer/protocol/arp/ARP.cc index f45e45b959..3da870ead4 100644 --- a/src/analyzer/protocol/arp/ARP.cc +++ b/src/analyzer/protocol/arp/ARP.cc @@ -100,8 +100,8 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) if ( ah->ar_hln != 6 ) { // don't know how to handle the opcode snprintf(errbuf, sizeof(errbuf), - "corrupt-arp-header (hrd=%i, hln=%i)", - ntohs(ah->ar_hrd), ah->ar_hln); + "corrupt-arp-header (hrd=%i, hln=%i)", + ntohs(ah->ar_hrd), ah->ar_hln); BadARP(ah, errbuf); return; } @@ -110,7 +110,7 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) default: { // don't know how to proceed snprintf(errbuf, sizeof(errbuf), - "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd)); + "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd)); BadARP(ah, errbuf); return; } @@ -122,8 +122,8 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) if ( ah->ar_pln != 4 ) { // don't know how to handle the opcode snprintf(errbuf, sizeof(errbuf), - "corrupt-arp-header (pro=%i, pln=%i)", - ntohs(ah->ar_pro), ah->ar_pln); + "corrupt-arp-header (pro=%i, pln=%i)", + ntohs(ah->ar_pro), ah->ar_pln); BadARP(ah, errbuf); return; } @@ -132,8 +132,8 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) default: { // don't know how to proceed snprintf(errbuf, sizeof(errbuf), - "unknown-arp-proto-address (pro=%i)", - ntohs(ah->ar_pro)); + "unknown-arp-proto-address (pro=%i)", + ntohs(ah->ar_pro)); BadARP(ah, errbuf); return; } @@ -151,12 +151,12 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) switch ( ntohs(ah->ar_op) ) { case ARPOP_REQUEST: RREvent(arp_request, pkt->l2_src, pkt->l2_dst, - ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); + ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); break; case ARPOP_REPLY: RREvent(arp_reply, pkt->l2_src, pkt->l2_dst, - ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); + ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah)); break; case ARPOP_REVREQUEST: @@ -165,7 +165,7 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) case ARPOP_INVREPLY: { // don't know how to handle the opcode snprintf(errbuf, sizeof(errbuf), - "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op)); + "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op)); BadARP(ah, errbuf); break; } @@ -173,7 +173,7 @@ void ARP_Analyzer::NextPacket(double t, const Packet* pkt) default: { // invalid opcode snprintf(errbuf, sizeof(errbuf), - "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op)); + "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op)); BadARP(ah, errbuf); return; } @@ -237,7 +237,7 @@ StringValPtr ARP_Analyzer::ToEthAddrStr(const u_char* addr) { char buf[1024]; snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); return make_intrusive(buf); } diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc index c7bbb87412..ae074bb9da 100644 --- a/src/iosource/Packet.cc +++ b/src/iosource/Packet.cc @@ -3,6 +3,7 @@ #include "Desc.h" #include "IP.h" #include "iosource/Manager.h" +#include "llanalyzer/Manager.h" #include "Var.h" extern "C" { @@ -45,7 +46,7 @@ void Packet::Init(int arg_link_type, pkt_timeval *arg_ts, uint32_t arg_caplen, data = arg_data; time = ts.tv_sec + double(ts.tv_usec) / 1e6; - hdr_size = GetLinkHeaderSize(arg_link_type); + hdr_size = 0; eth_type = 0; vlan = 0; inner_vlan = 0; @@ -58,14 +59,18 @@ void Packet::Init(int arg_link_type, pkt_timeval *arg_ts, uint32_t arg_caplen, l3_proto = L3_UNKNOWN; l3_checksummed = false; - if ( data && cap_len < hdr_size ) - { - Weird("truncated_link_header"); - return; - } + // For ll-analyzer: cur_pos points to the next payload. + cur_pos = data; if ( data ) - ProcessLayer2(); + { + // From here we assume that layer 2 is valid. If an ll-analyzer encounters + // an issue, it will call Packet::Weird(), which sets l2_valid to false. + l2_valid = true; + llanalyzer_mgr->ProcessPacket(this); + // Calculate header size after processing lower layers. + hdr_size = cur_pos - data; + } } const IP_Hdr Packet::IP() const @@ -79,521 +84,12 @@ void Packet::Weird(const char* name) l2_valid = false; } -int Packet::GetLinkHeaderSize(int link_type) +const u_char* const Packet::GetEndOfData() const { - switch ( link_type ) { - case DLT_NULL: - return 4; - - case DLT_EN10MB: - return 14; - - case DLT_FDDI: - return 13 + 8; // fddi_header + LLC - -#ifdef DLT_LINUX_SLL - case DLT_LINUX_SLL: - return 16; -#endif - - case DLT_PPP_SERIAL: // PPP_SERIAL - return 4; - - case DLT_IEEE802_11: // 802.11 monitor - return 34; - - case DLT_IEEE802_11_RADIO: // 802.11 plus RadioTap - return 59; - - case DLT_NFLOG: - // Linux netlink NETLINK NFLOG socket log messages - // The actual header size is variable, but we return the minimum - // expected size here, which is 4 bytes for the main header plus at - // least 2 bytes each for the type and length values assoicated with - // the final TLV carrying the packet payload. - return 8; - - case DLT_RAW: - return 0; + return data + cap_len; } - return -1; - } - -void Packet::ProcessLayer2() - { - l2_valid = true; - - // Unfortunately some packets on the link might have MPLS labels - // while others don't. That means we need to ask the link-layer if - // labels are in place. - bool have_mpls = false; - - const u_char* pdata = data; - const u_char* end_of_data = data + cap_len; - - switch ( link_type ) { - case DLT_NULL: - { - int protocol = (pdata[3] << 24) + (pdata[2] << 16) + (pdata[1] << 8) + pdata[0]; - pdata += GetLinkHeaderSize(link_type); - - // From the Wireshark Wiki: "AF_INET6, unfortunately, has - // different values in {NetBSD,OpenBSD,BSD/OS}, - // {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6 - // packet might have a link-layer header with 24, 28, or 30 - // as the AF_ value." As we may be reading traces captured on - // platforms other than what we're running on, we accept them - // all here. - - if ( protocol == AF_INET ) - l3_proto = L3_IPV4; - else if ( protocol == 24 || protocol == 28 || protocol == 30 ) - l3_proto = L3_IPV6; - else - { - Weird("non_ip_packet_in_null_transport"); - return; - } - - break; - } - - case DLT_EN10MB: - { - // Skip past Cisco FabricPath to encapsulated ethernet frame. - if ( pdata[12] == 0x89 && pdata[13] == 0x03 ) - { - auto constexpr cfplen = 16; - - if ( pdata + cfplen + GetLinkHeaderSize(link_type) >= end_of_data ) - { - Weird("truncated_link_header_cfp"); - return; - } - - pdata += cfplen; - } - - // Get protocol being carried from the ethernet frame. - int protocol = (pdata[12] << 8) + pdata[13]; - - eth_type = protocol; - l2_dst = pdata; - l2_src = pdata + 6; - - pdata += GetLinkHeaderSize(link_type); - - bool saw_vlan = false; - - while ( protocol == 0x8100 || protocol == 0x9100 || - protocol == 0x8864 ) - { - switch ( protocol ) - { - // VLAN carried over the ethernet frame. - // 802.1q / 802.1ad - case 0x8100: - case 0x9100: - { - if ( pdata + 4 >= end_of_data ) - { - Weird("truncated_link_header"); - return; - } - - auto& vlan_ref = saw_vlan ? inner_vlan : vlan; - vlan_ref = ((pdata[0] << 8) + pdata[1]) & 0xfff; - protocol = ((pdata[2] << 8) + pdata[3]); - pdata += 4; // Skip the vlan header - saw_vlan = true; - eth_type = protocol; - } - break; - - // PPPoE carried over the ethernet frame. - case 0x8864: - { - if ( pdata + 8 >= end_of_data ) - { - Weird("truncated_link_header"); - return; - } - - protocol = (pdata[6] << 8) + pdata[7]; - pdata += 8; // Skip the PPPoE session and PPP header - - if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_pppoe_encapsulation"); - return; - } - } - break; - } - } - - // Check for MPLS in VLAN. - if ( protocol == 0x8847 ) - have_mpls = true; - - // Normal path to determine Layer 3 protocol. - if ( ! have_mpls && l3_proto == L3_UNKNOWN ) - { - if ( protocol == 0x800 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x86dd ) - l3_proto = L3_IPV6; - else if ( protocol == 0x0806 || protocol == 0x8035 ) - l3_proto = L3_ARP; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ethernet"); - return; - } - } - - break; - } - - case DLT_PPP_SERIAL: - { - // Get PPP protocol. - int protocol = (pdata[2] << 8) + pdata[3]; - pdata += GetLinkHeaderSize(link_type); - - if ( protocol == 0x0281 ) - { - // MPLS Unicast. Remove the pdata link layer and - // denote a header size of zero before the IP header. - have_mpls = true; - } - else if ( protocol == 0x0021 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x0057 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet_in_ppp_encapsulation"); - return; - } - break; - } - - case DLT_IEEE802_11_RADIO: - { - if ( pdata + 3 >= end_of_data ) - { - Weird("truncated_radiotap_header"); - return; - } - - // Skip over the RadioTap header - int rtheader_len = (pdata[3] << 8) + pdata[2]; - - if ( pdata + rtheader_len >= end_of_data ) - { - Weird("truncated_radiotap_header"); - return; - } - - pdata += rtheader_len; - // fallthrough - } - - case DLT_IEEE802_11: - { - u_char len_80211 = 24; // minimal length of data frames - - if ( pdata + len_80211 >= end_of_data ) - { - Weird("truncated_802_11_header"); - return; - } - - u_char fc_80211 = pdata[0]; // Frame Control field - - // Skip non-data frame types (management & control). - if ( ! ((fc_80211 >> 2) & 0x02) ) - return; - - // Skip subtypes without data. - if ( (fc_80211 >> 4) & 0x04 ) - return; - - // 'To DS' and 'From DS' flags set indicate use of the 4th - // address field. - if ( (pdata[1] & 0x03) == 0x03 ) - len_80211 += l2_addr_len; - - // Look for the QoS indicator bit. - if ( (fc_80211 >> 4) & 0x08 ) - { - // Skip in case of A-MSDU subframes indicated by QoS - // control field. - if ( pdata[len_80211] & 0x80) - return; - - len_80211 += 2; - } - - if ( pdata + len_80211 >= end_of_data ) - { - Weird("truncated_802_11_header"); - return; - } - - // Determine link-layer addresses based - // on 'To DS' and 'From DS' flags - switch ( pdata[1] & 0x03 ) { - case 0x00: - l2_src = pdata + 10; - l2_dst = pdata + 4; - break; - - case 0x01: - l2_src = pdata + 10; - l2_dst = pdata + 16; - break; - - case 0x02: - l2_src = pdata + 16; - l2_dst = pdata + 4; - break; - - case 0x03: - l2_src = pdata + 24; - l2_dst = pdata + 16; - break; - } - - // skip 802.11 data header - pdata += len_80211; - - if ( pdata + 8 >= end_of_data ) - { - Weird("truncated_802_11_header"); - return; - } - // Check that the DSAP and SSAP are both SNAP and that the control - // field indicates that this is an unnumbered frame. - // The organization code (24bits) needs to also be zero to - // indicate that this is encapsulated ethernet. - if ( pdata[0] == 0xAA && pdata[1] == 0xAA && pdata[2] == 0x03 && - pdata[3] == 0 && pdata[4] == 0 && pdata[5] == 0 ) - { - pdata += 6; - } - else - { - // If this is a logical link control frame without the - // possibility of having a protocol we care about, we'll - // just skip it for now. - return; - } - - int protocol = (pdata[0] << 8) + pdata[1]; - if ( protocol == 0x0800 ) - l3_proto = L3_IPV4; - else if ( protocol == 0x86DD ) - l3_proto = L3_IPV6; - else if ( protocol == 0x0806 || protocol == 0x8035 ) - l3_proto = L3_ARP; - else - { - Weird("non_ip_packet_in_ieee802_11"); - return; - } - pdata += 2; - - break; - } - - case DLT_NFLOG: - { - // See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html - - uint8_t protocol = pdata[0]; - - if ( protocol == AF_INET ) - l3_proto = L3_IPV4; - else if ( protocol == AF_INET6 ) - l3_proto = L3_IPV6; - else - { - Weird("non_ip_in_nflog"); - return; - } - - uint8_t version = pdata[1]; - - if ( version != 0 ) - { - Weird("unknown_nflog_version"); - return; - } - - // Skip to TLVs. - pdata += 4; - - uint16_t tlv_len; - uint16_t tlv_type; - - while ( true ) - { - if ( pdata + 4 >= end_of_data ) - { - Weird("nflog_no_pcap_payload"); - return; - } - - // TLV Type and Length values are specified in host byte order - // (libpcap should have done any needed byteswapping already). - - tlv_len = *(reinterpret_cast(pdata)); - tlv_type = *(reinterpret_cast(pdata + 2)); - - auto constexpr nflog_type_payload = 9; - - if ( tlv_type == nflog_type_payload ) - { - // The raw packet payload follows this TLV. - pdata += 4; - break; - } - else - { - // The Length value includes the 4 octets for the Type and - // Length values, but TLVs are also implicitly padded to - // 32-bit alignments (that padding may not be included in - // the Length value). - - if ( tlv_len < 4 ) - { - Weird("nflog_bad_tlv_len"); - return; - } - else - { - auto rem = tlv_len % 4; - - if ( rem != 0 ) - tlv_len += 4 - rem; - } - - pdata += tlv_len; - } - } - - break; - } - - default: - { - // Assume we're pointing at IP. Just figure out which version. - pdata += GetLinkHeaderSize(link_type); - if ( pdata + sizeof(struct ip) >= end_of_data ) - { - Weird("truncated_link_header"); - return; - } - - const struct ip* ip = (const struct ip *)pdata; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("non_ip_packet"); - return; - } - - break; - } - } - - if ( have_mpls ) - { - // Skip the MPLS label stack. - bool end_of_stack = false; - - while ( ! end_of_stack ) - { - if ( pdata + 4 >= end_of_data ) - { - Weird("truncated_link_header"); - return; - } - - end_of_stack = *(pdata + 2) & 0x01; - pdata += 4; - } - - // We assume that what remains is IP - if ( pdata + sizeof(struct ip) >= end_of_data ) - { - Weird("no_ip_in_mpls_payload"); - return; - } - - const struct ip* ip = (const struct ip *)pdata; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_mpls_payload"); - return; - } - } - - else if ( zeek::detail::encap_hdr_size ) - { - // Blanket encapsulation. We assume that what remains is IP. - if ( pdata + zeek::detail::encap_hdr_size + sizeof(struct ip) >= end_of_data ) - { - Weird("no_ip_left_after_encap"); - return; - } - - pdata += zeek::detail::encap_hdr_size; - - const struct ip* ip = (const struct ip *)pdata; - - if ( ip->ip_v == 4 ) - l3_proto = L3_IPV4; - else if ( ip->ip_v == 6 ) - l3_proto = L3_IPV6; - else - { - // Neither IPv4 nor IPv6. - Weird("no_ip_in_encap"); - return; - } - - } - - // We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs (c) L3_ARP vs - // (d) L3_UNKNOWN. - - // Calculate how much header we've used up. - hdr_size = (pdata - data); -} - -RecordValPtr Packet::ToRawPktHdrVal() const +IntrusivePtr Packet::ToRawPktHdrVal() const { static auto raw_pkt_hdr_type = id::find_type("raw_pkt_hdr"); static auto l2_hdr_type = id::find_type("l2_hdr"); @@ -685,10 +181,30 @@ ValPtr Packet::FmtEUI48(const u_char* mac) const void Packet::Describe(ODesc* d) const { - const IP_Hdr ip = IP(); - d->Add(ip.SrcAddr()); - d->Add("->"); - d->Add(ip.DstAddr()); + switch ( l3_proto ) + { + case L3_ARP: + d->Add("ARP"); + break; + case L3_IPV4: + d->Add("IPv4"); + break; + case L3_IPV6: + d->Add("IPv6"); + break; + default: + d->Add("Unknown L3 protocol"); + } + + // Add IP-specific information + if ( l3_proto == L3_IPV4 || l3_proto == L3_IPV6 ) + { + const IP_Hdr ip = IP(); + d->Add(": "); + d->Add(ip.SrcAddr()); + d->Add("->"); + d->Add(ip.DstAddr()); + } } } // namespace zeek diff --git a/src/iosource/Packet.h b/src/iosource/Packet.h index 5ac6f1f876..648db8270a 100644 --- a/src/iosource/Packet.h +++ b/src/iosource/Packet.h @@ -127,7 +127,7 @@ public: /** * Interprets the Layer 3 of the packet as IP and returns a - * correspondign object. + * corresponding object. */ const IP_Hdr IP() const; @@ -141,14 +141,11 @@ public: RecordVal* BuildPktHdrVal() const; /** - * Static method returning the link-layer header size for a given - * link type. + * Returns the end of the captured data for bound checking. * - * @param link_type The link tyoe. - * - * @return The header size in bytes, or -1 if not known. + * @return End of the packet data. */ - static int GetLinkHeaderSize(int link_type); + const u_char* const GetEndOfData() const; /** * Describes the packet, with standard signature. @@ -158,7 +155,14 @@ public: /** * Maximal length of a layer 2 address. */ - static const int l2_addr_len = 6; + static const int L2_ADDR_LEN = 6; + + /** + * Empty layer 2 address to be used as default value. For example, the + * LinuxSLL llanalyzer doesn't have a destination address in the header + * and thus sets it to this default address. + */ + static constexpr const u_char L2_EMPTY_ADDR[L2_ADDR_LEN] = { 0 }; // These are passed in through the constructor. std::string tag; /// Used in serialization @@ -166,8 +170,9 @@ public: pkt_timeval ts; /// Capture timestamp const u_char* data; /// Packet data. uint32_t len; /// Actual length on wire - uint32_t cap_len; /// Captured packet length + uint32_t cap_len; /// Captured packet length uint32_t link_type; /// pcap link_type (DLT_EN10MB, DLT_RAW, etc) + const uint8_t* cur_pos; /// Pointer to the current start of unanalyzed payload data in the raw packet, used by llanalyzers // These are computed from Layer 2 data. These fields are only valid if // Layer2Valid() returns true. @@ -224,13 +229,10 @@ public: */ bool l3_checksummed; -private: - // Calculate layer 2 attributes. - void ProcessLayer2(); - - // Wrapper to generate a packet-level weird. + // Wrapper to generate a packet-level weird. Has to be public for llanalyzers to use it. void Weird(const char* name); +private: // Renders an MAC address into its ASCII representation. ValPtr FmtEUI48(const u_char* mac) const; diff --git a/src/iosource/PktDumper.cc b/src/iosource/PktDumper.cc index 87e4c6cae7..336b5f7777 100644 --- a/src/iosource/PktDumper.cc +++ b/src/iosource/PktDumper.cc @@ -53,11 +53,6 @@ const char* PktDumper::ErrorMsg() const return errmsg.size() ? errmsg.c_str() : nullptr; } -int PktDumper::HdrSize() const - { - return is_open ? props.hdr_size : -1; - } - void PktDumper::Opened(const Properties& arg_props) { is_open = true; diff --git a/src/iosource/PktDumper.h b/src/iosource/PktDumper.h index c279a704f0..5210a3c98f 100644 --- a/src/iosource/PktDumper.h +++ b/src/iosource/PktDumper.h @@ -50,11 +50,6 @@ public: */ const char* ErrorMsg() const; - /** - * Returns the size of the link-layer headers with this dumper. - */ - int HdrSize() const; - // PktDumper interface for derived classes to implement. /** @@ -97,7 +92,6 @@ protected: */ struct Properties { std::string path; - int hdr_size; double open_time; }; diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index c20e29d35c..519c6da81e 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -90,16 +90,6 @@ double PktSrc::CurrentPacketWallClock() void PktSrc::Opened(const Properties& arg_props) { - if ( Packet::GetLinkHeaderSize(arg_props.link_type) < 0 ) - { - char buf[512]; - snprintf(buf, sizeof(buf), - "unknown data link type 0x%x", arg_props.link_type); - Error(buf); - Close(); - return; - } - props = arg_props; SetClosed(false); diff --git a/src/iosource/pcap/Dumper.cc b/src/iosource/pcap/Dumper.cc index 78e3f97cf8..b7a47756ce 100644 --- a/src/iosource/pcap/Dumper.cc +++ b/src/iosource/pcap/Dumper.cc @@ -82,7 +82,6 @@ void PcapDumper::Open() } props.open_time = run_state::network_time; - props.hdr_size = Packet::GetLinkHeaderSize(pcap_datalink(pd)); Opened(props); } diff --git a/src/llanalyzer/Analyzer.cc b/src/llanalyzer/Analyzer.cc new file mode 100644 index 0000000000..ff5798070b --- /dev/null +++ b/src/llanalyzer/Analyzer.cc @@ -0,0 +1,47 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include "Analyzer.h" + +namespace zeek::llanalyzer { + +Analyzer::Analyzer(std::string name) + { + Tag t = llanalyzer_mgr->GetComponentTag(name); + + if ( ! t ) + reporter->InternalError("unknown llanalyzer name %s", name.c_str()); + + Init(t); + } + +Analyzer::Analyzer(const Tag& tag) + { + Init(tag); + } + +/* PRIVATE */ +void Analyzer::Init(const Tag& _tag) + { + tag = _tag; + } + +const Tag Analyzer::GetAnalyzerTag() const + { + assert(tag); + return tag; + } + +const char* Analyzer::GetAnalyzerName() const + { + assert(tag); + return llanalyzer_mgr->GetComponentName(tag).c_str(); + } + +bool Analyzer::IsAnalyzer(const char* name) + { + assert(tag); + return llanalyzer_mgr->GetComponentName(tag).compare(name) == 0; + } + +} diff --git a/src/llanalyzer/Analyzer.h b/src/llanalyzer/Analyzer.h new file mode 100644 index 0000000000..06dd75e5d1 --- /dev/null +++ b/src/llanalyzer/Analyzer.h @@ -0,0 +1,89 @@ +// See the file "COPYING" in the main distribution directory for copyright. +#pragma once + +#include "Defines.h" +#include "Manager.h" +#include "Tag.h" +#include + +namespace zeek::llanalyzer { + +/** + * Result of low layer analysis. + */ +enum class AnalyzerResult { + Failed, // Analysis failed + Continue, // Analysis succeded and an encapuslated protocol was determined + Terminate // Analysis succeded and there is no further analysis to do +}; + +using AnalysisResultTuple = std::tuple; + +class Analyzer { +public: + /** + * Constructor. + * + * @param name The name for the type of analyzer. The name must match + * the one the corresponding Component registers. + */ + explicit Analyzer(std::string name); + + /** + * Constructor. + * + * @param tag The tag for the type of analyzer. The tag must map to + * the name the corresponding Component registers. + */ + explicit Analyzer(const Tag& tag); + + /** + * Destructor. + */ + virtual ~Analyzer() = default; + + /** + * Returns the tag associated with the analyzer's type. + */ + const Tag GetAnalyzerTag() const; + + /** + * Returns a textual description of the analyzer's type. This is + * what's passed to the constructor and usally corresponds to the + * protocol name, e.g., "ARP". + */ + const char* GetAnalyzerName() const; + + /** + * Returns true if this analyzer's type matches the name passes in. + * This is shortcut for comparing GetAnalyzerName() with the given + * name. + * + * @param name The name to check. + */ + bool IsAnalyzer(const char* name); + + /** + * Analyzes the given packet. The analysis is supposed to start at cur_pos + * of the packet, which points to the so far unanalyzed part of the packet. + * If the analyzed protocol encapsulates another protocol, the packet's + * cur_pos should be updated to point to that payload. + * + * @param packet The packet to analyze. + * + * @return A tuple of analysis result and identifier. The result indicates + * how to proceed. If analysis can continue, the identifier determines the + * encapsulated protocol. + */ + virtual std::tuple Analyze(Packet* packet) = 0; + +protected: + friend class Manager; + +private: + Tag tag; + + void Init(const Tag& tag); +}; + +} // llanalyzer namespace end diff --git a/src/llanalyzer/AnalyzerSet.h b/src/llanalyzer/AnalyzerSet.h new file mode 100644 index 0000000000..de71fb7dda --- /dev/null +++ b/src/llanalyzer/AnalyzerSet.h @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "Analyzer.h" +#include "Defines.h" + +namespace zeek::llanalyzer { + +class Analyzer; + +class AnalyzerSet { +public: + virtual ~AnalyzerSet() = default; + virtual Analyzer* Dispatch(identifier_t identifier) = 0; + virtual void Reset() = 0; + +protected: + friend class Manager; + + virtual void DumpDebug() const = 0; +}; + +} diff --git a/src/llanalyzer/CMakeLists.txt b/src/llanalyzer/CMakeLists.txt new file mode 100644 index 0000000000..6a5fa16708 --- /dev/null +++ b/src/llanalyzer/CMakeLists.txt @@ -0,0 +1,21 @@ +include(ZeekSubdir) + +include_directories(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_subdirectory(protocol) +add_subdirectory(dispatchers) + +set(llanalyzer_SRCS + Analyzer.cc + ProtocolAnalyzerSet.cc + Manager.cc + Component.cc + Tag.cc + Config.cc +) + +bro_add_subdir_library(llanalyzer ${llanalyzer_SRCS}) +add_dependencies(bro_llanalyzer generate_outputs) diff --git a/src/llanalyzer/Component.cc b/src/llanalyzer/Component.cc new file mode 100644 index 0000000000..a5991cbf2b --- /dev/null +++ b/src/llanalyzer/Component.cc @@ -0,0 +1,33 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Component.h" +#include "Desc.h" +#include "Manager.h" + +using namespace zeek::llanalyzer; + +Component::Component(const std::string& name, factory_callback arg_factory, Tag::subtype_t arg_subtype, bool arg_enabled) + : plugin::Component(plugin::component::LLANALYZER, name), + plugin::TaggedComponent(arg_subtype) + { + factory = arg_factory; + enabled = arg_enabled; + } + +void Component::Initialize() + { + InitializeTag(); + llanalyzer_mgr->RegisterComponent(this, "LLANALYZER_"); + } + +void Component::DoDescribe(ODesc* d) const + { + if ( factory ) + { + d->Add("LLANALYZER_"); + d->Add(CanonicalName()); + d->Add(", "); + } + + d->Add(enabled ? "enabled" : "disabled"); + } diff --git a/src/llanalyzer/Component.h b/src/llanalyzer/Component.h new file mode 100644 index 0000000000..5d9ed0c6f3 --- /dev/null +++ b/src/llanalyzer/Component.h @@ -0,0 +1,61 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "zeek-config.h" +#include "util.h" +#include "Tag.h" + +#include "plugin/Component.h" +#include "plugin/TaggedComponent.h" + +namespace zeek::llanalyzer { + +class Analyzer; + +class Component : public plugin::Component, + public plugin::TaggedComponent { +public: + typedef Analyzer* (*factory_callback)(); + + Component(const std::string& name, factory_callback factory, Tag::subtype_t subtype = 0, bool enabled = true); + ~Component() override = default; + + /** + * Initialization function. This function has to be called before any + * plugin component functionality is used; it is used to add the + * plugin component to the list of components and to initialize tags + */ + void Initialize() override; + + /** + * Returns the analyzer's factory function. + */ + factory_callback Factory() const { return factory; } + + /** + * Returns true if the analyzer is currently enabled and hence + * available for use. + */ + bool Enabled() const { return enabled; } + + /** + * Enables or disables this analyzer. + * + * @param arg_enabled True to enabled, false to disable. + * + */ + void SetEnabled(bool arg_enabled) { enabled = arg_enabled; } + +protected: + /** + * Overriden from plugin::Component. + */ + void DoDescribe(ODesc* d) const override; + +private: + factory_callback factory; // The analyzer's factory callback. + bool enabled; // True if the analyzer is enabled. +}; + +} diff --git a/src/llanalyzer/Config.cc b/src/llanalyzer/Config.cc new file mode 100644 index 0000000000..1c068d27c2 --- /dev/null +++ b/src/llanalyzer/Config.cc @@ -0,0 +1,87 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Config.h" +#include "Reporter.h" +#include "DebugLogger.h" + +namespace zeek::llanalyzer { + +// ############################## +// ####### DispatcherConfig ##### +// ############################## +const std::string& DispatcherConfig::GetName() const + { + return name; + } + +const std::map& DispatcherConfig::GetMappings() const + { + return mappings; + } + +void DispatcherConfig::AddMapping(identifier_t identifier, + const std::string& analyzer_name) + { + DBG_LOG(DBG_LLANALYZER, "Adding configuration mapping: %s -> %#x -> %s", + name.c_str(), identifier, analyzer_name.c_str()); + + if ( mappings.count(identifier) ) + reporter->InternalError("Invalid config, identifier %#x already exists " + "for dispatcher set %s.", + identifier, name.c_str()); + + mappings.emplace(identifier, analyzer_name); + } + +bool DispatcherConfig::operator==(const DispatcherConfig& rhs) const + { + return name == rhs.name; + } + +bool DispatcherConfig::operator!=(const DispatcherConfig& rhs) const + { + return ! (rhs == *this); + } + +// ############################## +// ########### Config ########### +// ############################## +std::optional> +Config::GetDispatcherConfig(const std::string& name) + { + auto it = std::find_if( + dispatchers.begin(), dispatchers.end(), + [&](const DispatcherConfig& conf) { + return conf.GetName() == name; + }); + + if ( it == dispatchers.end() ) + return {}; + else + return {std::ref(*it)}; + } + +const std::vector& Config::GetDispatchers() const + { + return dispatchers; + } + +DispatcherConfig& Config::AddDispatcherConfig(const std::string& name) + { + return dispatchers.emplace_back(name); + } + +void Config::AddMapping(const std::string& name, identifier_t identifier, + const std::string& analyzer_name) + { + // Create dispatcher config if it does not exist yet + std::optional> dispatch_config = + GetDispatcherConfig(name); + + if ( ! dispatch_config ) + AddDispatcherConfig(name).AddMapping(identifier, analyzer_name); + else + dispatch_config->get().AddMapping(identifier, analyzer_name); + } + +} // namespace llanalyzer diff --git a/src/llanalyzer/Config.h b/src/llanalyzer/Config.h new file mode 100644 index 0000000000..0ce9837174 --- /dev/null +++ b/src/llanalyzer/Config.h @@ -0,0 +1,44 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include +#include +#include + +#include "Defines.h" + +namespace zeek::llanalyzer { + +class DispatcherConfig { +public: + explicit DispatcherConfig(const std::string name) : name(std::move(name)) { } + + const std::string& GetName() const; + const std::map& GetMappings() const; + + void AddMapping(identifier_t identifier, const std::string& analyzer_name); + + bool operator==(const DispatcherConfig& rhs) const; + bool operator!=(const DispatcherConfig& rhs) const; + +private: + const std::string name; + std::map mappings; +}; + +class Config { + +public: + const std::vector& GetDispatchers() const; + std::optional> GetDispatcherConfig(const std::string& name); + DispatcherConfig& AddDispatcherConfig(const std::string& name); + void AddMapping(const std::string& name, identifier_t identifier, const std::string& analyzer_name); + +private: + std::vector dispatchers; +}; + +} diff --git a/src/llanalyzer/Defines.h b/src/llanalyzer/Defines.h new file mode 100644 index 0000000000..307af09e3a --- /dev/null +++ b/src/llanalyzer/Defines.h @@ -0,0 +1,11 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include + +namespace zeek::llanalyzer { + + using identifier_t = uint32_t; + +} diff --git a/src/llanalyzer/Manager.cc b/src/llanalyzer/Manager.cc new file mode 100644 index 0000000000..0aa8e7f138 --- /dev/null +++ b/src/llanalyzer/Manager.cc @@ -0,0 +1,285 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include + +#include "Config.h" +#include "Manager.h" +#include "NetVar.h" +#include "ProtocolAnalyzerSet.h" +#include "plugin/Manager.h" + +using namespace zeek::llanalyzer; + +Manager::Manager() + : plugin::ComponentManager("LLAnalyzer", "Tag") + { + } + +Manager::~Manager() + { + delete analyzer_set; + } + +void Manager::InitPostScript() + { + auto llanalyzer_mapping = zeek::id::find("LLAnalyzer::config_map"); + if ( ! llanalyzer_mapping ) + return; + + auto mapping_val = llanalyzer_mapping->GetVal()->AsVectorVal(); + if ( mapping_val->Size() == 0 ) + return; + + Config configuration; + for (unsigned int i = 0; i < mapping_val->Size(); i++) + { + auto* rv = mapping_val->At(i)->AsRecordVal(); + auto parent = rv->GetField("parent"); + std::string parent_name = parent ? Lookup(parent->AsEnumVal())->Name() : "ROOT"; + auto identifier = rv->GetField("identifier")->AsCount(); + auto analyzer = rv->GetField("analyzer")->AsEnumVal(); + + configuration.AddMapping(parent_name, identifier, Lookup(analyzer)->Name()); + } + + analyzer_set = new ProtocolAnalyzerSet(configuration, "DefaultAnalyzer"); + } + +void Manager::Done() + { + } + +void Manager::DumpDebug() + { +#ifdef DEBUG + DBG_LOG(DBG_LLANALYZER, "Available llanalyzers after zeek_init():"); + for ( auto& current : GetComponents() ) + { + DBG_LOG(DBG_LLANALYZER, " %s (%s)", current->Name().c_str(), IsEnabled(current->Tag()) ? "enabled" : "disabled"); + } + + // Dump Analyzer Set + if (analyzer_set) + analyzer_set->DumpDebug(); +#endif + } + +bool Manager::EnableAnalyzer(const Tag& tag) + { + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + DBG_LOG(DBG_LLANALYZER, "Enabling analyzer %s", p->Name().c_str()); + p->SetEnabled(true); + + return true; + } + +bool Manager::EnableAnalyzer(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + DBG_LOG(DBG_LLANALYZER, "Enabling analyzer %s", p->Name().c_str()); + p->SetEnabled(true); + + return true; + } + +bool Manager::DisableAnalyzer(const Tag& tag) + { + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + DBG_LOG(DBG_LLANALYZER, "Disabling analyzer %s", p->Name().c_str()); + p->SetEnabled(false); + + return true; + } + +bool Manager::DisableAnalyzer(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + DBG_LOG(DBG_LLANALYZER, "Disabling analyzer %s", p->Name().c_str()); + p->SetEnabled(false); + + return true; + } + +void Manager::DisableAllAnalyzers() + { + DBG_LOG(DBG_LLANALYZER, "Disabling all analyzers"); + + std::list all_analyzers = GetComponents(); + for ( const auto& analyzer : all_analyzers ) + analyzer->SetEnabled(false); + } + +zeek::llanalyzer::Tag Manager::GetAnalyzerTag(const char* name) + { + return GetComponentTag(name); + } + +bool Manager::IsEnabled(Tag tag) + { + if ( ! tag ) + return false; + + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + return p->Enabled(); + } + +bool Manager::IsEnabled(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + return p->Enabled(); + } + +Analyzer* Manager::InstantiateAnalyzer(const Tag& tag) + { + Component* c = Lookup(tag); + + if ( ! c ) + { + reporter->InternalWarning("request to instantiate unknown llanalyzer"); + return nullptr; + } + + if ( ! c->Enabled() ) + return nullptr; + + if ( ! c->Factory() ) + { + reporter->InternalWarning("analyzer %s cannot be instantiated dynamically", GetComponentName(tag).c_str()); + return nullptr; + } + + Analyzer* a = c->Factory()(); + + if ( ! a ) + { + reporter->InternalWarning("analyzer instantiation failed"); + return nullptr; + } + + if ( tag != a->GetAnalyzerTag() ) + { + reporter->InternalError("Mismatch of requested analyzer %s and instantiated analyzer %s. This usually means that the plugin author made a mistake.", + GetComponentName(tag).c_str(), GetComponentName(a->GetAnalyzerTag()).c_str()); + return nullptr; + } + + return a; + } + +Analyzer* Manager::InstantiateAnalyzer(const std::string& name) + { + Tag tag = GetComponentTag(name); + return tag ? InstantiateAnalyzer(tag) : nullptr; + } + +void Manager::ProcessPacket(Packet* packet) + { +#ifdef DEBUG + static size_t counter = 0; + DBG_LOG(DBG_LLANALYZER, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time); +#endif + + if ( ! analyzer_set ) + return; + + // Dispatch and analyze layers + AnalyzerResult result = AnalyzerResult::Continue; + identifier_t next_layer_id = packet->link_type; + do + { + auto current_analyzer = analyzer_set->Dispatch(next_layer_id); + + // Analyzer not found + if ( current_analyzer == nullptr ) + { + DBG_LOG(DBG_LLANALYZER, "Could not find analyzer for identifier %#x", next_layer_id); + packet->Weird("no_suitable_analyzer_found"); + break; + } + + // Analyze this layer and get identifier of next layer protocol + std::tie(result, next_layer_id) = current_analyzer->Analyze(packet); + +#ifdef DEBUG + switch ( result ) + { + case AnalyzerResult::Continue: + DBG_LOG(DBG_LLANALYZER, "Analysis in %s succeeded, next layer identifier is %#x.", + current_analyzer->GetAnalyzerName(), next_layer_id); + break; + case AnalyzerResult::Terminate: + DBG_LOG(DBG_LLANALYZER, "Done, last found layer identifier was %#x.", next_layer_id); + break; + case AnalyzerResult::Failed: + DBG_LOG(DBG_LLANALYZER, "Analysis failed in %s", current_analyzer->GetAnalyzerName()); + } +#endif + + } while ( result == AnalyzerResult::Continue ); + + if ( result == AnalyzerResult::Terminate ) + CustomEncapsulationSkip(packet); + + // Processing finished, reset analyzer set state for next packet + analyzer_set->Reset(); + } + +void Manager::CustomEncapsulationSkip(Packet* packet) + { + if ( zeek::detail::encap_hdr_size > 0 ) + { + auto pdata = packet->cur_pos; + + // Blanket encapsulation. We assume that what remains is IP. + if ( pdata + zeek::detail::encap_hdr_size + sizeof(struct ip) >= packet->GetEndOfData() ) + { + packet->Weird("no_ip_left_after_encap"); + return; + } + + pdata += zeek::detail::encap_hdr_size; + + auto ip = (const struct ip*)pdata; + + switch ( ip->ip_v ) + { + case 4: + packet->l3_proto = L3_IPV4; + break; + case 6: + packet->l3_proto = L3_IPV6; + break; + default: + { + // Neither IPv4 nor IPv6. + packet->Weird("no_ip_in_encap"); + return; + } + } + } + } diff --git a/src/llanalyzer/Manager.h b/src/llanalyzer/Manager.h new file mode 100644 index 0000000000..54e444bb07 --- /dev/null +++ b/src/llanalyzer/Manager.h @@ -0,0 +1,167 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +#include "Tag.h" +#include "Analyzer.h" +#include "Component.h" +#include "AnalyzerSet.h" +#include "plugin/ComponentManager.h" +#include "iosource/Packet.h" + +#include "../Dict.h" +#include "../net_util.h" + +namespace zeek::llanalyzer { + +class AnalyzerSet; + +class Manager : public plugin::ComponentManager { +public: + /** + * Constructor. + */ + Manager(); + + /** + * Destructor. + */ + ~Manager(); + + /** + * Second-stage initialization of the manager. This is called late + * during Bro's initialization after any scripts are processed. + */ + void InitPostScript(); + + /** + * Finished the manager's operations. + */ + void Done(); + + /** + * Dumps out the state of all registered analyzers to the \c analyzer + * debug stream. Should be called only after any \c zeek_init events + * have executed to ensure that any of their changes are applied. + */ + void DumpDebug(); // Called after zeek_init() events. + + /** + * Enables an analyzer type. Only enabled analyzers will be + * instantiated for new connections. + * + * @param tag The analyzer's tag. + * + * @return True if successful. + */ + bool EnableAnalyzer(const Tag& tag); + + /** + * Enables an analyzer type. Only enabled analyzers will be + * instantiated for new connections. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @return True if successful. + */ + bool EnableAnalyzer(EnumVal* tag); + + /** + * Enables an analyzer type. Disabled analyzers will not be + * instantiated for new connections. + * + * @param tag The analyzer's tag. + * + * @return True if successful. + */ + bool DisableAnalyzer(const Tag& tag); + + /** + * Disables an analyzer type. Disabled analyzers will not be + * instantiated for new connections. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @return True if successful. + */ + bool DisableAnalyzer(EnumVal* tag); + + /** + * Disables all currently registered analyzers. + */ + void DisableAllAnalyzers(); + + /** + * Returns the tag associated with an analyer name, or the tag + * associated with an error if no such analyzer exists. + * + * @param name The canonical analyzer name to check. + */ + Tag GetAnalyzerTag(const char* name); + + /** + * Returns true if an analyzer is enabled. + * + * @param tag The analyzer's tag. + */ + bool IsEnabled(Tag tag); + + /** + * Returns true if an analyzer is enabled. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + */ + bool IsEnabled(EnumVal* tag); + + /** + * Instantiates a new analyzer instance. + * + * @param tag The analyzer's tag. + * + * @return The new analyzer instance. Returns + * null if tag is invalid, the requested analyzer is disabled, or the + * analyzer can't be instantiated. + */ + Analyzer* InstantiateAnalyzer(const Tag& tag); + + /** + * Instantiates a new analyzer. + * + * @param name The name of the analyzer. + * + * @return The new analyzer instance. Returns + * null if the name is not known or if the requested analyzer that is + * disabled. + */ + Analyzer* InstantiateAnalyzer(const std::string& name); + + /** + * Processes a packet by applying the configured low layer analyzers. + * + * @param packet The packet to process. + */ + void ProcessPacket(Packet* packet); + +protected: + /** + * Skips a fixed amount of packet data that is defined by encap_hdr_size. + * It is assumed that an IP header follows. + * + * @param packet The packet to adapt. + */ + void CustomEncapsulationSkip(Packet* packet); + +private: + AnalyzerSet* analyzer_set = nullptr; + +}; + +} + +extern zeek::llanalyzer::Manager* llanalyzer_mgr; diff --git a/src/llanalyzer/ProtocolAnalyzerSet.cc b/src/llanalyzer/ProtocolAnalyzerSet.cc new file mode 100644 index 0000000000..6d2aeca83f --- /dev/null +++ b/src/llanalyzer/ProtocolAnalyzerSet.cc @@ -0,0 +1,137 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "ProtocolAnalyzerSet.h" + +namespace zeek::llanalyzer { + +ProtocolAnalyzerSet::ProtocolAnalyzerSet(Config& configuration, const std::string& default_analyzer_name) + { + // Instantiate objects for all analyzers + for ( const auto& current_dispatcher_config : configuration.GetDispatchers() ) + { + for ( const auto& current_mapping : current_dispatcher_config.GetMappings() ) + { + // Check if already instantiated + if ( analyzers.count(current_mapping.second) != 0 ) + continue; + + // Check if analyzer exists + if ( Analyzer* newAnalyzer = llanalyzer_mgr->InstantiateAnalyzer(current_mapping.second) ) + analyzers.emplace(current_mapping.second, newAnalyzer); + } + } + + // Generate Dispatchers, starting at root + root_dispatcher = GetDispatcher(configuration, "ROOT"); + if ( root_dispatcher == nullptr ) + reporter->InternalError("No dispatching configuration for ROOT of llanalyzer set."); + + // Set up default analysis + auto it = analyzers.find(default_analyzer_name); + if ( it != analyzers.end() ) + default_analyzer = it->second; + else + default_analyzer = llanalyzer_mgr->InstantiateAnalyzer(default_analyzer_name); + + default_dispatcher = nullptr; + if ( default_analyzer != nullptr ) + default_dispatcher = GetDispatcher(configuration, default_analyzer_name); + + current_state = root_dispatcher; + } + +ProtocolAnalyzerSet::~ProtocolAnalyzerSet() + { + bool delete_default = default_analyzer != nullptr; + for ( const auto& current : analyzers ) + { + if ( current.second == default_analyzer ) + delete_default = false; + + delete current.second; + } + + if ( delete_default ) + delete default_analyzer; + } + +Analyzer* ProtocolAnalyzerSet::Dispatch(identifier_t identifier) + { + // Because leaf nodes (aka no more dispatching) can still have an existing analyzer that returns more identifiers, + // current_state needs to be checked to be not null. In this case there would have been an analyzer dispatched + // in the last layer, but no dispatcher for it (end of FSM) + const Value* result = nullptr; + if ( current_state ) + result = current_state->Lookup(identifier); + + if ( result == nullptr ) + { + if ( current_state != default_dispatcher ) + { + // Switch to default analysis once + current_state = default_dispatcher; + return default_analyzer; + } + return nullptr; + } + else + { + current_state = result->dispatcher; + return result->analyzer; + } + } + +void ProtocolAnalyzerSet::Reset() + { + current_state = root_dispatcher; + } + +void ProtocolAnalyzerSet::DumpDebug() const + { +#ifdef DEBUG + DBG_LOG(DBG_LLANALYZER, "ProtocolAnalyzerSet FSM:"); + for ( const auto& current : dispatchers ) + { + DBG_LOG(DBG_LLANALYZER, " Dispatcher (%p): %s", current.second, current.first.c_str()); + current.second->DumpDebug(); + } +#endif + } + +Dispatcher* ProtocolAnalyzerSet::GetDispatcher(Config& configuration, const std::string& dispatcher_name) + { + // Is it already created? + if ( dispatchers.count(dispatcher_name) != 0 ) + return dispatchers[dispatcher_name]; + + // Create new dispatcher from config + std::optional> dispatcher_config = configuration.GetDispatcherConfig(dispatcher_name); + if ( ! dispatcher_config ) + // No such dispatcher found, this is therefore implicitly a leaf + return nullptr; + + const auto& mappings = dispatcher_config->get().GetMappings(); + + Dispatcher* dispatcher = new dispatcher_impl(); + dispatchers.emplace(dispatcher_name, dispatcher); + + for ( const auto& current_mapping : mappings ) + { + // No analyzer with this name. Report warning and ignore. + if ( analyzers.count(current_mapping.second) == 0 ) + { + reporter->InternalWarning("No analyzer %s found for dispatching identifier %#x of %s, ignoring.", + current_mapping.second.c_str(), + current_mapping.first, + dispatcher_name.c_str()); + continue; + } + + dispatcher->Register(current_mapping.first, analyzers.at(current_mapping.second), + GetDispatcher(configuration, current_mapping.second)); + } + + return dispatcher; + } + +} diff --git a/src/llanalyzer/ProtocolAnalyzerSet.h b/src/llanalyzer/ProtocolAnalyzerSet.h new file mode 100644 index 0000000000..1f6a786456 --- /dev/null +++ b/src/llanalyzer/ProtocolAnalyzerSet.h @@ -0,0 +1,39 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "AnalyzerSet.h" +#include "Config.h" +#include "dispatchers/Dispatcher.h" +#include "dispatchers/UniversalDispatcher.h" +#include "dispatchers/VectorDispatcher.h" + +namespace zeek::llanalyzer { + +class ProtocolAnalyzerSet : public AnalyzerSet { + +public: + explicit ProtocolAnalyzerSet(Config& configuration, const std::string& default_analyzer_name); + ~ProtocolAnalyzerSet() override; + + Analyzer* Dispatch(identifier_t identifier) override; + void Reset() override; + +protected: + void DumpDebug() const override; + +private: + using dispatcher_impl = VectorDispatcher; + //using dispatcher_impl = UniversalDispatcher; + + std::map analyzers; + std::map dispatchers; + Dispatcher* root_dispatcher = nullptr; + Dispatcher* default_dispatcher = nullptr; + Dispatcher* current_state = nullptr; + Analyzer* default_analyzer = nullptr; + + Dispatcher* GetDispatcher(Config& configuration, const std::string& dispatcher_name); +}; + +} diff --git a/src/llanalyzer/Tag.cc b/src/llanalyzer/Tag.cc new file mode 100644 index 0000000000..9960ed5e35 --- /dev/null +++ b/src/llanalyzer/Tag.cc @@ -0,0 +1,41 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Tag.h" +#include "Manager.h" + +namespace zeek::llanalyzer { + +Tag Tag::Error; + +Tag::Tag(type_t type, subtype_t subtype) + : zeek::Tag(llanalyzer_mgr->GetTagType(), type, subtype) + { + } + +Tag& Tag::operator=(const Tag& other) + { + zeek::Tag::operator=(other); + return *this; + } + +const IntrusivePtr& Tag::AsVal() const + { + return zeek::Tag::AsVal(llanalyzer_mgr->GetTagType()); + } + +EnumVal* Tag::AsEnumVal() const + { + return AsVal().get(); + } + +Tag::Tag(IntrusivePtr val) + : zeek::Tag(std::move(val)) + { + } + +Tag::Tag(EnumVal* val) + : zeek::Tag({NewRef {}, val}) + { + } + +} diff --git a/src/llanalyzer/Tag.h b/src/llanalyzer/Tag.h new file mode 100644 index 0000000000..66c2cdc6cb --- /dev/null +++ b/src/llanalyzer/Tag.h @@ -0,0 +1,130 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "zeek-config.h" +#include "../Tag.h" + +namespace zeek::plugin { + template class TaggedComponent; + template class ComponentManager; +} +namespace plugin { + template + using TaggedComponent [[deprecated("Remove in v4.1. Use zeek::plugin::TaggedComponent instead.")]] = + zeek::plugin::TaggedComponent; + template + using ComponentManager [[deprecated("Remove in v4.1. Use zeek::plugin::ComponentManager instead.")]] = + zeek::plugin::ComponentManager; +} + +namespace zeek::llanalyzer { + +class Manager; +class Component; + +/** + * Class to identify a protocol analyzer type. + */ +class Tag : public zeek::Tag { +public: + /* + * Copy constructor. + */ + Tag(const Tag& other) : zeek::Tag(other) { } + + /** + * Default constructor. This initializes the tag with an error value + * that will make \c operator \c bool return false. + */ + Tag() : zeek::Tag() { } + + /** + * Destructor. + */ + ~Tag() = default; + + /** + * Returns false if the tag represents an error value rather than a + * legal analyzer type. + */ + explicit operator bool() const { return *this != Tag(); } + + /** + * Assignment operator. + */ + Tag& operator=(const Tag& other); + + /** + * Compares two tags for equality. + */ + bool operator==(const Tag& other) const + { + return zeek::Tag::operator==(other); + } + + /** + * Compares two tags for inequality. + */ + bool operator!=(const Tag& other) const + { + return zeek::Tag::operator!=(other); + } + + /** + * Compares two tags for less-than relationship. + */ + bool operator<(const Tag& other) const + { + return zeek::Tag::operator<(other); + } + + /** + * Returns the \c Analyzer::Tag enum that corresponds to this tag. + * The returned value does not have its ref-count increased. + * + * @param etype the script-layer enum type associated with the tag. + */ + const IntrusivePtr& AsVal() const; + + /** + * Returns the \c Analyzer::Tag enum that corresponds to this tag. + * The returned value does not have its ref-count increased. + * + * @param etype the script-layer enum type associated with the tag. + */ + [[deprecated("Remove in v4.1. Use AsVal() instead.")]] + EnumVal* AsEnumVal() const; + + static Tag Error; + +protected: + + friend class llanalyzer::Manager; + friend class plugin::ComponentManager; + friend class plugin::TaggedComponent; + + /** + * Constructor. + * + * @param type The main type. Note that the \a llanalyzer::Manager + * manages the value space internally, so noone else should assign + * any main types. + * + * @param subtype The sub type, which is left to an analyzer for + * interpretation. By default it's set to zero. + */ + explicit Tag(type_t type, subtype_t subtype = 0); + + /** + * Constructor. + * + * @param val An enum value of script type \c Analyzer::Tag. + */ + explicit Tag(IntrusivePtr val); + + [[deprecated("Remove in v4.1. Construct from IntrusivePtr instead")]] + explicit Tag(EnumVal* val); +}; + +} diff --git a/src/llanalyzer/dispatchers/CMakeLists.txt b/src/llanalyzer/dispatchers/CMakeLists.txt new file mode 100644 index 0000000000..ea4183fef8 --- /dev/null +++ b/src/llanalyzer/dispatchers/CMakeLists.txt @@ -0,0 +1,13 @@ +include(ZeekSubdir) + +include_directories(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +set(dispatcher_SRCS + UniversalDispatcher.cc + VectorDispatcher.cc +) + +bro_add_subdir_library(llanalyzer_dispatcher ${dispatcher_SRCS}) diff --git a/src/llanalyzer/dispatchers/Dispatcher.h b/src/llanalyzer/dispatchers/Dispatcher.h new file mode 100644 index 0000000000..a59060459d --- /dev/null +++ b/src/llanalyzer/dispatchers/Dispatcher.h @@ -0,0 +1,47 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +#include "Analyzer.h" +#include "Defines.h" + +namespace zeek::llanalyzer { + +class Dispatcher; // Forward decl for Value +using register_pair = std::pair>; +using register_map = std::map>; + +class Value { +public: + Analyzer* analyzer; + Dispatcher* dispatcher; + + Value(Analyzer* analyzer, Dispatcher* dispatcher) + : analyzer(analyzer), dispatcher(dispatcher) + { + } +}; + +class Dispatcher { +public: + virtual ~Dispatcher() = default; + + virtual bool Register(identifier_t identifier, Analyzer* analyzer, Dispatcher* dispatcher) = 0; + virtual void Register(const register_map& data) + { + for ( auto& current : data ) + Register(current.first, current.second.first, current.second.second); + } + + virtual const Value* Lookup(identifier_t identifier) const = 0; + + virtual size_t Size() const = 0; + virtual void Clear() = 0; + + virtual void DumpDebug() const = 0; + }; + +} diff --git a/src/llanalyzer/dispatchers/UniversalDispatcher.cc b/src/llanalyzer/dispatchers/UniversalDispatcher.cc new file mode 100644 index 0000000000..2bc86664e1 --- /dev/null +++ b/src/llanalyzer/dispatchers/UniversalDispatcher.cc @@ -0,0 +1,210 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "UniversalDispatcher.h" + +namespace zeek::llanalyzer { + +UniversalDispatcher::UniversalDispatcher() : generator(rd()) + { + SetBins(2); + + table = std::vector(ONE << m, {0, nullptr}); + + // Initialize random engine + distribution_a = std::uniform_int_distribution(1, ~static_cast(0)); + distribution_b = std::uniform_int_distribution(0, (ONE << w_minus_m) - ONE); + + // Initialize random parameters + RandomizeAB(); + } + +UniversalDispatcher::~UniversalDispatcher() + { + FreeValues(); + } + +bool UniversalDispatcher::Register(identifier_t identifier, Analyzer* analyzer, Dispatcher* dispatcher) + { +#if DEBUG > 1 + std::shared_ptr deferred(nullptr, [=](...) { + std::cout << "Inserted " << identifier << std::endl; + }); +#endif + + uint64_t hashed_id = Hash(identifier); + if ( table[hashed_id].second == nullptr ) + { + // Free bin, insert the value + table[hashed_id] = std::make_pair(identifier, new Value(analyzer, dispatcher)); + return true; + } + else if ( table[hashed_id].first != identifier ) + { + // The bin is not empty, but the content isn't the to-be-inserted identifier --> resolve collision + + // Create intermediate representation with the new element in it, then rehash with that data + std::vector intermediate = CreateIntermediate(); + intermediate.emplace_back(identifier, new Value(analyzer, dispatcher)); + + // Try increasing the #bins until it works or it can't get any larger. + Rehash(intermediate); + return true; + } + + // Analyzer with this ID is already registered. + return false; + } + +void UniversalDispatcher::Register(const register_map& data) + { + // Analyzer already registered + for ( const auto& current : data ) + { + if ( table[Hash(current.first)].second != nullptr ) + throw std::invalid_argument("Analyzer " + std::to_string(current.first) + " already registered!"); + } + + // Create intermediate representation of current analyzer set, then add all new ones + std::vector intermediate = CreateIntermediate(); + for ( const auto& current : data ) + intermediate.emplace_back(current.first, new Value(current.second.first, current.second.second)); + + Rehash(intermediate); + } + +Value* UniversalDispatcher::Lookup(identifier_t identifier) const + { + uint64_t hashed_id = Hash(identifier); + + // The hashed_id can't be larger than the number of bins + assert(hashed_id < table.size() && "Hashed ID is outside of the hash table range!"); + + pair_t entry = table[hashed_id]; + if ( entry.second != nullptr && entry.first == identifier ) + return entry.second; + + return nullptr; + } + +size_t UniversalDispatcher::Size() const + { + size_t result = 0; + for ( const auto& current : table ) + { + if ( current.second != nullptr ) + result++; + } + return result; + } + +void UniversalDispatcher::Clear() + { + // Free all analyzers + FreeValues(); + + SetBins(2); + table = std::vector(ONE << m, {0, nullptr}); + RandomizeAB(); + } + +size_t UniversalDispatcher::BucketCount() + { + return table.size(); + } + +void UniversalDispatcher::Rehash() + { + // Intermediate representation is just the current table without nulls + Rehash(CreateIntermediate()); + } + +void UniversalDispatcher::DumpDebug() const + { +#ifdef DEBUG + DBG_LOG(DBG_LLANALYZER, " Dispatcher elements (used/total): %lu/%lu", Size(), table.size()); + for ( size_t i = 0; i < table.size(); i++ ) + { + if ( table[i].second != nullptr ) + DBG_LOG(DBG_LLANALYZER, " %#8x => %s, %p", table[i].first, table[i].second->analyzer->GetAnalyzerName(), table[i].second->dispatcher); + } +#endif + } + +// ####################### +// ####### PRIVATE ####### +// ####################### + +void UniversalDispatcher::FreeValues() + { + for ( auto& current : table ) + { + delete current.second; + current.second = nullptr; + } + } + +void UniversalDispatcher::Rehash(const std::vector& intermediate) + { + while ( ! FindCollisionFreeHashFunction(intermediate) ) + { + DBG_LOG(DBG_LLANALYZER, "Rehashing did not work. Increasing #bins to %" PRIu64 " (%" PRIu64 " bit).", (uint64_t)std::pow(2, m + 1), m + 1); + SetBins(m + 1); + } + } + +bool UniversalDispatcher::FindCollisionFreeHashFunction(const std::vector& intermediate) + { + // Don't even try if the number of values is larger than the number of buckets + if ( ONE << m < intermediate.size() ) + return false; + + // Remember the hash function parameters to not break the table if rehashing doesn't work + uint64_t stored_a = a; + uint64_t stored_b = b; + + // Because the hash function hashes all values in the universe uniformly to m bins with probability 1/m + // we should at least try a multiple of #bins times. + for ( size_t i = 1; i <= (ONE << m); i++ ) + { + // Step 1: Re-randomize hash function parameters + RandomizeAB(); + + // Step 2: Create new table + std::vector new_table(ONE << m, {0, nullptr}); + + // Step 3: Try to insert all elements into the new table with the new hash function + bool finished = true; + for ( const auto& current : intermediate ) + { + uint64_t hashed_id = Hash(current.first); + assert(hashed_id < new_table.size()); + if ( new_table[hashed_id].second == nullptr ) + { + // Free bin, insert the value + new_table[hashed_id] = current; + } + else + { + // The bin is not empty which means there is a collision + // (there are no duplicates in the intermediate representation so that can't be the case) + finished = false; + break; + } + } + + // Step 4: If the inserting finished without collisions, overwrite the previous table and exit + if ( finished ) + { + DBG_LOG(DBG_LLANALYZER, "Took %lu rehash(es) to resolve.", i); + table = new_table; + return true; + } + } + + // Finding a collision free hash function failed. Revert the hash function parameters. + a = stored_a; + b = stored_b; + return false; + } + +} diff --git a/src/llanalyzer/dispatchers/UniversalDispatcher.h b/src/llanalyzer/dispatchers/UniversalDispatcher.h new file mode 100644 index 0000000000..52b2baa982 --- /dev/null +++ b/src/llanalyzer/dispatchers/UniversalDispatcher.h @@ -0,0 +1,108 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include "Dispatcher.h" + +namespace zeek::llanalyzer { + +class UniversalDispatcher : public Dispatcher { +public: + UniversalDispatcher(); + ~UniversalDispatcher() override; + + bool Register(identifier_t identifier, Analyzer* analyzer, Dispatcher* dispatcher) override; + void Register(const register_map& data) override; + Value* Lookup(identifier_t identifier) const override; + size_t Size() const override; + void Clear() override; + + void DumpDebug() const override; + size_t BucketCount(); + + // Rehashes the hash table including re-randomization of the hash function. + void Rehash(); + +private: + using pair_t = std::pair; + static const uint64_t ONE = 1u; + + // Chosen random constants for the currently selected collision free random hash function + uint64_t a = 0; // Needs to be a random odd positive value < 2^(sizeof(uint64_t) * 8) + uint64_t b = 0; // Needs to be a random non-negative value < 2^(((sizeof(uint64_t) * 8) - M) + + // Current bits that define the number of bins. Initially 2 which means there are 2^2 = 4 bins. + uint64_t m = 2; + + // Current shift value which is the number of bits that are "insignificant" because of the universe size. + uint64_t w_minus_m = 0; + + // RNG + std::random_device rd; + std::mt19937_64 generator; + std::uniform_int_distribution distribution_a; + std::uniform_int_distribution distribution_b; + +// Debug +#if DEBUG > 0 + size_t nptr_counter = 0; + size_t mismatch_counter = 0; + size_t all_counter = 0; +#endif + + std::vector table; + + void FreeValues(); + + void Rehash(const std::vector& intermediate); + + /** + * Tries to find a collision free hash function with the current number of buckets. + * + * @param intermediate The key-value set to store in the hashtable. + * @return true, iff it found a collision-free hash function. + */ + bool FindCollisionFreeHashFunction(const std::vector& intermediate); + + [[nodiscard]] inline uint64_t Hash(const uint64_t value) const + { + return (a * value + b) >> w_minus_m; + } + + inline void RandomizeAB() + { + do { + a = distribution_a(generator); + } while ( a % 2 == 0 ); + + b = distribution_b(generator); + } + + inline void SetBins(uint64_t new_m) + { + if ( new_m > (sizeof(uint64_t) * 8) ) + throw std::runtime_error("Number of bits for bin count too large."); + + m = new_m; + w_minus_m = sizeof(uint64_t) * 8 - m; + distribution_b = std::uniform_int_distribution(0, ((uint64_t)(1u) << w_minus_m) - (uint64_t)(1u)); + } + + inline std::vector CreateIntermediate() + { + std::vector intermediate; + for ( const auto& current : table ) + { + if ( current.second != nullptr ) + { + assert(current.second->analyzer != nullptr); + intermediate.emplace_back(current.first, current.second); + } + } + return intermediate; + } + +}; + +} diff --git a/src/llanalyzer/dispatchers/VectorDispatcher.cc b/src/llanalyzer/dispatchers/VectorDispatcher.cc new file mode 100644 index 0000000000..d948e3efda --- /dev/null +++ b/src/llanalyzer/dispatchers/VectorDispatcher.cc @@ -0,0 +1,122 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include + +#include "VectorDispatcher.h" + +namespace zeek::llanalyzer { + +VectorDispatcher::~VectorDispatcher() + { + FreeValues(); + } + +bool VectorDispatcher::Register(identifier_t identifier, Analyzer* analyzer, Dispatcher* dispatcher) + { + // If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it. + if ( table.size() == 1 && table[0] == nullptr ) + { + table[0] = new Value(analyzer, dispatcher); + lowest_identifier = identifier; + return true; + } + + // If highestIdentifier == identifier, overwrite would happen -> no check needed, will return false + if ( GetHighestIdentifier() < identifier ) + { + table.resize(table.size() + (identifier - GetHighestIdentifier()), nullptr); + } + else if ( identifier < lowest_identifier ) + { + // Lower than the lowest registered identifier. Shift up by lowerBound - identifier + identifier_t distance = lowest_identifier - identifier; + table.resize(table.size() + distance, nullptr); + + // Shift values + for ( ssize_t i = table.size() - 1; i >= 0; i-- ) + { + if ( table[i] != nullptr ) + { + table.at(i + distance) = table.at(i); + table.at(i) = nullptr; + } + } + + lowest_identifier = identifier; + } + + int64_t index = identifier - lowest_identifier; + if ( table[index] == nullptr ) + { + table[index] = new Value(analyzer, dispatcher); + return true; + } + + return false; + } + +void VectorDispatcher::Register(const register_map& data) + { + // Search smallest and largest identifier and resize vector + const auto& lowest_new = + std::min_element(data.begin(), data.end(), + [](const register_pair& a, const register_pair& b) { + return a.first < b.first; + }); + + // Register lowest first in order to do shifting only once + Register(lowest_new->first, lowest_new->second.first, lowest_new->second.second); + for ( auto i = data.begin(); i != data.end(); i++ ) + { + // Already added if i == lowest_new + if ( i == lowest_new ) + continue; + + if ( ! Register(i->first, i->second.first, i->second.second) ) + throw std::invalid_argument("Analyzer already registered!"); + } + } + +const Value* VectorDispatcher::Lookup(identifier_t identifier) const + { + int64_t index = identifier - lowest_identifier; + if ( index >= 0 && index < static_cast(table.size()) && table[index] != nullptr ) + return table[index]; + + return nullptr; + } + +size_t VectorDispatcher::Size() const + { + return std::count_if(table.begin(), table.end(), [](const auto* v) { return v != nullptr; }); + } + +void VectorDispatcher::Clear() + { + FreeValues(); + table.clear(); + } + +void VectorDispatcher::FreeValues() + { + for ( auto& current : table ) + { + delete current; + current = nullptr; + } + } + +void VectorDispatcher::DumpDebug() const + { +#ifdef DEBUG + DBG_LOG(DBG_LLANALYZER, " Dispatcher elements (used/total): %lu/%lu", Size(), table.size()); + DBG_LOG(DBG_LLANALYZER, "TABLE SIZE %lu", table.size()); + for ( size_t i = 0; i < table.size(); i++ ) + { + if ( table[i] != nullptr ) + DBG_LOG(DBG_LLANALYZER, " %#8lx => %s, %p", i+lowest_identifier, table[i]->analyzer->GetAnalyzerName(), table[i]->dispatcher); + } +#endif + } + +} diff --git a/src/llanalyzer/dispatchers/VectorDispatcher.h b/src/llanalyzer/dispatchers/VectorDispatcher.h new file mode 100644 index 0000000000..e801cde476 --- /dev/null +++ b/src/llanalyzer/dispatchers/VectorDispatcher.h @@ -0,0 +1,41 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include "Dispatcher.h" + +namespace zeek::llanalyzer { + +class VectorDispatcher : public Dispatcher { +public: + VectorDispatcher() + : table(std::vector(1, nullptr)) + { } + + ~VectorDispatcher() override; + + bool Register(identifier_t identifier, Analyzer* analyzer, Dispatcher* dispatcher) override; + void Register(const register_map& data) override; + + const Value* Lookup(identifier_t identifier) const override; + + size_t Size() const override; + void Clear() override; + +protected: + void DumpDebug() const override; + +private: + identifier_t lowest_identifier = 0; + std::vector table; + + void FreeValues(); + + inline identifier_t GetHighestIdentifier() const + { + return lowest_identifier + table.size() - 1; + } +}; + +} diff --git a/src/llanalyzer/protocol/CMakeLists.txt b/src/llanalyzer/protocol/CMakeLists.txt new file mode 100644 index 0000000000..fbcef0f2c9 --- /dev/null +++ b/src/llanalyzer/protocol/CMakeLists.txt @@ -0,0 +1,18 @@ +add_subdirectory(default) + +add_subdirectory(wrapper) +add_subdirectory(null) +add_subdirectory(ethernet) +add_subdirectory(vlan) +add_subdirectory(pppoe) +add_subdirectory(ppp_serial) +add_subdirectory(ieee802_11) +add_subdirectory(ieee802_11_radio) +add_subdirectory(fddi) +add_subdirectory(nflog) +add_subdirectory(mpls) +add_subdirectory(linux_sll) + +add_subdirectory(arp) +add_subdirectory(ipv4) +add_subdirectory(ipv6) diff --git a/src/llanalyzer/protocol/arp/ARP.cc b/src/llanalyzer/protocol/arp/ARP.cc new file mode 100644 index 0000000000..4def2a449f --- /dev/null +++ b/src/llanalyzer/protocol/arp/ARP.cc @@ -0,0 +1,19 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "ARP.h" + +using namespace zeek::llanalyzer::ARP; + +ARPAnalyzer::ARPAnalyzer() + : zeek::llanalyzer::Analyzer("ARP") + { + } + +std::tuple ARPAnalyzer::Analyze(Packet* packet) + { + // TODO: Make ARP analyzer a native LL analyzer + packet->l3_proto = L3_ARP; + + // Leave LL analyzer land + return { AnalyzerResult::Terminate, 0 }; + } diff --git a/src/llanalyzer/protocol/arp/ARP.h b/src/llanalyzer/protocol/arp/ARP.h new file mode 100644 index 0000000000..6bf341ed51 --- /dev/null +++ b/src/llanalyzer/protocol/arp/ARP.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::ARP { + +class ARPAnalyzer : public Analyzer { +public: + ARPAnalyzer(); + ~ARPAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new ARPAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/arp/CMakeLists.txt b/src/llanalyzer/protocol/arp/CMakeLists.txt new file mode 100644 index 0000000000..2db553b496 --- /dev/null +++ b/src/llanalyzer/protocol/arp/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE $ {CMAKE_CURRENT_SOURCE_DIR} $ {CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer ARP) +zeek_plugin_cc(ARP.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/arp/Plugin.cc b/src/llanalyzer/protocol/arp/Plugin.cc new file mode 100644 index 0000000000..5a7f296ddf --- /dev/null +++ b/src/llanalyzer/protocol/arp/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "plugin/Plugin.h" +#include "ARP.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_ARP { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("ARP", + zeek::llanalyzer::ARP::ARPAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::ARP"; + config.description = "ARP LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/default/CMakeLists.txt b/src/llanalyzer/protocol/default/CMakeLists.txt new file mode 100644 index 0000000000..3753b432f9 --- /dev/null +++ b/src/llanalyzer/protocol/default/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer Default) +zeek_plugin_cc(Default.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/default/Default.cc b/src/llanalyzer/protocol/default/Default.cc new file mode 100644 index 0000000000..3e01e1ba8c --- /dev/null +++ b/src/llanalyzer/protocol/default/Default.cc @@ -0,0 +1,28 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Default.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::Default; + +DefaultAnalyzer::DefaultAnalyzer() + : zeek::llanalyzer::Analyzer("DefaultAnalyzer") + { + } + +std::tuple DefaultAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + // Assume we're pointing at IP. Just figure out which version. + if ( pdata + sizeof(struct ip) >= packet->GetEndOfData() ) + { + packet->Weird("default_ll_analyser_failed"); + return { AnalyzerResult::Failed, 0 }; + } + + auto ip = (const struct ip *)pdata; + identifier_t protocol = ip->ip_v; + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/default/Default.h b/src/llanalyzer/protocol/default/Default.h new file mode 100644 index 0000000000..6c02b72f62 --- /dev/null +++ b/src/llanalyzer/protocol/default/Default.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::Default { + +class DefaultAnalyzer : public Analyzer { +public: + DefaultAnalyzer(); + ~DefaultAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new DefaultAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/default/Plugin.cc b/src/llanalyzer/protocol/default/Plugin.cc new file mode 100644 index 0000000000..cc92fd6870 --- /dev/null +++ b/src/llanalyzer/protocol/default/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Default.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_Default { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("DefaultAnalyzer", + zeek::llanalyzer::Default::DefaultAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::DefaultAnalyzer"; + config.description = "Default LL-Analyzer for IP fallback"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/ethernet/CMakeLists.txt b/src/llanalyzer/protocol/ethernet/CMakeLists.txt new file mode 100644 index 0000000000..583abdcc44 --- /dev/null +++ b/src/llanalyzer/protocol/ethernet/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer Ethernet) +zeek_plugin_cc(Ethernet.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ethernet/Ethernet.cc b/src/llanalyzer/protocol/ethernet/Ethernet.cc new file mode 100644 index 0000000000..564a3bf10f --- /dev/null +++ b/src/llanalyzer/protocol/ethernet/Ethernet.cc @@ -0,0 +1,75 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Ethernet.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::Ethernet; + +EthernetAnalyzer::EthernetAnalyzer() + : zeek::llanalyzer::Analyzer("Ethernet") + { + } + +std::tuple EthernetAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + // Skip past Cisco FabricPath to encapsulated ethernet frame. + if ( pdata[12] == 0x89 && pdata[13] == 0x03 ) + { + auto constexpr cfplen = 16; + + if ( pdata + cfplen + 14 >= end_of_data ) + { + packet->Weird("truncated_link_header_cfp"); + return { AnalyzerResult::Failed, 0 }; + } + + pdata += cfplen; + } + + // Get protocol being carried from the ethernet frame. + identifier_t protocol = (pdata[12] << 8) + pdata[13]; + + packet->eth_type = protocol; + packet->l2_dst = pdata; + packet->l2_src = pdata + 6; + + // Ethernet II frames + if ( protocol >= 1536 ) + { + pdata += 14; + return { AnalyzerResult::Continue, protocol }; + } + + // Other ethernet frame types + if ( protocol <= 1500 ) + { + if ( pdata + 16 >= end_of_data ) + { + packet->Weird("truncated_ethernet_frame"); + return { AnalyzerResult::Failed, 0 }; + } + + // In the following we use undefined EtherTypes to signal uncommon + // frame types. This allows specialized analyzers to take over. + // Note that pdata remains at the start of the ethernet frame. + + // IEEE 802.2 SNAP + if ( pdata[14] == 0xAA && pdata[15] == 0xAA) + return { AnalyzerResult::Continue, 1502 }; + + // Novell raw IEEE 802.3 + if ( pdata[14] == 0xFF && pdata[15] == 0xFF) + return { AnalyzerResult::Continue, 1503 }; + + + // IEEE 802.2 LLC + return { AnalyzerResult::Continue, 1501 }; + } + + // Undefined (1500 < EtherType < 1536) + packet->Weird("undefined_ether_type"); + return { AnalyzerResult::Failed, protocol }; + } diff --git a/src/llanalyzer/protocol/ethernet/Ethernet.h b/src/llanalyzer/protocol/ethernet/Ethernet.h new file mode 100644 index 0000000000..a6805f84a8 --- /dev/null +++ b/src/llanalyzer/protocol/ethernet/Ethernet.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::Ethernet { + +class EthernetAnalyzer : public Analyzer { +public: + EthernetAnalyzer(); + ~EthernetAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new EthernetAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ethernet/Plugin.cc b/src/llanalyzer/protocol/ethernet/Plugin.cc new file mode 100644 index 0000000000..5ae0e1cc87 --- /dev/null +++ b/src/llanalyzer/protocol/ethernet/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Ethernet.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_Ethernet { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("Ethernet", + zeek::llanalyzer::Ethernet::EthernetAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::Ethernet"; + config.description = "Ethernet LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/fddi/CMakeLists.txt b/src/llanalyzer/protocol/fddi/CMakeLists.txt new file mode 100644 index 0000000000..a1a7c571a7 --- /dev/null +++ b/src/llanalyzer/protocol/fddi/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer FDDI) +zeek_plugin_cc(FDDI.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/fddi/FDDI.cc b/src/llanalyzer/protocol/fddi/FDDI.cc new file mode 100644 index 0000000000..c5594061f7 --- /dev/null +++ b/src/llanalyzer/protocol/fddi/FDDI.cc @@ -0,0 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "FDDI.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::FDDI; + +FDDIAnalyzer::FDDIAnalyzer() + : zeek::llanalyzer::Analyzer("FDDI") + { + } + +std::tuple FDDIAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + auto hdr_size = 13 + 8; // FDDI header + LLC + + if ( pdata + hdr_size >= packet->GetEndOfData() ) + { + packet->Weird("FDDI_analyzer_failed"); + return { AnalyzerResult::Failed, 0 }; + } + + // We just skip the header and hope for default analysis + pdata += hdr_size; + return { AnalyzerResult::Continue, -1 }; + } diff --git a/src/llanalyzer/protocol/fddi/FDDI.h b/src/llanalyzer/protocol/fddi/FDDI.h new file mode 100644 index 0000000000..b4217739dd --- /dev/null +++ b/src/llanalyzer/protocol/fddi/FDDI.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::FDDI { + +class FDDIAnalyzer : public zeek::llanalyzer::Analyzer { +public: + FDDIAnalyzer(); + ~FDDIAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static zeek::llanalyzer::Analyzer* Instantiate() + { + return new FDDIAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/fddi/Plugin.cc b/src/llanalyzer/protocol/fddi/Plugin.cc new file mode 100644 index 0000000000..809f30312f --- /dev/null +++ b/src/llanalyzer/protocol/fddi/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "FDDI.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_FDDI { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("FDDI", + zeek::llanalyzer::FDDI::FDDIAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::FDDI"; + config.description = "FDDI LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/ieee802_11/CMakeLists.txt b/src/llanalyzer/protocol/ieee802_11/CMakeLists.txt new file mode 100644 index 0000000000..e8f20d8e80 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer IEEE802_11) +zeek_plugin_cc(IEEE802_11.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ieee802_11/IEEE802_11.cc b/src/llanalyzer/protocol/ieee802_11/IEEE802_11.cc new file mode 100644 index 0000000000..363706ae49 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11/IEEE802_11.cc @@ -0,0 +1,113 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IEEE802_11.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::IEEE802_11; + +IEEE802_11Analyzer::IEEE802_11Analyzer() + : zeek::llanalyzer::Analyzer("IEEE802_11") + { + } + +std::tuple IEEE802_11Analyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + u_char len_80211 = 24; // minimal length of data frames + + if ( pdata + len_80211 >= end_of_data ) + { + packet->Weird("truncated_802_11_header"); + return { AnalyzerResult::Failed, 0 }; + } + + u_char fc_80211 = pdata[0]; // Frame Control field + + // Skip non-data frame types (management & control). + if ( ! ((fc_80211 >> 2) & 0x02) ) + return { AnalyzerResult::Failed, 0 }; + + // Skip subtypes without data. + if ( (fc_80211 >> 4) & 0x04 ) + return { AnalyzerResult::Failed, 0 }; + + // 'To DS' and 'From DS' flags set indicate use of the 4th + // address field. + if ( (pdata[1] & 0x03) == 0x03 ) + len_80211 += packet->L2_ADDR_LEN; + + // Look for the QoS indicator bit. + if ( (fc_80211 >> 4) & 0x08 ) + { + // Skip in case of A-MSDU subframes indicated by QoS + // control field. + if ( pdata[len_80211] & 0x80 ) + return { AnalyzerResult::Failed, 0 }; + + len_80211 += 2; + } + + if ( pdata + len_80211 >= end_of_data ) + { + packet->Weird("truncated_802_11_header"); + return { AnalyzerResult::Failed, 0 }; + } + + // Determine link-layer addresses based + // on 'To DS' and 'From DS' flags + switch ( pdata[1] & 0x03 ) + { + case 0x00: + packet->l2_src = pdata + 10; + packet->l2_dst = pdata + 4; + break; + + case 0x01: + packet->l2_src = pdata + 10; + packet->l2_dst = pdata + 16; + break; + + case 0x02: + packet->l2_src = pdata + 16; + packet->l2_dst = pdata + 4; + break; + + case 0x03: + packet->l2_src = pdata + 24; + packet->l2_dst = pdata + 16; + break; + } + + // skip 802.11 data header + pdata += len_80211; + + if ( pdata + 8 >= end_of_data ) + { + packet->Weird("truncated_802_11_header"); + return { AnalyzerResult::Failed, 0 }; + } + + // Check that the DSAP and SSAP are both SNAP and that the control + // field indicates that this is an unnumbered frame. + // The organization code (24bits) needs to also be zero to + // indicate that this is encapsulated ethernet. + if ( pdata[0] == 0xAA && pdata[1] == 0xAA && pdata[2] == 0x03 && + pdata[3] == 0 && pdata[4] == 0 && pdata[5] == 0 ) + { + pdata += 6; + } + else + { + // If this is a logical link control frame without the + // possibility of having a protocol we care about, we'll + // just skip it for now. + return { AnalyzerResult::Failed, 0 }; + } + + identifier_t protocol = (pdata[0] << 8) + pdata[1]; + pdata += 2; + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/ieee802_11/IEEE802_11.h b/src/llanalyzer/protocol/ieee802_11/IEEE802_11.h new file mode 100644 index 0000000000..930de4bce5 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11/IEEE802_11.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::IEEE802_11 { + +class IEEE802_11Analyzer : public Analyzer { +public: + IEEE802_11Analyzer(); + ~IEEE802_11Analyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new IEEE802_11Analyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ieee802_11/Plugin.cc b/src/llanalyzer/protocol/ieee802_11/Plugin.cc new file mode 100644 index 0000000000..b85fb29b9a --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IEEE802_11.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_IEEE802_11 { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("IEEE802_11", + zeek::llanalyzer::IEEE802_11::IEEE802_11Analyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::IEEE802_11"; + config.description = "IEEE 802.11 LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/ieee802_11_radio/CMakeLists.txt b/src/llanalyzer/protocol/ieee802_11_radio/CMakeLists.txt new file mode 100644 index 0000000000..2df7896a34 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11_radio/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer IEEE802_11_Radio) +zeek_plugin_cc(IEEE802_11_Radio.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.cc b/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.cc new file mode 100644 index 0000000000..ef39420c64 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.cc @@ -0,0 +1,38 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include + +#include "IEEE802_11_Radio.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::IEEE802_11_Radio; + +IEEE802_11_RadioAnalyzer::IEEE802_11_RadioAnalyzer() + : zeek::llanalyzer::Analyzer("IEEE802_11_Radio") + { + } + +std::tuple IEEE802_11_RadioAnalyzer::Analyze(Packet* packet) + { + auto pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + if ( pdata + 3 >= end_of_data ) + { + packet->Weird("truncated_radiotap_header"); + return { AnalyzerResult::Failed, 0 }; + } + + // Skip over the RadioTap header + int rtheader_len = (pdata[3] << 8) + pdata[2]; + + if ( pdata + rtheader_len >= end_of_data ) + { + packet->Weird("truncated_radiotap_header"); + return { AnalyzerResult::Failed, 0 }; + } + + packet->cur_pos += rtheader_len; + + return { AnalyzerResult::Continue, DLT_IEEE802_11 }; + } diff --git a/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.h b/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.h new file mode 100644 index 0000000000..8fd9d0af65 --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11_radio/IEEE802_11_Radio.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::IEEE802_11_Radio { + +class IEEE802_11_RadioAnalyzer : public Analyzer { +public: + IEEE802_11_RadioAnalyzer(); + ~IEEE802_11_RadioAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new IEEE802_11_RadioAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ieee802_11_radio/Plugin.cc b/src/llanalyzer/protocol/ieee802_11_radio/Plugin.cc new file mode 100644 index 0000000000..e0339be75d --- /dev/null +++ b/src/llanalyzer/protocol/ieee802_11_radio/Plugin.cc @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IEEE802_11_Radio.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_IEEE802_11_Radio { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("IEEE802_11_Radio", + zeek::llanalyzer::IEEE802_11_Radio::IEEE802_11_RadioAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::IEEE802_11_Radio"; + config.description = "IEEE 802.11 Radiotap LL-Analyzer"; + return config; + } + +} plugin; +} diff --git a/src/llanalyzer/protocol/ipv4/CMakeLists.txt b/src/llanalyzer/protocol/ipv4/CMakeLists.txt new file mode 100644 index 0000000000..ca4a2e033c --- /dev/null +++ b/src/llanalyzer/protocol/ipv4/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer IPv4) +zeek_plugin_cc(IPv4.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ipv4/IPv4.cc b/src/llanalyzer/protocol/ipv4/IPv4.cc new file mode 100644 index 0000000000..138ebc8460 --- /dev/null +++ b/src/llanalyzer/protocol/ipv4/IPv4.cc @@ -0,0 +1,18 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IPv4.h" + +using namespace zeek::llanalyzer::IPv4; + +IPv4Analyzer::IPv4Analyzer() + : zeek::llanalyzer::Analyzer("IPv4") + { + } + +std::tuple IPv4Analyzer::Analyze(Packet* packet) + { + packet->l3_proto = L3_IPV4; + + // Leave LL analyzer land + return { AnalyzerResult::Terminate, 0 }; + } diff --git a/src/llanalyzer/protocol/ipv4/IPv4.h b/src/llanalyzer/protocol/ipv4/IPv4.h new file mode 100644 index 0000000000..4e16ec4371 --- /dev/null +++ b/src/llanalyzer/protocol/ipv4/IPv4.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::IPv4 { + +class IPv4Analyzer : public Analyzer { +public: + IPv4Analyzer(); + ~IPv4Analyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new IPv4Analyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ipv4/Plugin.cc b/src/llanalyzer/protocol/ipv4/Plugin.cc new file mode 100644 index 0000000000..7990ac70e0 --- /dev/null +++ b/src/llanalyzer/protocol/ipv4/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IPv4.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_IPv4 { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("IPv4", + zeek::llanalyzer::IPv4::IPv4Analyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::IPv4"; + config.description = "IPv4 LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/ipv6/CMakeLists.txt b/src/llanalyzer/protocol/ipv6/CMakeLists.txt new file mode 100644 index 0000000000..36beced1b2 --- /dev/null +++ b/src/llanalyzer/protocol/ipv6/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE $ {CMAKE_CURRENT_SOURCE_DIR} $ {CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer IPv6) +zeek_plugin_cc(IPv6.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ipv6/IPv6.cc b/src/llanalyzer/protocol/ipv6/IPv6.cc new file mode 100644 index 0000000000..ee6b6ef059 --- /dev/null +++ b/src/llanalyzer/protocol/ipv6/IPv6.cc @@ -0,0 +1,18 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IPv6.h" + +using namespace zeek::llanalyzer::IPv6; + +IPv6Analyzer::IPv6Analyzer() + : zeek::llanalyzer::Analyzer("IPv6") + { + } + +std::tuple IPv6Analyzer::Analyze(Packet* packet) + { + packet->l3_proto = L3_IPV6; + + // Leave LL analyzer land + return { AnalyzerResult::Terminate, 0 }; + } diff --git a/src/llanalyzer/protocol/ipv6/IPv6.h b/src/llanalyzer/protocol/ipv6/IPv6.h new file mode 100644 index 0000000000..0364d6b4d5 --- /dev/null +++ b/src/llanalyzer/protocol/ipv6/IPv6.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::IPv6 { + +class IPv6Analyzer : public Analyzer { +public: + IPv6Analyzer(); + ~IPv6Analyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new IPv6Analyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ipv6/Plugin.cc b/src/llanalyzer/protocol/ipv6/Plugin.cc new file mode 100644 index 0000000000..137db569d3 --- /dev/null +++ b/src/llanalyzer/protocol/ipv6/Plugin.cc @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "plugin/Plugin.h" +#include "IPv6.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_IPv6 { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("IPv6", + zeek::llanalyzer::IPv6::IPv6Analyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::IPv6"; + config.description = "IPv6 LL-Analyzer"; + return config; + } +} plugin; + +} diff --git a/src/llanalyzer/protocol/linux_sll/CMakeLists.txt b/src/llanalyzer/protocol/linux_sll/CMakeLists.txt new file mode 100644 index 0000000000..069b1db41a --- /dev/null +++ b/src/llanalyzer/protocol/linux_sll/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE $ {CMAKE_CURRENT_SOURCE_DIR} $ {CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer LinuxSLL) +zeek_plugin_cc(LinuxSLL.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/linux_sll/LinuxSLL.cc b/src/llanalyzer/protocol/linux_sll/LinuxSLL.cc new file mode 100644 index 0000000000..975b8bba09 --- /dev/null +++ b/src/llanalyzer/protocol/linux_sll/LinuxSLL.cc @@ -0,0 +1,34 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "LinuxSLL.h" + +using namespace zeek::llanalyzer::LinuxSLL; + +LinuxSLLAnalyzer::LinuxSLLAnalyzer() + : zeek::llanalyzer::Analyzer("LinuxSLL") + { + } + +std::tuple LinuxSLLAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + if ( pdata + sizeof(SLLHeader) >= packet->GetEndOfData() ) + { + packet->Weird("truncated_Linux_SLL_header"); + return { AnalyzerResult::Failed, 0 }; + } + + //TODO: Handle different ARPHRD_types + auto hdr = (const SLLHeader*)pdata; + + identifier_t protocol = ntohs(hdr->protocol_type); + packet->l2_src = (u_char*) &(hdr->addr); + + // SLL doesn't include a destination address in the header, but not setting l2_dst to something + // here will cause crashes elsewhere. + packet->l2_dst = Packet::L2_EMPTY_ADDR; + + pdata += sizeof(SLLHeader); + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/linux_sll/LinuxSLL.h b/src/llanalyzer/protocol/linux_sll/LinuxSLL.h new file mode 100644 index 0000000000..72c53972b7 --- /dev/null +++ b/src/llanalyzer/protocol/linux_sll/LinuxSLL.h @@ -0,0 +1,35 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::LinuxSLL { + +class LinuxSLLAnalyzer : public Analyzer { +public: + LinuxSLLAnalyzer(); + ~LinuxSLLAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new LinuxSLLAnalyzer(); + } + +private: + + // Structure layout is based on https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html + struct SLLHeader + { + uint16_t packet_type; + uint16_t arphrd_type; + uint16_t addr_len; + uint64_t addr; + uint16_t protocol_type; + } __attribute__((__packed__)); +}; + +} diff --git a/src/llanalyzer/protocol/linux_sll/Plugin.cc b/src/llanalyzer/protocol/linux_sll/Plugin.cc new file mode 100644 index 0000000000..8968e38c79 --- /dev/null +++ b/src/llanalyzer/protocol/linux_sll/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "plugin/Plugin.h" +#include "LinuxSLL.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_LinuxSLL { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("LinuxSLL", + zeek::llanalyzer::LinuxSLL::LinuxSLLAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::LinuxSLL"; + config.description = "Linux cooked capture (SLL) LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/mpls/CMakeLists.txt b/src/llanalyzer/protocol/mpls/CMakeLists.txt new file mode 100644 index 0000000000..3fd7a9f8df --- /dev/null +++ b/src/llanalyzer/protocol/mpls/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer MPLS) +zeek_plugin_cc(MPLS.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/mpls/MPLS.cc b/src/llanalyzer/protocol/mpls/MPLS.cc new file mode 100644 index 0000000000..412cf74266 --- /dev/null +++ b/src/llanalyzer/protocol/mpls/MPLS.cc @@ -0,0 +1,55 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "MPLS.h" + +using namespace zeek::llanalyzer::MPLS; + +MPLSAnalyzer::MPLSAnalyzer() + : zeek::llanalyzer::Analyzer("MPLS") + { + } + +std::tuple MPLSAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + // Skip the MPLS label stack. + bool end_of_stack = false; + + while ( ! end_of_stack ) + { + if ( pdata + 4 >= end_of_data ) + { + packet->Weird("truncated_link_header"); + return { AnalyzerResult::Failed, 0 }; + } + + end_of_stack = *(pdata + 2u) & 0x01; + pdata += 4; + } + + // According to RFC3032 the encapsulated protocol is not encoded. + // We assume that what remains is IP. + if ( pdata + sizeof(struct ip) >= end_of_data ) + { + packet->Weird("no_ip_in_mpls_payload"); + return { AnalyzerResult::Failed, 0 }; + } + + auto ip = (const struct ip*)pdata; + + if ( ip->ip_v == 4 ) + packet->l3_proto = L3_IPV4; + else if ( ip->ip_v == 6 ) + packet->l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + packet->Weird("no_ip_in_mpls_payload"); + return { AnalyzerResult::Failed, 0 }; + } + + packet->hdr_size = (pdata - packet->data); + return { AnalyzerResult::Terminate, 0 }; + } diff --git a/src/llanalyzer/protocol/mpls/MPLS.h b/src/llanalyzer/protocol/mpls/MPLS.h new file mode 100644 index 0000000000..72581f5ae7 --- /dev/null +++ b/src/llanalyzer/protocol/mpls/MPLS.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::MPLS { + +class MPLSAnalyzer : public zeek::llanalyzer::Analyzer { +public: + MPLSAnalyzer(); + ~MPLSAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static zeek::llanalyzer::Analyzer* Instantiate() + { + return new MPLSAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/mpls/Plugin.cc b/src/llanalyzer/protocol/mpls/Plugin.cc new file mode 100644 index 0000000000..c24b1003f3 --- /dev/null +++ b/src/llanalyzer/protocol/mpls/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "MPLS.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_MPLS { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("MPLS", + zeek::llanalyzer::MPLS::MPLSAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::MPLS"; + config.description = "MPLS LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/nflog/CMakeLists.txt b/src/llanalyzer/protocol/nflog/CMakeLists.txt new file mode 100644 index 0000000000..12069356b9 --- /dev/null +++ b/src/llanalyzer/protocol/nflog/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer NFLog) +zeek_plugin_cc(NFLog.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/nflog/NFLog.cc b/src/llanalyzer/protocol/nflog/NFLog.cc new file mode 100644 index 0000000000..1f919dbca1 --- /dev/null +++ b/src/llanalyzer/protocol/nflog/NFLog.cc @@ -0,0 +1,80 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "NFLog.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::NFLog; + +NFLogAnalyzer::NFLogAnalyzer() + : zeek::llanalyzer::Analyzer("NFLog") + { + } + +std::tuple NFLogAnalyzer::Analyze(Packet* packet) { + auto& pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + // See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html + identifier_t protocol = pdata[0]; + uint8_t version = pdata[1]; + + if ( version != 0 ) + { + packet->Weird("unknown_nflog_version"); + return { AnalyzerResult::Failed, 0 }; + } + + // Skip to TLVs. + pdata += 4; + + uint16_t tlv_len; + uint16_t tlv_type; + + while ( true ) + { + if ( pdata + 4 >= end_of_data ) + { + packet->Weird("nflog_no_pcap_payload"); + return { AnalyzerResult::Failed, 0 }; + } + + // TLV Type and Length values are specified in host byte order + // (libpcap should have done any needed byteswapping already). + + tlv_len = *(reinterpret_cast(pdata)); + tlv_type = *(reinterpret_cast(pdata + 2)); + + auto constexpr nflog_type_payload = 9; + + if ( tlv_type == nflog_type_payload ) + { + // The raw packet payload follows this TLV. + pdata += 4; + break; + } + else + { + // The Length value includes the 4 octets for the Type and + // Length values, but TLVs are also implicitly padded to + // 32-bit alignments (that padding may not be included in + // the Length value). + + if ( tlv_len < 4 ) + { + packet->Weird("nflog_bad_tlv_len"); + return { AnalyzerResult::Failed, 0 }; + } + else + { + auto rem = tlv_len % 4; + + if ( rem != 0 ) + tlv_len += 4 - rem; + } + + pdata += tlv_len; + } + } + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/nflog/NFLog.h b/src/llanalyzer/protocol/nflog/NFLog.h new file mode 100644 index 0000000000..aeb8234c31 --- /dev/null +++ b/src/llanalyzer/protocol/nflog/NFLog.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::NFLog { + +class NFLogAnalyzer : public Analyzer { +public: + NFLogAnalyzer(); + ~NFLogAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new NFLogAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/nflog/Plugin.cc b/src/llanalyzer/protocol/nflog/Plugin.cc new file mode 100644 index 0000000000..16106fee2d --- /dev/null +++ b/src/llanalyzer/protocol/nflog/Plugin.cc @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "NFLog.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_NFLog { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("NFLog", + zeek::llanalyzer::NFLog::NFLogAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::NFLog"; + config.description = "NFLog LL-Analyzer"; + return config; + } +} plugin; + +} diff --git a/src/llanalyzer/protocol/null/CMakeLists.txt b/src/llanalyzer/protocol/null/CMakeLists.txt new file mode 100644 index 0000000000..1aa1392127 --- /dev/null +++ b/src/llanalyzer/protocol/null/CMakeLists.txt @@ -0,0 +1,7 @@ +include(ZeekPlugin) + +include_directories(BEFORE $ {CMAKE_CURRENT_SOURCE_DIR} $ {CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer Null) +zeek_plugin_cc(Null.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/null/Null.cc b/src/llanalyzer/protocol/null/Null.cc new file mode 100644 index 0000000000..d9c29582a2 --- /dev/null +++ b/src/llanalyzer/protocol/null/Null.cc @@ -0,0 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Null.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::Null; + +NullAnalyzer::NullAnalyzer() + : zeek::llanalyzer::Analyzer("Null") + { + } + +std::tuple NullAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + if ( pdata + 4 >= packet->GetEndOfData() ) + { + packet->Weird("null_analyzer_failed"); + return { AnalyzerResult::Failed, 0 }; + } + + identifier_t protocol = (pdata[3] << 24) + (pdata[2] << 16) + (pdata[1] << 8) + pdata[0]; + pdata += 4; // skip link header + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/null/Null.h b/src/llanalyzer/protocol/null/Null.h new file mode 100644 index 0000000000..27294bc386 --- /dev/null +++ b/src/llanalyzer/protocol/null/Null.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::Null { + +class NullAnalyzer : public Analyzer { +public: + NullAnalyzer(); + ~NullAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new NullAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/null/Plugin.cc b/src/llanalyzer/protocol/null/Plugin.cc new file mode 100644 index 0000000000..3d1ddc4213 --- /dev/null +++ b/src/llanalyzer/protocol/null/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "plugin/Plugin.h" +#include "Null.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_Null { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("Null", + zeek::llanalyzer::Null::NullAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::Null"; + config.description = "Null LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/ppp_serial/CMakeLists.txt b/src/llanalyzer/protocol/ppp_serial/CMakeLists.txt new file mode 100644 index 0000000000..536eb1721d --- /dev/null +++ b/src/llanalyzer/protocol/ppp_serial/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer PPPSerial) +zeek_plugin_cc(PPPSerial.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/ppp_serial/PPPSerial.cc b/src/llanalyzer/protocol/ppp_serial/PPPSerial.cc new file mode 100644 index 0000000000..a250210113 --- /dev/null +++ b/src/llanalyzer/protocol/ppp_serial/PPPSerial.cc @@ -0,0 +1,22 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "PPPSerial.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::PPPSerial; + +PPPSerialAnalyzer::PPPSerialAnalyzer() + : zeek::llanalyzer::Analyzer("PPPSerial") + { + } + +std::tuple PPPSerialAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + // Extract protocol identifier + identifier_t protocol = (pdata[2] << 8) + pdata[3]; + pdata += 4; // skip link header + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/ppp_serial/PPPSerial.h b/src/llanalyzer/protocol/ppp_serial/PPPSerial.h new file mode 100644 index 0000000000..030b8801fa --- /dev/null +++ b/src/llanalyzer/protocol/ppp_serial/PPPSerial.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::PPPSerial { + +class PPPSerialAnalyzer : public Analyzer { +public: + PPPSerialAnalyzer(); + ~PPPSerialAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new PPPSerialAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/ppp_serial/Plugin.cc b/src/llanalyzer/protocol/ppp_serial/Plugin.cc new file mode 100644 index 0000000000..c7ac7c42cd --- /dev/null +++ b/src/llanalyzer/protocol/ppp_serial/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "PPPSerial.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_PPPSerial { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("PPPSerial", + zeek::llanalyzer::PPPSerial::PPPSerialAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::PPPSerial"; + config.description = "PPPSerial LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/pppoe/CMakeLists.txt b/src/llanalyzer/protocol/pppoe/CMakeLists.txt new file mode 100644 index 0000000000..9a59457cf8 --- /dev/null +++ b/src/llanalyzer/protocol/pppoe/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer PPPoE) +zeek_plugin_cc(PPPoE.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/pppoe/PPPoE.cc b/src/llanalyzer/protocol/pppoe/PPPoE.cc new file mode 100644 index 0000000000..903e5ab07b --- /dev/null +++ b/src/llanalyzer/protocol/pppoe/PPPoE.cc @@ -0,0 +1,28 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "PPPoE.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::PPPoE; + +PPPoEAnalyzer::PPPoEAnalyzer() + : zeek::llanalyzer::Analyzer("PPPoE") + { + } + +std::tuple PPPoEAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + if ( pdata + 8 >= packet->GetEndOfData() ) + { + packet->Weird("truncated_pppoe_header"); + return { AnalyzerResult::Failed, 0 }; + } + + // Extract protocol identifier + identifier_t protocol = (pdata[6] << 8u) + pdata[7]; + pdata += 8; // Skip the PPPoE session and PPP header + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/pppoe/PPPoE.h b/src/llanalyzer/protocol/pppoe/PPPoE.h new file mode 100644 index 0000000000..cbeeda160f --- /dev/null +++ b/src/llanalyzer/protocol/pppoe/PPPoE.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::PPPoE { + +class PPPoEAnalyzer : public Analyzer { +public: + PPPoEAnalyzer(); + ~PPPoEAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new PPPoEAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/pppoe/Plugin.cc b/src/llanalyzer/protocol/pppoe/Plugin.cc new file mode 100644 index 0000000000..95883f51ca --- /dev/null +++ b/src/llanalyzer/protocol/pppoe/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "PPPoE.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_PPPoE { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("PPPoE", + zeek::llanalyzer::PPPoE::PPPoEAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::PPPoE"; + config.description = "PPPoE LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/vlan/CMakeLists.txt b/src/llanalyzer/protocol/vlan/CMakeLists.txt new file mode 100644 index 0000000000..9105912d01 --- /dev/null +++ b/src/llanalyzer/protocol/vlan/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer VLAN) +zeek_plugin_cc(VLAN.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/vlan/Plugin.cc b/src/llanalyzer/protocol/vlan/Plugin.cc new file mode 100644 index 0000000000..8e4da160d7 --- /dev/null +++ b/src/llanalyzer/protocol/vlan/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "VLAN.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer_VLAN { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("VLAN", + zeek::llanalyzer::VLAN::VLANAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::VLAN"; + config.description = "VLAN LL-Analyzer"; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/vlan/VLAN.cc b/src/llanalyzer/protocol/vlan/VLAN.cc new file mode 100644 index 0000000000..e1cfb7c056 --- /dev/null +++ b/src/llanalyzer/protocol/vlan/VLAN.cc @@ -0,0 +1,31 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "VLAN.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::VLAN; + +VLANAnalyzer::VLANAnalyzer() + : zeek::llanalyzer::Analyzer("VLAN") + { + } + +std::tuple VLANAnalyzer::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + + if ( pdata + 4 >= packet->GetEndOfData() ) + { + packet->Weird("truncated_VLAN_header"); + return { AnalyzerResult::Failed, 0 }; + } + + auto& vlan_ref = packet->vlan != 0 ? packet->inner_vlan : packet->vlan; + vlan_ref = ((pdata[0] << 8u) + pdata[1]) & 0xfff; + + identifier_t protocol = ((pdata[2] << 8u) + pdata[3]); + packet->eth_type = protocol; + pdata += 4; // Skip the VLAN header + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/vlan/VLAN.h b/src/llanalyzer/protocol/vlan/VLAN.h new file mode 100644 index 0000000000..1f7532b940 --- /dev/null +++ b/src/llanalyzer/protocol/vlan/VLAN.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::VLAN { + +class VLANAnalyzer : public Analyzer { +public: + VLANAnalyzer(); + ~VLANAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new VLANAnalyzer(); + } +}; + +} diff --git a/src/llanalyzer/protocol/wrapper/CMakeLists.txt b/src/llanalyzer/protocol/wrapper/CMakeLists.txt new file mode 100644 index 0000000000..d1506bcae6 --- /dev/null +++ b/src/llanalyzer/protocol/wrapper/CMakeLists.txt @@ -0,0 +1,8 @@ + +include(ZeekPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +zeek_plugin_begin(LLAnalyzer Wrapper) +zeek_plugin_cc(Wrapper.cc Plugin.cc) +zeek_plugin_end() diff --git a/src/llanalyzer/protocol/wrapper/Plugin.cc b/src/llanalyzer/protocol/wrapper/Plugin.cc new file mode 100644 index 0000000000..36baa8a6dd --- /dev/null +++ b/src/llanalyzer/protocol/wrapper/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Wrapper.h" +#include "plugin/Plugin.h" +#include "llanalyzer/Component.h" + +namespace zeek::plugin::LLAnalyzer { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("Wrapper", + zeek::llanalyzer::Wrapper::WrapperAnalyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLAnalyzer::Wrapper"; + config.description = "A wrapper for the original zeek code."; + return config; + } + +} plugin; + +} diff --git a/src/llanalyzer/protocol/wrapper/Wrapper.cc b/src/llanalyzer/protocol/wrapper/Wrapper.cc new file mode 100644 index 0000000000..b14d34e953 --- /dev/null +++ b/src/llanalyzer/protocol/wrapper/Wrapper.cc @@ -0,0 +1,163 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Wrapper.h" +#include "NetVar.h" + +using namespace zeek::llanalyzer::Wrapper; + +WrapperAnalyzer::WrapperAnalyzer() + : zeek::llanalyzer::Analyzer("Wrapper") + { + } + +std::tuple WrapperAnalyzer::Analyze(Packet* packet) + { + // Unfortunately some packets on the link might have MPLS labels + // while others don't. That means we need to ask the link-layer if + // labels are in place. + bool have_mpls = false; + + auto pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + // Skip past Cisco FabricPath to encapsulated ethernet frame. + if ( pdata[12] == 0x89 && pdata[13] == 0x03 ) + { + auto constexpr cfplen = 16; + + if ( pdata + cfplen + 14 >= end_of_data ) + { + packet->Weird("truncated_link_header_cfp"); + return { AnalyzerResult::Failed, 0 }; + } + + pdata += cfplen; + } + + // Extract protocol identifier + identifier_t protocol = (pdata[12] << 8u) + pdata[13]; + + packet->eth_type = protocol; + packet->l2_dst = pdata; + packet->l2_src = pdata + 6; + + pdata += 14; + + bool saw_vlan = false; + + while ( protocol == 0x8100 || protocol == 0x9100 || + protocol == 0x8864 ) + { + switch ( protocol ) + { + // VLAN carried over the ethernet frame. + // 802.1q / 802.1ad + case 0x8100: + case 0x9100: + { + if ( pdata + 4 >= end_of_data ) + { + packet->Weird("truncated_link_header"); + return { AnalyzerResult::Failed, 0 }; + } + + auto& vlan_ref = saw_vlan ? packet->inner_vlan : packet->vlan; + vlan_ref = ((pdata[0] << 8u) + pdata[1]) & 0xfff; + protocol = ((pdata[2] << 8u) + pdata[3]); + pdata += 4; // Skip the vlan header + saw_vlan = true; + packet->eth_type = protocol; + } + break; + + // PPPoE carried over the ethernet frame. + case 0x8864: + { + if ( pdata + 8 >= end_of_data ) + { + packet->Weird("truncated_link_header"); + return { AnalyzerResult::Failed, 0 }; + } + + protocol = (pdata[6] << 8u) + pdata[7]; + pdata += 8; // Skip the PPPoE session and PPP header + + if ( protocol == 0x0021 ) + packet->l3_proto = L3_IPV4; + else if ( protocol == 0x0057 ) + packet->l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + packet->Weird("non_ip_packet_in_pppoe_encapsulation"); + return { AnalyzerResult::Failed, 0 }; + } + } + break; + } + } + + // Check for MPLS in VLAN. + if ( protocol == 0x8847 ) + have_mpls = true; + + // Normal path to determine Layer 3 protocol. + if ( ! have_mpls && packet->l3_proto == L3_UNKNOWN ) + { + if ( protocol == 0x800 ) + packet->l3_proto = L3_IPV4; + else if ( protocol == 0x86dd ) + packet->l3_proto = L3_IPV6; + else if ( protocol == 0x0806 || protocol == 0x8035 ) + packet->l3_proto = L3_ARP; + else + { + // Neither IPv4 nor IPv6. + packet->Weird("non_ip_packet_in_ethernet"); + return { AnalyzerResult::Failed, 0 }; + } + } + + if ( have_mpls ) + { + // Skip the MPLS label stack. + bool end_of_stack = false; + + while ( ! end_of_stack ) + { + if ( pdata + 4 >= end_of_data ) + { + packet->Weird("truncated_link_header"); + return { AnalyzerResult::Failed, 0 }; + } + + end_of_stack = *(pdata + 2u) & 0x01; + pdata += 4; + } + + // We assume that what remains is IP + if ( pdata + sizeof(struct ip) >= end_of_data ) + { + packet->Weird("no_ip_in_mpls_payload"); + return { AnalyzerResult::Failed, 0 }; + } + + const struct ip* ip = (const struct ip*)pdata; + + if ( ip->ip_v == 4 ) + packet->l3_proto = L3_IPV4; + else if ( ip->ip_v == 6 ) + packet->l3_proto = L3_IPV6; + else + { + // Neither IPv4 nor IPv6. + packet->Weird("no_ip_in_mpls_payload"); + return { AnalyzerResult::Failed, 0 }; + } + } + + // Calculate how much header we've used up. + packet->hdr_size = (pdata - packet->data); + + return { AnalyzerResult::Continue, protocol }; + } diff --git a/src/llanalyzer/protocol/wrapper/Wrapper.h b/src/llanalyzer/protocol/wrapper/Wrapper.h new file mode 100644 index 0000000000..74d257c052 --- /dev/null +++ b/src/llanalyzer/protocol/wrapper/Wrapper.h @@ -0,0 +1,23 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include + +namespace zeek::llanalyzer::Wrapper { + +class WrapperAnalyzer : public Analyzer { +public: + WrapperAnalyzer(); + ~WrapperAnalyzer() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new WrapperAnalyzer(); + } +}; + +} diff --git a/src/plugin/Component.cc b/src/plugin/Component.cc index df9b048f76..7be5d465d0 100644 --- a/src/plugin/Component.cc +++ b/src/plugin/Component.cc @@ -46,6 +46,10 @@ void Component::Describe(ODesc* d) const d->Add("Analyzer"); break; + case component::LLANALYZER: + d->Add("Low-Layer Analyzer"); + break; + case component::FILE_ANALYZER: d->Add("File Analyzer"); break; diff --git a/src/plugin/Component.h b/src/plugin/Component.h index 72237adac7..6d069e6edf 100644 --- a/src/plugin/Component.h +++ b/src/plugin/Component.h @@ -18,6 +18,7 @@ enum Type { READER, /// An input reader (not currently used). WRITER, /// A logging writer (not currenly used). ANALYZER, /// A protocol analyzer. + LLANALYZER, /// A low layer protocol analyzer. FILE_ANALYZER, /// A file analyzer. IOSOURCE, /// An I/O source, excluding packet sources. PKTSRC, /// A packet source. diff --git a/src/plugin/TaggedComponent.h b/src/plugin/TaggedComponent.h index d1a37a5794..3852ffeea6 100644 --- a/src/plugin/TaggedComponent.h +++ b/src/plugin/TaggedComponent.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace zeek::plugin { diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index aa9cb09643..a3d7418226 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -55,6 +55,7 @@ extern "C" { #include "input/readers/raw/Raw.h" #include "analyzer/Manager.h" #include "analyzer/Tag.h" +#include "llanalyzer/Manager.h" #include "plugin/Manager.h" #include "file_analysis/Manager.h" #include "zeekygen/Manager.h" @@ -92,6 +93,7 @@ zeek::ValManager* zeek::val_mgr = nullptr; zeek::ValManager*& val_mgr = zeek::val_mgr; zeek::analyzer::Manager* zeek::analyzer_mgr = nullptr; zeek::analyzer::Manager*& analyzer_mgr = zeek::analyzer_mgr; +zeek::llanalyzer::Manager* llanalyzer_mgr = nullptr; zeek::plugin::Manager* zeek::plugin_mgr = nullptr; zeek::plugin::Manager*& plugin_mgr = zeek::plugin_mgr; @@ -265,6 +267,7 @@ static void done_with_network() run_state::terminating = true; analyzer_mgr->Done(); + llanalyzer_mgr->Done(); timer_mgr->Expire(); dns_mgr->Flush(); event_mgr.Drain(); @@ -335,6 +338,7 @@ static void terminate_bro() delete zeekygen_mgr; delete analyzer_mgr; + delete llanalyzer_mgr; delete file_mgr; // broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr delete iosource_mgr; @@ -581,6 +585,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) iosource_mgr = new iosource::Manager(); event_registry = new EventRegistry(); analyzer_mgr = new analyzer::Manager(); + llanalyzer_mgr = new llanalyzer::Manager(); log_mgr = new logging::Manager(); input_mgr = new input::Manager(); file_mgr = new file_analysis::Manager(); @@ -689,6 +694,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) } analyzer_mgr->InitPostScript(); + llanalyzer_mgr->InitPostScript(); file_mgr->InitPostScript(); dns_mgr->InitPostScript(); @@ -889,6 +895,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) broker_mgr->ZeekInitDone(); reporter->ZeekInitDone(); analyzer_mgr->DumpDebug(); + llanalyzer_mgr->DumpDebug(); run_state::detail::have_pending_timers = ! run_state::reading_traces && timer_mgr->Size() > 0; diff --git a/testing/btest/Baseline/core.truncation/output b/testing/btest/Baseline/core.truncation/output index 8ef1ff8e9d..0bd1083165 100644 --- a/testing/btest/Baseline/core.truncation/output +++ b/testing/btest/Baseline/core.truncation/output @@ -3,78 +3,78 @@ #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-03 +#open 2020-07-02-14-29-19 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334160095.895421 - - - - - truncated_IP - F zeek -#close 2019-06-07-02-20-03 +#close 2020-07-02-14-29-19 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-03 +#open 2020-07-02-14-29-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334156241.519125 - - - - - truncated_IP - F zeek -#close 2019-06-07-02-20-03 +#close 2020-07-02-14-29-20 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-04 +#open 2020-07-02-14-29-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334094648.590126 - - - - - truncated_IP - F zeek -#close 2019-06-07-02-20-04 +#close 2020-07-02-14-29-20 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-05 +#open 2020-07-02-14-29-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1338328954.078361 - - - - - internally_truncated_header - F zeek -#close 2019-06-07-02-20-05 +#close 2020-07-02-14-29-21 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-05 +#open 2020-07-02-14-29-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -0.000000 - - - - - truncated_link_header - F zeek -#close 2019-06-07-02-20-05 +0.000000 - - - - - truncated_ethernet_frame - F zeek +#close 2020-07-02-14-29-21 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-06 +#open 2020-07-02-14-29-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1508360735.834163 - 163.253.48.183 0 192.150.187.43 0 invalid_IP_header_size - F zeek -#close 2019-06-07-02-20-06 +#close 2020-07-02-14-29-21 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-06 +#open 2020-07-02-14-29-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1508360735.834163 - 163.253.48.183 0 192.150.187.43 0 internally_truncated_header - F zeek -#close 2019-06-07-02-20-06 +#close 2020-07-02-14-29-22 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-02-20-07 +#open 2020-07-02-14-29-22 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1500557630.000000 - 0.255.0.255 0 15.254.2.1 0 invalid_IP_header_size_in_tunnel - F zeek -#close 2019-06-07-02-20-07 +#close 2020-07-02-14-29-22 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 382bb30cb2..ada222d35d 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 @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2019-10-15-01-48-24 +#open 2020-06-24-22-11-31 #fields name #types string scripts/base/init-bare.zeek @@ -19,6 +19,29 @@ scripts/base/init-bare.zeek build/scripts/base/bif/plugins/Zeek_SNMP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_KRB.types.bif.zeek build/scripts/base/bif/event.bif.zeek + scripts/base/llprotocols/__load__.zeek + scripts/base/llprotocols/default/__load__.zeek + scripts/base/llprotocols/default/main.zeek + scripts/base/llprotocols/ethernet/__load__.zeek + scripts/base/llprotocols/ethernet/main.zeek + scripts/base/llprotocols/fddi/__load__.zeek + scripts/base/llprotocols/fddi/main.zeek + scripts/base/llprotocols/ieee802_11/__load__.zeek + scripts/base/llprotocols/ieee802_11/main.zeek + scripts/base/llprotocols/ieee802_11_radio/__load__.zeek + scripts/base/llprotocols/ieee802_11_radio/main.zeek + scripts/base/llprotocols/linux_sll/__load__.zeek + scripts/base/llprotocols/linux_sll/main.zeek + scripts/base/llprotocols/nflog/__load__.zeek + scripts/base/llprotocols/nflog/main.zeek + scripts/base/llprotocols/null/__load__.zeek + scripts/base/llprotocols/null/main.zeek + scripts/base/llprotocols/ppp_serial/__load__.zeek + scripts/base/llprotocols/ppp_serial/main.zeek + scripts/base/llprotocols/pppoe/__load__.zeek + scripts/base/llprotocols/pppoe/main.zeek + scripts/base/llprotocols/vlan/__load__.zeek + scripts/base/llprotocols/vlan/main.zeek scripts/base/init-frameworks-and-bifs.zeek scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/main.zeek @@ -187,4 +210,4 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_SQLiteWriter.sqlite.bif.zeek scripts/policy/misc/loaded-scripts.zeek scripts/base/utils/paths.zeek -#close 2019-10-15-01-48-24 +#close 2020-06-24-22-11-31 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 0f83430933..a67b3644ff 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 @@ -19,6 +19,29 @@ scripts/base/init-bare.zeek build/scripts/base/bif/plugins/Zeek_SNMP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_KRB.types.bif.zeek build/scripts/base/bif/event.bif.zeek + scripts/base/llprotocols/__load__.zeek + scripts/base/llprotocols/default/__load__.zeek + scripts/base/llprotocols/default/main.zeek + scripts/base/llprotocols/ethernet/__load__.zeek + scripts/base/llprotocols/ethernet/main.zeek + scripts/base/llprotocols/fddi/__load__.zeek + scripts/base/llprotocols/fddi/main.zeek + scripts/base/llprotocols/ieee802_11/__load__.zeek + scripts/base/llprotocols/ieee802_11/main.zeek + scripts/base/llprotocols/ieee802_11_radio/__load__.zeek + scripts/base/llprotocols/ieee802_11_radio/main.zeek + scripts/base/llprotocols/linux_sll/__load__.zeek + scripts/base/llprotocols/linux_sll/main.zeek + scripts/base/llprotocols/nflog/__load__.zeek + scripts/base/llprotocols/nflog/main.zeek + scripts/base/llprotocols/null/__load__.zeek + scripts/base/llprotocols/null/main.zeek + scripts/base/llprotocols/ppp_serial/__load__.zeek + scripts/base/llprotocols/ppp_serial/main.zeek + scripts/base/llprotocols/pppoe/__load__.zeek + scripts/base/llprotocols/pppoe/main.zeek + scripts/base/llprotocols/vlan/__load__.zeek + scripts/base/llprotocols/vlan/main.zeek scripts/base/init-frameworks-and-bifs.zeek scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/main.zeek diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index e75cba3f3c..d125d897ec 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -283,7 +283,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1600793171.441844, 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)) -> @@ -464,7 +464,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1600793171.441844, 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, , ()) -> @@ -827,6 +827,7 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/control) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/data.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/dce-rpc) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/default) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/dhcp) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/dir.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/directions-and-hosts.zeek) -> -1 @@ -834,9 +835,11 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/dns) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/dpd) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/email.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/ethernet) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/event.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/exec.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/extract) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/fddi) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/file_analysis.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/files) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/files.zeek) -> -1 @@ -847,6 +850,8 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/hash) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/hash_hrw.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/http) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11_radio) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/imap) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/init-default.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/init-frameworks-and-bifs.zeek) -> -1 @@ -855,6 +860,8 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/intel) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/irc) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/krb) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/linux_sll) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/llprotocols) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/logging) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/logging.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/main.zeek) -> -1 @@ -863,9 +870,11 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/mqtt) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/mysql) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/netcontrol) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/nflog) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/notice) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ntlm) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ntp) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/null) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/numbers.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/openflow) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/option.bif.zeek) -> -1 @@ -875,6 +884,8 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/pe) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/plugins) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/pop3) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/ppp_serial) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/pppoe) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/queue.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/radius) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/rdp) -> -1 @@ -907,6 +918,7 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/urls.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/utils.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/version.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/vlan) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/weird.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/x509) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/xmpp) -> -1 @@ -1213,7 +1225,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1600793171.441844, 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)) @@ -1394,7 +1406,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1600793171.441844, 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, , ()) @@ -1757,6 +1769,7 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/control) 0.000000 MetaHookPre LoadFile(0, base<...>/data.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/dce-rpc) +0.000000 MetaHookPre LoadFile(0, base<...>/default) 0.000000 MetaHookPre LoadFile(0, base<...>/dhcp) 0.000000 MetaHookPre LoadFile(0, base<...>/dir.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/directions-and-hosts.zeek) @@ -1764,9 +1777,11 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/dns) 0.000000 MetaHookPre LoadFile(0, base<...>/dpd) 0.000000 MetaHookPre LoadFile(0, base<...>/email.zeek) +0.000000 MetaHookPre LoadFile(0, base<...>/ethernet) 0.000000 MetaHookPre LoadFile(0, base<...>/event.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/exec.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/extract) +0.000000 MetaHookPre LoadFile(0, base<...>/fddi) 0.000000 MetaHookPre LoadFile(0, base<...>/file_analysis.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/files) 0.000000 MetaHookPre LoadFile(0, base<...>/files.zeek) @@ -1777,6 +1792,8 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/hash) 0.000000 MetaHookPre LoadFile(0, base<...>/hash_hrw.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/http) +0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11) +0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11_radio) 0.000000 MetaHookPre LoadFile(0, base<...>/imap) 0.000000 MetaHookPre LoadFile(0, base<...>/init-default.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/init-frameworks-and-bifs.zeek) @@ -1785,6 +1802,8 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/intel) 0.000000 MetaHookPre LoadFile(0, base<...>/irc) 0.000000 MetaHookPre LoadFile(0, base<...>/krb) +0.000000 MetaHookPre LoadFile(0, base<...>/linux_sll) +0.000000 MetaHookPre LoadFile(0, base<...>/llprotocols) 0.000000 MetaHookPre LoadFile(0, base<...>/logging) 0.000000 MetaHookPre LoadFile(0, base<...>/logging.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/main.zeek) @@ -1793,9 +1812,11 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/mqtt) 0.000000 MetaHookPre LoadFile(0, base<...>/mysql) 0.000000 MetaHookPre LoadFile(0, base<...>/netcontrol) +0.000000 MetaHookPre LoadFile(0, base<...>/nflog) 0.000000 MetaHookPre LoadFile(0, base<...>/notice) 0.000000 MetaHookPre LoadFile(0, base<...>/ntlm) 0.000000 MetaHookPre LoadFile(0, base<...>/ntp) +0.000000 MetaHookPre LoadFile(0, base<...>/null) 0.000000 MetaHookPre LoadFile(0, base<...>/numbers.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/openflow) 0.000000 MetaHookPre LoadFile(0, base<...>/option.bif.zeek) @@ -1805,6 +1826,8 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/pe) 0.000000 MetaHookPre LoadFile(0, base<...>/plugins) 0.000000 MetaHookPre LoadFile(0, base<...>/pop3) +0.000000 MetaHookPre LoadFile(0, base<...>/ppp_serial) +0.000000 MetaHookPre LoadFile(0, base<...>/pppoe) 0.000000 MetaHookPre LoadFile(0, base<...>/queue.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/radius) 0.000000 MetaHookPre LoadFile(0, base<...>/rdp) @@ -1837,6 +1860,7 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/urls.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/utils.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/version.zeek) +0.000000 MetaHookPre LoadFile(0, base<...>/vlan) 0.000000 MetaHookPre LoadFile(0, base<...>/weird.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/x509) 0.000000 MetaHookPre LoadFile(0, base<...>/xmpp) @@ -2142,7 +2166,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1600793171.441844, 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) @@ -2323,7 +2347,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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1600793171.441844, 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() @@ -2698,6 +2722,7 @@ 0.000000 | HookLoadFile base<...>/control 0.000000 | HookLoadFile base<...>/data.bif.zeek 0.000000 | HookLoadFile base<...>/dce-rpc +0.000000 | HookLoadFile base<...>/default 0.000000 | HookLoadFile base<...>/dhcp 0.000000 | HookLoadFile base<...>/dir.zeek 0.000000 | HookLoadFile base<...>/directions-and-hosts.zeek @@ -2705,9 +2730,11 @@ 0.000000 | HookLoadFile base<...>/dns 0.000000 | HookLoadFile base<...>/dpd 0.000000 | HookLoadFile base<...>/email.zeek +0.000000 | HookLoadFile base<...>/ethernet 0.000000 | HookLoadFile base<...>/event.bif.zeek 0.000000 | HookLoadFile base<...>/exec.zeek 0.000000 | HookLoadFile base<...>/extract +0.000000 | HookLoadFile base<...>/fddi 0.000000 | HookLoadFile base<...>/file_analysis.bif.zeek 0.000000 | HookLoadFile base<...>/files 0.000000 | HookLoadFile base<...>/files.zeek @@ -2718,6 +2745,8 @@ 0.000000 | HookLoadFile base<...>/hash 0.000000 | HookLoadFile base<...>/hash_hrw.zeek 0.000000 | HookLoadFile base<...>/http +0.000000 | HookLoadFile base<...>/ieee802_11 +0.000000 | HookLoadFile base<...>/ieee802_11_radio 0.000000 | HookLoadFile base<...>/imap 0.000000 | HookLoadFile base<...>/init-default.zeek 0.000000 | HookLoadFile base<...>/init-frameworks-and-bifs.zeek @@ -2726,6 +2755,8 @@ 0.000000 | HookLoadFile base<...>/intel 0.000000 | HookLoadFile base<...>/irc 0.000000 | HookLoadFile base<...>/krb +0.000000 | HookLoadFile base<...>/linux_sll +0.000000 | HookLoadFile base<...>/llprotocols 0.000000 | HookLoadFile base<...>/logging 0.000000 | HookLoadFile base<...>/logging.bif.zeek 0.000000 | HookLoadFile base<...>/main.zeek @@ -2734,9 +2765,11 @@ 0.000000 | HookLoadFile base<...>/mqtt 0.000000 | HookLoadFile base<...>/mysql 0.000000 | HookLoadFile base<...>/netcontrol +0.000000 | HookLoadFile base<...>/nflog 0.000000 | HookLoadFile base<...>/notice 0.000000 | HookLoadFile base<...>/ntlm 0.000000 | HookLoadFile base<...>/ntp +0.000000 | HookLoadFile base<...>/null 0.000000 | HookLoadFile base<...>/numbers.zeek 0.000000 | HookLoadFile base<...>/openflow 0.000000 | HookLoadFile base<...>/option.bif.zeek @@ -2746,6 +2779,8 @@ 0.000000 | HookLoadFile base<...>/pe 0.000000 | HookLoadFile base<...>/plugins 0.000000 | HookLoadFile base<...>/pop3 +0.000000 | HookLoadFile base<...>/ppp_serial +0.000000 | HookLoadFile base<...>/pppoe 0.000000 | HookLoadFile base<...>/queue.zeek 0.000000 | HookLoadFile base<...>/radius 0.000000 | HookLoadFile base<...>/rdp @@ -2778,12 +2813,13 @@ 0.000000 | HookLoadFile base<...>/urls.zeek 0.000000 | HookLoadFile base<...>/utils.zeek 0.000000 | HookLoadFile base<...>/version.zeek +0.000000 | HookLoadFile base<...>/vlan 0.000000 | HookLoadFile base<...>/weird.zeek 0.000000 | HookLoadFile base<...>/x509 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=1599794475.539113, node=zeek, filter=ip or not ip, init=T, success=T] +0.000000 | HookLogWrite packet_filter [ts=1600793171.441844, 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/Baseline/plugins.ll-protocol/output b/testing/btest/Baseline/plugins.ll-protocol/output new file mode 100644 index 0000000000..578a37577d --- /dev/null +++ b/testing/btest/Baseline/plugins.ll-protocol/output @@ -0,0 +1,9 @@ +LLDemo::Bar - A Bar LL-test-analyzer. (dynamic, version 1.0.0) + [Low-Layer Analyzer] Bar (LLANALYZER_BAR, enabled) + [Event] bar_message + +=== +bar_message (DSAP = 42, SSAP = 42, Control = 3) +bar_message (DSAP = 42, SSAP = 42, Control = 3) +bar_message (DSAP = 42, SSAP = 42, Control = 3) +bar_message (DSAP = 42, SSAP = 42, Control = 3) diff --git a/testing/btest/Baseline/scripts.base.protocols.arp.linuxsll/.stdout b/testing/btest/Baseline/scripts.base.protocols.arp.linuxsll/.stdout new file mode 100644 index 0000000000..971bacd567 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.arp.linuxsll/.stdout @@ -0,0 +1,12 @@ +cc:2d:e0:26:19:99, 00:00:00:00:00:00, 192.168.22.1, cc:2d:e0:26:19:99, 192.168.22.160, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:3f:0d, 00:00:00:00:00:00, 192.168.22.81, 00:50:56:8b:3f:0d, 192.168.22.81, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:3f:0d, 00:00:00:00:00:00, 192.168.22.81, 00:50:56:8b:3f:0d, 192.168.22.81, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 +00:50:56:8b:cf:fa, 00:00:00:00:00:00, 10.1.10.100, 00:50:56:8b:cf:fa, 10.1.10.1, 00:00:00:00:00:00 diff --git a/testing/btest/Traces/http/get_nosyn.trace b/testing/btest/Traces/http/get_nosyn.trace new file mode 100644 index 0000000000..9a1d08ce69 Binary files /dev/null and b/testing/btest/Traces/http/get_nosyn.trace differ diff --git a/testing/btest/Traces/linuxsll-arp.pcap b/testing/btest/Traces/linuxsll-arp.pcap new file mode 100644 index 0000000000..7898d55a40 Binary files /dev/null and b/testing/btest/Traces/linuxsll-arp.pcap differ diff --git a/testing/btest/plugins/ll-protocol-plugin/.btest-ignore b/testing/btest/plugins/ll-protocol-plugin/.btest-ignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/plugins/ll-protocol-plugin/CMakeLists.txt b/testing/btest/plugins/ll-protocol-plugin/CMakeLists.txt new file mode 100644 index 0000000000..7f11aa11e7 --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/CMakeLists.txt @@ -0,0 +1,18 @@ + +project(Zeek-LL-Plugin-Demo-Bar) + +cmake_minimum_required(VERSION 2.6.3) + +if ( NOT ZEEK_DIST ) + message(FATAL_ERROR "ZEEK_DIST not set") +endif () + +set(CMAKE_MODULE_PATH ${ZEEK_DIST}/cmake) + +include(ZeekPlugin) + +zeek_plugin_begin(LLDemo Bar) +zeek_plugin_cc(src/Plugin.cc) +zeek_plugin_cc(src/Bar.cc) +zeek_plugin_bif(src/events.bif) +zeek_plugin_end() diff --git a/testing/btest/plugins/ll-protocol-plugin/scripts/LLDemo/Bar/base/main.zeek b/testing/btest/plugins/ll-protocol-plugin/scripts/LLDemo/Bar/base/main.zeek new file mode 100644 index 0000000000..031bd4f058 --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/scripts/LLDemo/Bar/base/main.zeek @@ -0,0 +1,5 @@ +module LL_BAR; + +redef LLAnalyzer::config_map += { + LLAnalyzer::ConfigEntry($parent=LLAnalyzer::LLANALYZER_ETHERNET, $identifier=1501, $analyzer=LLAnalyzer::LLANALYZER_BAR), +}; diff --git a/testing/btest/plugins/ll-protocol-plugin/scripts/__load__.zeek b/testing/btest/plugins/ll-protocol-plugin/scripts/__load__.zeek new file mode 100644 index 0000000000..697ab585a1 --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/scripts/__load__.zeek @@ -0,0 +1 @@ +@load LLDemo/Bar/base/main diff --git a/testing/btest/plugins/ll-protocol-plugin/src/Bar.cc b/testing/btest/plugins/ll-protocol-plugin/src/Bar.cc new file mode 100644 index 0000000000..93c8b87dc0 --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/src/Bar.cc @@ -0,0 +1,35 @@ +#include "Bar.h" +#include "Event.h" +#include "Val.h" +#include "events.bif.h" + +using namespace zeek::llanalyzer::LLDemo; + +Bar::Bar() + : zeek::llanalyzer::Analyzer("Bar") + { + } + +std::tuple Bar::Analyze(Packet* packet) + { + auto& pdata = packet->cur_pos; + auto end_of_data = packet->GetEndOfData(); + + // Rudimentary parsing of 802.2 LLC + if ( pdata + 17 >= end_of_data ) + { + packet->Weird("truncated_llc_header"); + return { AnalyzerResult::Failed, 0 }; + } + + auto dsap = pdata[14]; + auto ssap = pdata[15]; + auto control = pdata[16]; + + mgr.Enqueue(bar_message, + val_mgr->Count(dsap), + val_mgr->Count(ssap), + val_mgr->Count(control)); + + return std::make_tuple(AnalyzerResult::Terminate, 0); + } diff --git a/testing/btest/plugins/ll-protocol-plugin/src/Bar.h b/testing/btest/plugins/ll-protocol-plugin/src/Bar.h new file mode 100644 index 0000000000..24f0a0856c --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/src/Bar.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace zeek::llanalyzer::LLDemo { + +class Bar : public Analyzer { +public: + Bar(); + ~Bar() override = default; + + std::tuple Analyze(Packet* packet) override; + + static Analyzer* Instantiate() + { + return new Bar(); + } +}; + +} + diff --git a/testing/btest/plugins/ll-protocol-plugin/src/Plugin.cc b/testing/btest/plugins/ll-protocol-plugin/src/Plugin.cc new file mode 100644 index 0000000000..4e0b7bc451 --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/src/Plugin.cc @@ -0,0 +1,27 @@ + +#include "Plugin.h" +#include "llanalyzer/Component.h" + +#include "Bar.h" + +namespace zeek::plugin::LLDemo_Bar { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() + { + AddComponent(new zeek::llanalyzer::Component("Bar", + zeek::llanalyzer::LLDemo::Bar::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "LLDemo::Bar"; + config.description = "A Bar LL-test-analyzer."; + config.version.major = 1; + config.version.minor = 0; + config.version.patch = 0; + return config; + } + +} plugin; + +} diff --git a/testing/btest/plugins/ll-protocol-plugin/src/events.bif b/testing/btest/plugins/ll-protocol-plugin/src/events.bif new file mode 100644 index 0000000000..0b5c6888ab --- /dev/null +++ b/testing/btest/plugins/ll-protocol-plugin/src/events.bif @@ -0,0 +1,2 @@ + +event bar_message%(dsap: count, ssap: count, control: count%); diff --git a/testing/btest/plugins/ll-protocol.zeek b/testing/btest/plugins/ll-protocol.zeek new file mode 100644 index 0000000000..125daba230 --- /dev/null +++ b/testing/btest/plugins/ll-protocol.zeek @@ -0,0 +1,14 @@ +# @TEST-EXEC: ${DIST}/auxil/zeek-aux/plugin-support/init-plugin -u . LLDemo Bar +# @TEST-EXEC: cp -r %DIR/ll-protocol-plugin/* . +# @TEST-EXEC: ./configure --zeek-dist=${DIST} && make +# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -NN LLDemo::Bar >>output +# @TEST-EXEC: echo === >>output +# @TEST-EXEC: ZEEK_PLUGIN_PATH=`pwd` zeek -r $TRACES/raw_packets.trace %INPUT >>output +# @TEST-EXEC: TEST_DIFF_CANONIFIER= btest-diff output + +event bar_message(dsap: count, ssap: count, control: count) + { + print fmt("bar_message (DSAP = %x, SSAP = %x, Control = %x)", + dsap, ssap, control); + } + diff --git a/testing/btest/plugins/pktdumper-plugin/src/Foo.cc b/testing/btest/plugins/pktdumper-plugin/src/Foo.cc index 75dc5d990b..9f0ad925dd 100644 --- a/testing/btest/plugins/pktdumper-plugin/src/Foo.cc +++ b/testing/btest/plugins/pktdumper-plugin/src/Foo.cc @@ -20,7 +20,6 @@ Foo::~Foo() void Foo::Open() { props.open_time = zeek::run_state::network_time; - props.hdr_size = 0; Opened(props); } diff --git a/testing/btest/scripts/base/protocols/arp/linuxsll.test b/testing/btest/scripts/base/protocols/arp/linuxsll.test new file mode 100644 index 0000000000..01922961cb --- /dev/null +++ b/testing/btest/scripts/base/protocols/arp/linuxsll.test @@ -0,0 +1,12 @@ +# @TEST-EXEC: zeek -r $TRACES/linuxsll-arp.pcap %INPUT +# @TEST-EXEC: btest-diff .stdout + +event arp_request(mac_src: string, mac_dst: string, SPA: addr, SHA: string, TPA: addr, THA: string) + { + print mac_src, mac_dst, SPA, SHA, TPA, THA; + } + +event arp_reply(mac_src: string, mac_dst: string, SPA: addr, SHA: string, TPA: addr, THA: string) + { + print mac_src, mac_dst, SPA, SHA, TPA, THA; + }