From 1cf251d1ca40474a9462e8d541792a83de3abfdc Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 23 Sep 2020 16:17:06 -0700 Subject: [PATCH] Move IP and IP tunnel code from Sessions into packet analyzers --- scripts/base/packet-protocols/__load__.zeek | 2 + .../base/packet-protocols/ethernet/main.zeek | 4 +- .../base/packet-protocols/gre/__load__.zeek | 1 + scripts/base/packet-protocols/gre/main.zeek | 5 + .../packet-protocols/ieee802_11/main.zeek | 4 +- scripts/base/packet-protocols/ip/main.zeek | 5 +- .../packet-protocols/iptunnel/__load__.zeek | 1 + .../base/packet-protocols/iptunnel/main.zeek | 5 + .../base/packet-protocols/linux_sll/main.zeek | 4 +- scripts/base/packet-protocols/nflog/main.zeek | 4 +- scripts/base/packet-protocols/null/main.zeek | 8 +- .../packet-protocols/ppp_serial/main.zeek | 4 +- scripts/base/packet-protocols/pppoe/main.zeek | 4 +- scripts/base/packet-protocols/vlan/main.zeek | 4 +- src/Conn.h | 4 +- src/Frag.cc | 56 +- src/Frag.h | 38 +- src/IP.h | 5 + src/RunState.cc | 23 +- src/RunState.h | 2 +- src/Sessions.cc | 659 ++---------------- src/Sessions.h | 115 +-- src/analyzer/protocol/ayiya/AYIYA.cc | 7 +- src/analyzer/protocol/gtpv1/GTPv1.cc | 6 +- .../protocol/gtpv1/gtpv1-analyzer.pac | 1 - src/analyzer/protocol/teredo/Teredo.cc | 4 +- src/analyzer/protocol/vxlan/VXLAN.cc | 37 +- src/iosource/Packet.cc | 5 +- src/iosource/Packet.h | 21 +- src/iosource/PktSrc.cc | 17 +- src/packet_analysis/Analyzer.h | 8 +- src/packet_analysis/Manager.cc | 44 ++ src/packet_analysis/Manager.h | 19 +- src/packet_analysis/protocol/CMakeLists.txt | 4 +- .../protocol/{ipv4 => gre}/CMakeLists.txt | 4 +- src/packet_analysis/protocol/gre/GRE.cc | 218 ++++++ .../protocol/{ipv4/IPv4.h => gre/GRE.h} | 10 +- .../protocol/{ipv6 => gre}/Plugin.cc | 13 +- src/packet_analysis/protocol/ip/IP.cc | 263 ++++++- src/packet_analysis/protocol/ip/IP.h | 18 +- .../{ipv6 => iptunnel}/CMakeLists.txt | 4 +- .../protocol/iptunnel/IPTunnel.cc | 238 +++++++ .../protocol/iptunnel/IPTunnel.h | 98 +++ .../protocol/{ipv4 => iptunnel}/Plugin.cc | 12 +- src/packet_analysis/protocol/ipv4/IPv4.cc | 20 - src/packet_analysis/protocol/ipv6/IPv6.cc | 20 - src/packet_analysis/protocol/ipv6/IPv6.h | 23 - src/zeek-setup.cc | 6 + .../core.disable-mobile-ipv6/weird.log | 6 +- .../Baseline/core.ip-broken-header/weird.log | 8 +- .../canonified_loaded_scripts.log | 8 +- .../canonified_loaded_scripts.log | 8 +- testing/btest/Baseline/plugins.hooks/output | 26 +- 53 files changed, 1226 insertions(+), 907 deletions(-) create mode 100644 scripts/base/packet-protocols/gre/__load__.zeek create mode 100644 scripts/base/packet-protocols/gre/main.zeek create mode 100644 scripts/base/packet-protocols/iptunnel/__load__.zeek create mode 100644 scripts/base/packet-protocols/iptunnel/main.zeek rename src/packet_analysis/protocol/{ipv4 => gre}/CMakeLists.txt (63%) create mode 100644 src/packet_analysis/protocol/gre/GRE.cc rename src/packet_analysis/protocol/{ipv4/IPv4.h => gre/GRE.h} (65%) rename src/packet_analysis/protocol/{ipv6 => gre}/Plugin.cc (54%) rename src/packet_analysis/protocol/{ipv6 => iptunnel}/CMakeLists.txt (60%) create mode 100644 src/packet_analysis/protocol/iptunnel/IPTunnel.cc create mode 100644 src/packet_analysis/protocol/iptunnel/IPTunnel.h rename src/packet_analysis/protocol/{ipv4 => iptunnel}/Plugin.cc (51%) delete mode 100644 src/packet_analysis/protocol/ipv4/IPv4.cc delete mode 100644 src/packet_analysis/protocol/ipv6/IPv6.cc delete mode 100644 src/packet_analysis/protocol/ipv6/IPv6.h diff --git a/scripts/base/packet-protocols/__load__.zeek b/scripts/base/packet-protocols/__load__.zeek index 572b1a0c0c..d4cbeaf893 100644 --- a/scripts/base/packet-protocols/__load__.zeek +++ b/scripts/base/packet-protocols/__load__.zeek @@ -12,3 +12,5 @@ @load base/packet-protocols/pppoe @load base/packet-protocols/vlan @load base/packet-protocols/mpls +@load base/packet-protocols/gre +@load base/packet-protocols/iptunnel diff --git a/scripts/base/packet-protocols/ethernet/main.zeek b/scripts/base/packet-protocols/ethernet/main.zeek index 6f1c31df90..0094003e8f 100644 --- a/scripts/base/packet-protocols/ethernet/main.zeek +++ b/scripts/base/packet-protocols/ethernet/main.zeek @@ -17,8 +17,8 @@ export { redef dispatch_map += { [0x8847] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS), - [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), + [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), [0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), [0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), [0x8100] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN), diff --git a/scripts/base/packet-protocols/gre/__load__.zeek b/scripts/base/packet-protocols/gre/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/packet-protocols/gre/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/packet-protocols/gre/main.zeek b/scripts/base/packet-protocols/gre/main.zeek new file mode 100644 index 0000000000..9039ff4dfb --- /dev/null +++ b/scripts/base/packet-protocols/gre/main.zeek @@ -0,0 +1,5 @@ +module PacketAnalyzer::GRE; + +export { + const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IPTUNNEL &redef; +} diff --git a/scripts/base/packet-protocols/ieee802_11/main.zeek b/scripts/base/packet-protocols/ieee802_11/main.zeek index f46f89e377..ee12c03714 100644 --- a/scripts/base/packet-protocols/ieee802_11/main.zeek +++ b/scripts/base/packet-protocols/ieee802_11/main.zeek @@ -6,8 +6,8 @@ export { } redef dispatch_map += { - [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), + [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), [0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), [0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP) }; diff --git a/scripts/base/packet-protocols/ip/main.zeek b/scripts/base/packet-protocols/ip/main.zeek index feb5fde73b..a34ef987bd 100644 --- a/scripts/base/packet-protocols/ip/main.zeek +++ b/scripts/base/packet-protocols/ip/main.zeek @@ -6,6 +6,7 @@ export { } redef dispatch_map += { - [4] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [6] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6) + [4] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPTUNNEL), # IPv4 tunnel + [41] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPTUNNEL), # IPv6 tunnel + [47] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_GRE) }; diff --git a/scripts/base/packet-protocols/iptunnel/__load__.zeek b/scripts/base/packet-protocols/iptunnel/__load__.zeek new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/packet-protocols/iptunnel/__load__.zeek @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/packet-protocols/iptunnel/main.zeek b/scripts/base/packet-protocols/iptunnel/main.zeek new file mode 100644 index 0000000000..d219c92522 --- /dev/null +++ b/scripts/base/packet-protocols/iptunnel/main.zeek @@ -0,0 +1,5 @@ +module PacketAnalyzer::IPTUNNEL; + +export { + const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef; +} diff --git a/scripts/base/packet-protocols/linux_sll/main.zeek b/scripts/base/packet-protocols/linux_sll/main.zeek index 995c972ae6..2c4f5334fb 100644 --- a/scripts/base/packet-protocols/linux_sll/main.zeek +++ b/scripts/base/packet-protocols/linux_sll/main.zeek @@ -6,8 +6,8 @@ export { } redef dispatch_map += { - [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), + [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), [0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), # RARP [0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP) diff --git a/scripts/base/packet-protocols/nflog/main.zeek b/scripts/base/packet-protocols/nflog/main.zeek index cecc0d466b..92c399d60d 100644 --- a/scripts/base/packet-protocols/nflog/main.zeek +++ b/scripts/base/packet-protocols/nflog/main.zeek @@ -9,6 +9,6 @@ const AF_INET : count = 2; const AF_INET6 : count = 10; redef dispatch_map += { - [AF_INET] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [AF_INET6] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6) + [AF_INET] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [AF_INET6] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP) }; diff --git a/scripts/base/packet-protocols/null/main.zeek b/scripts/base/packet-protocols/null/main.zeek index 650ae97448..1e088f8fb2 100644 --- a/scripts/base/packet-protocols/null/main.zeek +++ b/scripts/base/packet-protocols/null/main.zeek @@ -17,8 +17,8 @@ redef PacketAnalyzer::ROOT::dispatch_map += { ## 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. redef dispatch_map += { - [2] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [24] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), - [28] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), - [30] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6) + [2] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [24] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [28] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [30] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP) }; diff --git a/scripts/base/packet-protocols/ppp_serial/main.zeek b/scripts/base/packet-protocols/ppp_serial/main.zeek index 4c2ba042c0..86a9e7f971 100644 --- a/scripts/base/packet-protocols/ppp_serial/main.zeek +++ b/scripts/base/packet-protocols/ppp_serial/main.zeek @@ -13,6 +13,6 @@ redef PacketAnalyzer::ROOT::dispatch_map += { redef dispatch_map += { [0x0281] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS), - [0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6) + [0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP) }; diff --git a/scripts/base/packet-protocols/pppoe/main.zeek b/scripts/base/packet-protocols/pppoe/main.zeek index f8e8f76d44..ffc372d120 100644 --- a/scripts/base/packet-protocols/pppoe/main.zeek +++ b/scripts/base/packet-protocols/pppoe/main.zeek @@ -6,6 +6,6 @@ export { } redef dispatch_map += { - [0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6) + [0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP) }; diff --git a/scripts/base/packet-protocols/vlan/main.zeek b/scripts/base/packet-protocols/vlan/main.zeek index 7f564cfa0d..9de5272913 100644 --- a/scripts/base/packet-protocols/vlan/main.zeek +++ b/scripts/base/packet-protocols/vlan/main.zeek @@ -7,8 +7,8 @@ export { redef dispatch_map += { [0x8847] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS), - [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4), - [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6), + [0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), + [0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IP), [0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), [0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP), [0x8100] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN), diff --git a/src/Conn.h b/src/Conn.h index 5b33b5eeed..53019fd236 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -306,7 +306,7 @@ public: UID GetUID() const { return uid; } - const EncapsulationStack* GetEncapsulation() const + EncapsulationStack* GetEncapsulation() const { return encapsulation; } void CheckFlowLabel(bool is_orig, uint32_t flow_label); @@ -351,7 +351,7 @@ protected: double start_time, last_time; double inactivity_timeout; RecordValPtr conn_val; - const EncapsulationStack* encapsulation; // tunnels + EncapsulationStack* encapsulation; // tunnels int suppress_event; // suppress certain events to once per conn. unsigned int installed_status_timer:1; diff --git a/src/Frag.cc b/src/Frag.cc index f8322e7317..0dc4f27196 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -297,6 +297,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */) struct ip* reassem4 = (struct ip*) pkt_start; reassem4->ip_len = htons(frag_size + proto_hdr_len); reassembled_pkt = new IP_Hdr(reassem4, true); + reassembled_pkt->reassembled = true; DeleteTimer(); } @@ -306,6 +307,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */) reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n); reassembled_pkt = new IP_Hdr(reassem6, true, n, chain); + reassembled_pkt->reassembled = true; DeleteTimer(); } @@ -323,7 +325,7 @@ void FragReassembler::Expire(double t) expire_timer->ClearReassembler(); expire_timer = nullptr; // timer manager will delete it - sessions->Remove(this); + fragment_mgr->Remove(this); } void FragReassembler::DeleteTimer() @@ -336,4 +338,56 @@ void FragReassembler::DeleteTimer() } } +FragmentManager::~FragmentManager() + { + Clear(); + } + +FragReassembler* FragmentManager::NextFragment(double t, const IP_Hdr* ip, const u_char* pkt) + { + uint32_t frag_id = ip->ID(); + FragReassemblerKey key = std::make_tuple(ip->SrcAddr(), ip->DstAddr(), frag_id); + + FragReassembler* f = nullptr; + auto it = fragments.find(key); + if ( it != fragments.end() ) + f = it->second; + + if ( ! f ) + { + f = new FragReassembler(sessions, ip, pkt, key, t); + fragments[key] = f; + if ( fragments.size() > max_fragments ) + max_fragments = fragments.size(); + return f; + } + + f->AddFragment(t, ip, pkt); + return f; + } + +void FragmentManager::Clear() + { + for ( const auto& entry : fragments ) + Unref(entry.second); + + fragments.clear(); + } + +void FragmentManager::Remove(detail::FragReassembler* f) + { + if ( ! f ) + return; + + if ( fragments.erase(f->Key()) == 0 ) + reporter->InternalWarning("fragment reassembler not in dict"); + + Unref(f); + } + +uint32_t FragmentManager::MemoryAllocation() const + { + return fragments.size() * (sizeof(FragmentMap::key_type) + sizeof(FragmentMap::value_type)); + } + } // namespace zeek::detail diff --git a/src/Frag.h b/src/Frag.h index f954b18486..1fb373f1cc 100644 --- a/src/Frag.h +++ b/src/Frag.h @@ -32,7 +32,7 @@ public: void DeleteTimer(); void ClearTimer() { expire_timer = nullptr; } - const IP_Hdr* ReassembledPkt() { return reassembled_pkt; } + IP_Hdr* ReassembledPkt() { return reassembled_pkt; } const FragReassemblerKey& Key() const { return key; } protected: @@ -67,4 +67,40 @@ protected: FragReassembler* f; }; +class FragmentManager { +public: + + FragmentManager() = default; + ~FragmentManager(); + + FragReassembler* NextFragment(double t, const IP_Hdr* ip, const u_char* pkt); + void Clear(); + void Remove(detail::FragReassembler* f); + + size_t Size() const { return fragments.size(); } + size_t MaxFragments() const { return max_fragments; } + uint32_t MemoryAllocation() const; + +private: + + using FragmentMap = std::map; + FragmentMap fragments; + size_t max_fragments = 0; +}; + +extern FragmentManager* fragment_mgr; + +class FragReassemblerTracker { +public: + FragReassemblerTracker(FragReassembler* f) + : frag_reassembler(f) + { } + + ~FragReassemblerTracker() + { fragment_mgr->Remove(frag_reassembler); } + +private: + FragReassembler* frag_reassembler; +}; + } // namespace zeek::detail diff --git a/src/IP.h b/src/IP.h index dff7f5b8b6..7ec5b5ac79 100644 --- a/src/IP.h +++ b/src/IP.h @@ -554,6 +554,11 @@ public: [[deprecated("Remove in v4.1. Use ToPktHdrVal() instead.")]] RecordVal* BuildPktHdrVal(RecordVal* pkt_hdr, int sindex) const; + /** + * Denotes whether this header is from a set of packet fragments. + */ + bool reassembled = false; + private: const struct ip* ip4 = nullptr; const struct ip6_hdr* ip6 = nullptr; diff --git a/src/RunState.cc b/src/RunState.cc index 0865d9b4fa..43ca01aee6 100644 --- a/src/RunState.cc +++ b/src/RunState.cc @@ -36,6 +36,7 @@ extern "C" { #include "iosource/PktDumper.h" #include "plugin/Manager.h" #include "broker/Manager.h" +#include "packet_analysis/Manager.h" extern "C" { extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -209,11 +210,8 @@ void expire_timers() zeek::detail::max_timer_expires - current_dispatched); } -void dispatch_packet(const Packet* pkt) +void dispatch_packet(Packet* pkt, iosource::PktSrc* pkt_src) { - if ( ! pkt->l2_valid ) - return; - double t = run_state::pseudo_realtime ? check_pseudo_time(pkt) : pkt->time; if ( ! zeek_start_network_time ) @@ -224,6 +222,12 @@ void dispatch_packet(const Packet* pkt) event_mgr.Enqueue(network_time_init, Args{}); } + current_iosrc = pkt_src; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + current_pktsrc = pkt_src; +#pragma GCC diagnostic pop + // network_time never goes back. update_network_time(zeek::detail::timer_mgr->Time() < t ? t : zeek::detail::timer_mgr->Time()); processing_start_time = t; @@ -249,7 +253,7 @@ void dispatch_packet(const Packet* pkt) } } - sessions->NextPacket(t, pkt); + packet_mgr->ProcessPacket(pkt); event_mgr.Drain(); if ( sp ) @@ -264,6 +268,12 @@ void dispatch_packet(const Packet* pkt) if ( pseudo_realtime && ! first_wallclock ) first_wallclock = util::current_time(true); + + current_iosrc = nullptr; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + current_pktsrc = nullptr; +#pragma GCC diagnostic pop } void run_loop() @@ -468,7 +478,10 @@ bool is_processing_suspended() { return _processing_suspended; } } // namespace zeek::run_state // Remove all of these in v4.1. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" zeek::iosource::PktSrc*& current_pktsrc = zeek::run_state::detail::current_pktsrc; +#pragma GCC diagnostic pop zeek::iosource::IOSource*& current_iosrc = zeek::run_state::detail::current_iosrc; zeek::iosource::PktDumper*& pkt_dumper = zeek::run_state::detail::pkt_dumper; bool& have_pending_timers = zeek::run_state::detail::have_pending_timers; diff --git a/src/RunState.h b/src/RunState.h index 1994784fbe..1928a7cd60 100644 --- a/src/RunState.h +++ b/src/RunState.h @@ -24,7 +24,7 @@ extern void get_final_stats(); extern void finish_run(int drain_events); extern void delete_run(); // Reclaim all memory, etc. extern void update_network_time(double new_network_time); -extern void dispatch_packet(const zeek::Packet* pkt); +extern void dispatch_packet(zeek::Packet* pkt, zeek::iosource::PktSrc* pkt_src); extern void expire_timers(); extern void zeek_terminate_loop(const char* reason); diff --git a/src/Sessions.cc b/src/Sessions.cc index 4a56d4a35e..21dac57bff 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -22,7 +22,6 @@ #include "analyzer/protocol/stepping-stone/SteppingStone.h" #include "analyzer/protocol/stepping-stone/events.bif.h" -#include "Discard.h" #include "RuleMatcher.h" #include "TunnelEncapsulation.h" @@ -46,29 +45,6 @@ zeek::NetSessions* zeek::sessions; zeek::NetSessions*& sessions = zeek::sessions; namespace zeek { -namespace detail { - -void IPTunnelTimer::Dispatch(double t, bool is_expire) - { - NetSessions::IPTunnelMap::const_iterator it = - sessions->ip_tunnels.find(tunnel_idx); - - if ( it == sessions->ip_tunnels.end() ) - return; - - double last_active = it->second.second; - double inactive_time = t > last_active ? t - last_active : 0; - - if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout ) - // tunnel activity timed out, delete it from map - sessions->ip_tunnels.erase(tunnel_idx); - - else if ( ! is_expire ) - // tunnel activity didn't timeout, schedule another timer - timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx)); - } - -} // namespace detail NetSessions::NetSessions() { @@ -77,33 +53,14 @@ NetSessions::NetSessions() else stp_manager = nullptr; - discarder = new detail::Discarder(); - if ( ! discarder->IsActive() ) - { - delete discarder; - discarder = nullptr; - } - packet_filter = nullptr; - num_packets_processed = 0; - static auto pkt_profile_file = id::find_val("pkt_profile_file"); - - if ( detail::pkt_profile_mode && detail::pkt_profile_freq > 0 && pkt_profile_file ) - pkt_profiler = new detail::PacketProfiler(detail::pkt_profile_mode, - detail::pkt_profile_freq, - pkt_profile_file->AsFile()); - else - pkt_profiler = nullptr; - memset(&stats, 0, sizeof(SessionStats)); } NetSessions::~NetSessions() { delete packet_filter; - delete pkt_profiler; - delete discarder; delete stp_manager; for ( const auto& entry : tcp_conns ) @@ -112,8 +69,8 @@ NetSessions::~NetSessions() Unref(entry.second); for ( const auto& entry : icmp_conns ) Unref(entry.second); - for ( const auto& entry : fragments ) - Unref(entry.second); + + detail::fragment_mgr->Clear(); } void NetSessions::Done() @@ -122,25 +79,12 @@ void NetSessions::Done() void NetSessions::NextPacket(double t, const Packet* pkt) { - detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet"); - - if ( raw_packet ) - event_mgr.Enqueue(raw_packet, pkt->ToRawPktHdrVal()); - - if ( pkt_profiler ) - pkt_profiler->ProfilePkt(t, pkt->cap_len); - - ++num_packets_processed; + EncapsulationStack* encapsulation = nullptr; + auto it = pkt->key_store.find("encap"); + if ( it != pkt->key_store.end() ) + encapsulation = std::any_cast(*it); bool dumped_packet = false; - if ( pkt->dump_packet || zeek::detail::record_all_packets ) - { - DumpPacket(pkt); - dumped_packet = true; - } - - if ( ! pkt->session_analysis ) - return; if ( pkt->hdr_size > pkt->cap_len ) { @@ -158,9 +102,26 @@ void NetSessions::NextPacket(double t, const Packet* pkt) return; } - auto ip = (const struct ip*) (pkt->data + pkt->hdr_size); - IP_Hdr ip_hdr(ip, false); - DoNextPacket(t, pkt, &ip_hdr, nullptr); + if ( ! encapsulation ) + { + const struct ip* ip = (const struct ip*) (pkt->data + pkt->hdr_size); + IP_Hdr ip_hdr(ip, false); + DoNextPacket(t, pkt, &ip_hdr, encapsulation); + } + else + { + const IP_Hdr* ip_hdr; + auto it = pkt->key_store.find("encap_inner_ip"); + if ( it != pkt->key_store.end() ) + ip_hdr = std::any_cast(*it); + else + { + IP_Hdr pkt_ip = pkt->IP(); + ip_hdr = &pkt_ip; + } + + DoNextPacket(t, pkt, ip_hdr, encapsulation); + } } else if ( pkt->l3_proto == L3_IPV6 ) @@ -171,8 +132,25 @@ void NetSessions::NextPacket(double t, const Packet* pkt) return; } - IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt->data + pkt->hdr_size), false, caplen); - DoNextPacket(t, pkt, &ip_hdr, nullptr); + if ( ! encapsulation ) + { + IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt->data + pkt->hdr_size), false, caplen); + DoNextPacket(t, pkt, &ip_hdr, encapsulation); + } + else + { + const IP_Hdr* ip_hdr = nullptr; + auto it = pkt->key_store.find("encap_inner_ip"); + if ( it != pkt->key_store.end() ) + ip_hdr = std::any_cast(*it); + else + { + IP_Hdr pkt_ip = pkt->IP(); + ip_hdr = &pkt_ip; + } + + DoNextPacket(t, pkt, ip_hdr, encapsulation); + } } else @@ -180,182 +158,18 @@ void NetSessions::NextPacket(double t, const Packet* pkt) Weird("unknown_packet_type", pkt); return; } - - // Check whether packet should be recorded based on session analysis - if ( pkt->dump_packet && ! dumped_packet ) - DumpPacket(pkt); - } - -static unsigned int gre_header_len(uint16_t flags) - { - unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type. - - if ( flags & 0x8000 ) - // Checksum/Reserved1 present. - len += 4; - - // Not considering routing presence bit since it's deprecated ... - - if ( flags & 0x2000 ) - // Key present. - len += 4; - - if ( flags & 0x1000 ) - // Sequence present. - len += 4; - - if ( flags & 0x0080 ) - // Acknowledgement present. - len += 4; - - return len; } void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr, const EncapsulationStack* encapsulation) { uint32_t caplen = pkt->cap_len - pkt->hdr_size; - const struct ip* ip4 = ip_hdr->IP4_Hdr(); - uint32_t len = ip_hdr->TotalLen(); - if ( len == 0 ) - { - // TCP segmentation offloading can zero out the ip_len field. - Weird("ip_hdr_len_zero", pkt, encapsulation); - - // Cope with the zero'd out ip_len field by using the caplen. - len = pkt->cap_len - pkt->hdr_size; - } - - if ( pkt->len < len + pkt->hdr_size ) - { - Weird("truncated_IP", pkt, encapsulation); - return; - } - - // For both of these it is safe to pass ip_hdr because the presence - // is guaranteed for the functions that pass data to us. uint16_t ip_hdr_len = ip_hdr->HdrLen(); - if ( ip_hdr_len > len ) - { - Weird("invalid_IP_header_size", ip_hdr, encapsulation); - return; - } - - if ( ip_hdr_len > caplen ) - { - Weird("internally_truncated_header", ip_hdr, encapsulation); - return; - } - - if ( ip_hdr->IP4_Hdr() ) - { - if ( ip_hdr_len < sizeof(struct ip) ) - { - Weird("IPv4_min_header_size", pkt); - return; - } - } - else - { - if ( ip_hdr_len < sizeof(struct ip6_hdr) ) - { - Weird("IPv6_min_header_size", pkt); - return; - } - } - - // Ignore if packet matches packet filter. - if ( packet_filter && packet_filter->Match(ip_hdr, len, caplen) ) - return; - - if ( ! pkt->l2_checksummed && ! zeek::detail::ignore_checksums && ip4 && - detail::in_cksum(reinterpret_cast(ip4), ip_hdr_len) != 0xffff ) - { - Weird("bad_IP_checksum", pkt, encapsulation); - return; - } - - if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) ) - return; - - detail::FragReassembler* f = nullptr; - - if ( ip_hdr->IsFragment() ) - { - pkt->dump_packet = true; // always record fragments - - if ( caplen < len ) - { - Weird("incompletely_captured_fragment", ip_hdr, encapsulation); - - // Don't try to reassemble, that's doomed. - // Discard all except the first fragment (which - // is useful in analyzing header-only traces) - if ( ip_hdr->FragOffset() != 0 ) - return; - } - else - { - f = NextFragment(t, ip_hdr, pkt->data + pkt->hdr_size); - const IP_Hdr* ih = f->ReassembledPkt(); - if ( ! ih ) - // It didn't reassemble into anything yet. - return; - - ip4 = ih->IP4_Hdr(); - ip_hdr = ih; - - caplen = len = ip_hdr->TotalLen(); - ip_hdr_len = ip_hdr->HdrLen(); - - if ( ip_hdr_len > len ) - { - Weird("invalid_IP_header_size", ip_hdr, encapsulation); - return; - } - } - } - - detail::FragReassemblerTracker frt(this, f); len -= ip_hdr_len; // remove IP header - caplen -= ip_hdr_len; + caplen -= ip_hdr_len; // remove IP header - // We stop building the chain when seeing IPPROTO_ESP so if it's - // there, it's always the last. - if ( ip_hdr->LastHeader() == IPPROTO_ESP ) - { - pkt->dump_packet = true; - if ( esp_packet ) - event_mgr.Enqueue(esp_packet, ip_hdr->ToPktHdrVal()); - - // Can't do more since upper-layer payloads are going to be encrypted. - return; - } - -#ifdef ENABLE_MOBILE_IPV6 - // We stop building the chain when seeing IPPROTO_MOBILITY so it's always - // last if present. - if ( ip_hdr->LastHeader() == IPPROTO_MOBILITY ) - { - pkt->dump_packet = true; - - if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff ) - { - Weird("bad_MH_checksum", pkt, encapsulation); - return; - } - - if ( mobile_ipv6_message ) - event_mgr.Enqueue(mobile_ipv6_message, ip_hdr->ToPktHdrVal()); - - if ( ip_hdr->NextProto() != IPPROTO_NONE ) - Weird("mobility_piggyback", pkt, encapsulation); - - return; - } -#endif int proto = ip_hdr->NextProto(); if ( CheckHeaderTrunc(proto, len, caplen, pkt, encapsulation) ) @@ -368,8 +182,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr id.dst_addr = ip_hdr->DstAddr(); ConnectionMap* d = nullptr; BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::IP; - int gre_version = -1; - int gre_link_type = DLT_RAW; switch ( proto ) { case IPPROTO_TCP: @@ -424,236 +236,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr break; } - case IPPROTO_GRE: - { - if ( ! BifConst::Tunnel::enable_gre ) - { - Weird("GRE_tunnel", ip_hdr, encapsulation); - return; - } - - uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0))); - uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2))); - gre_version = flags_ver & 0x0007; - - unsigned int eth_len = 0; - unsigned int gre_len = gre_header_len(flags_ver); - unsigned int ppp_len = gre_version == 1 ? 4 : 0; - unsigned int erspan_len = 0; - - if ( gre_version != 0 && gre_version != 1 ) - { - Weird("unknown_gre_version", ip_hdr, encapsulation, - util::fmt("%d", gre_version)); - return; - } - - if ( gre_version == 0 ) - { - if ( proto_typ == 0x6558 ) - { - // transparent ethernet bridging - if ( len > gre_len + 14 ) - { - eth_len = 14; - gre_link_type = DLT_EN10MB; - proto_typ = ntohs(*((uint16_t*)(data + gre_len + eth_len - 2))); - } - else - { - Weird("truncated_GRE", ip_hdr, encapsulation); - return; - } - } - - else if ( proto_typ == 0x88be ) - { - // ERSPAN type II - if ( len > gre_len + 14 + 8 ) - { - erspan_len = 8; - eth_len = 14; - gre_link_type = DLT_EN10MB; - proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2))); - } - else - { - Weird("truncated_GRE", ip_hdr, encapsulation); - return; - } - } - - else if ( proto_typ == 0x22eb ) - { - // ERSPAN type III - if ( len > gre_len + 14 + 12 ) - { - erspan_len = 12; - eth_len = 14; - gre_link_type = DLT_EN10MB; - - auto flags = data + gre_len + erspan_len - 1; - bool have_opt_header = ((*flags & 0x01) == 0x01); - - if ( have_opt_header ) - { - if ( len > gre_len + erspan_len + 8 + eth_len ) - erspan_len += 8; - else - { - Weird("truncated_GRE", ip_hdr, encapsulation); - return; - } - } - - proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2))); - } - else - { - Weird("truncated_GRE", ip_hdr, encapsulation); - return; - } - } - } - - else // gre_version == 1 - { - if ( proto_typ != 0x880b ) - { - // Enhanced GRE payload must be PPP. - Weird("egre_protocol_type", ip_hdr, encapsulation, - util::fmt("%d", proto_typ)); - return; - } - } - - if ( flags_ver & 0x4000 ) - { - // RFC 2784 deprecates the variable length routing field - // specified by RFC 1701. It could be parsed here, but easiest - // to just skip for now. - Weird("gre_routing", ip_hdr, encapsulation); - return; - } - - if ( flags_ver & 0x0078 ) - { - // Expect last 4 bits of flags are reserved, undefined. - Weird("unknown_gre_flags", ip_hdr, encapsulation); - return; - } - - if ( len < gre_len + ppp_len + eth_len + erspan_len || caplen < gre_len + ppp_len + eth_len + erspan_len ) - { - Weird("truncated_GRE", ip_hdr, encapsulation); - return; - } - - if ( gre_version == 1 ) - { - uint16_t ppp_proto = ntohs(*((uint16_t*)(data + gre_len + 2))); - - if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 ) - { - Weird("non_ip_packet_in_encap", ip_hdr, encapsulation); - return; - } - - proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6; - } - - // If we know there's an Ethernet header here, it's not skipped yet. - // The Packet::init() that happens later will process all layer 2 - // data, including things like vlan tags. - data += gre_len + ppp_len + erspan_len; - len -= gre_len + ppp_len + erspan_len; - caplen -= gre_len + ppp_len + erspan_len; - - // Treat GRE tunnel like IP tunnels, fallthrough to logic below now - // that GRE header is stripped and only payload packet remains. - // The only thing different is the tunnel type enum value to use. - tunnel_type = BifEnum::Tunnel::GRE; - } - - case IPPROTO_IPV4: - case IPPROTO_IPV6: - { - if ( ! BifConst::Tunnel::enable_ip ) - { - Weird("IP_tunnel", ip_hdr, encapsulation); - return; - } - - if ( encapsulation && - encapsulation->Depth() >= BifConst::Tunnel::max_depth ) - { - Weird("exceeded_tunnel_max_depth", ip_hdr, encapsulation); - return; - } - - IP_Hdr* inner = nullptr; - - if ( gre_version != 0 ) - { - // Check for a valid inner packet first. - int result = ParseIPPacket(caplen, data, proto, inner); - if ( result == -2 ) - Weird("invalid_inner_IP_version", ip_hdr, encapsulation); - else if ( result < 0 ) - Weird("truncated_inner_IP", ip_hdr, encapsulation); - else if ( result > 0 ) - Weird("inner_IP_payload_length_mismatch", ip_hdr, encapsulation); - - if ( result != 0 ) - { - delete inner; - return; - } - } - - // Look up to see if we've already seen this IP tunnel, identified - // by the pair of IP addresses, so that we can always associate the - // same UID with it. - IPPair tunnel_idx; - if ( ip_hdr->SrcAddr() < ip_hdr->DstAddr() ) - tunnel_idx = IPPair(ip_hdr->SrcAddr(), ip_hdr->DstAddr()); - else - tunnel_idx = IPPair(ip_hdr->DstAddr(), ip_hdr->SrcAddr()); - - IPTunnelMap::iterator it = ip_tunnels.find(tunnel_idx); - - if ( it == ip_tunnels.end() ) - { - EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(), - tunnel_type); - ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time); - detail::timer_mgr->Add(new detail::IPTunnelTimer(run_state::network_time, tunnel_idx)); - } - else - it->second.second = zeek::run_state::network_time; - - if ( gre_version == 0 ) - DoNextInnerPacket(t, pkt, caplen, len, data, gre_link_type, - encapsulation, ip_tunnels[tunnel_idx].first); - else - DoNextInnerPacket(t, pkt, inner, encapsulation, - ip_tunnels[tunnel_idx].first); - - return; - } - - case IPPROTO_NONE: - { - // If the packet is encapsulated in Teredo, then it was a bubble and - // the Teredo analyzer may have raised an event for that, else we're - // not sure the reason for the No Next header in the packet. - if ( ! ( encapsulation && - encapsulation->LastType() == BifEnum::Tunnel::TEREDO ) ) - Weird("ipv6_no_next", pkt); - - return; - } - default: Weird("unknown_protocol", pkt, encapsulation, util::fmt("%d", proto)); return; @@ -717,15 +299,11 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal()); conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data, - record_packet, record_content, pkt); + record_packet, record_content, pkt); - if ( f ) - { - // Above we already recorded the fragment in its entirety. - f->DeleteTimer(); - } - - else if ( record_packet ) + // We skip this block for reassembled packets because the pointer + // math wouldn't work. + if ( ! ip_hdr->reassembled && record_packet ) { if ( record_content ) pkt->dump_packet = true; // save the whole thing @@ -738,82 +316,6 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr } } -void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, - const IP_Hdr* inner, const EncapsulationStack* prev, - const EncapsulatingConn& ec) - { - uint32_t caplen, len; - caplen = len = inner->TotalLen(); - - pkt_timeval ts; - int link_type; - - if ( pkt ) - ts = pkt->ts; - else - { - ts.tv_sec = (time_t) run_state::network_time; - ts.tv_usec = (suseconds_t) - ((run_state::network_time - (double)ts.tv_sec) * 1000000); - } - - const u_char* data = nullptr; - - if ( inner->IP4_Hdr() ) - data = (const u_char*) inner->IP4_Hdr(); - else - data = (const u_char*) inner->IP6_Hdr(); - - EncapsulationStack* outer = prev ? - new EncapsulationStack(*prev) : new EncapsulationStack(); - outer->Add(ec); - - // Construct fake packet for DoNextPacket - Packet p; - p.Init(DLT_RAW, &ts, caplen, len, data, false, ""); - packet_mgr->ProcessPacket(&p); - - DoNextPacket(t, &p, inner, outer); - - delete inner; - delete outer; - } - -void NetSessions::DoNextInnerPacket(double t, const Packet* pkt, - uint32_t caplen, uint32_t len, - const u_char* data, int link_type, - const EncapsulationStack* prev, - const EncapsulatingConn& ec) - { - pkt_timeval ts; - - if ( pkt ) - ts = pkt->ts; - else - { - ts.tv_sec = (time_t) run_state::network_time; - ts.tv_usec = (suseconds_t) - ((run_state::network_time - (double)ts.tv_sec) * 1000000); - } - - EncapsulationStack* outer = prev ? - new EncapsulationStack(*prev) : new EncapsulationStack(); - outer->Add(ec); - - // Construct fake packet for DoNextPacket - Packet p; - p.Init(link_type, &ts, caplen, len, data, false, ""); - packet_mgr->ProcessPacket(&p); - - if ( p.l2_valid && (p.l3_proto == L3_IPV4 || p.l3_proto == L3_IPV6) ) - { - auto inner = p.IP(); - DoNextPacket(t, &p, &inner, outer); - } - - delete outer; - } - int NetSessions::ParseIPPacket(int caplen, const u_char* const pkt, int proto, IP_Hdr*& inner) { @@ -862,18 +364,6 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen, case IPPROTO_UDP: min_hdr_len = sizeof(struct udphdr); break; - case IPPROTO_IPV4: - min_hdr_len = sizeof(struct ip); - break; - case IPPROTO_IPV6: - min_hdr_len = sizeof(struct ip6_hdr); - break; - case IPPROTO_NONE: - min_hdr_len = 0; - break; - case IPPROTO_GRE: - min_hdr_len = 4; - break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: default: @@ -897,31 +387,6 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32_t len, uint32_t caplen, return false; } -detail::FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt) - { - uint32_t frag_id = ip->ID(); - - detail::FragReassemblerKey key = std::make_tuple(ip->SrcAddr(), ip->DstAddr(), frag_id); - - detail::FragReassembler* f = nullptr; - auto it = fragments.find(key); - if ( it != fragments.end() ) - f = it->second; - - if ( ! f ) - { - f = new detail::FragReassembler(this, ip, pkt, key, t); - fragments[key] = f; - if ( fragments.size() > stats.max_fragments ) - stats.max_fragments = fragments.size(); - return f; - } - - f->AddFragment(t, ip, pkt); - return f; - } - Connection* NetSessions::FindConnection(Val* v) { const auto& vt = v->GetType(); @@ -1048,17 +513,6 @@ void NetSessions::Remove(Connection* c) } } -void NetSessions::Remove(detail::FragReassembler* f) - { - if ( ! f ) - return; - - if ( fragments.erase(f->Key()) == 0 ) - reporter->InternalWarning("fragment reassembler not in dict"); - - Unref(f); - } - void NetSessions::Insert(Connection* c) { assert(c->IsKeyValid()); @@ -1135,13 +589,12 @@ void NetSessions::Clear() Unref(entry.second); for ( const auto& entry : icmp_conns ) Unref(entry.second); - for ( const auto& entry : fragments ) - Unref(entry.second); tcp_conns.clear(); udp_conns.clear(); icmp_conns.clear(); - fragments.clear(); + + detail::fragment_mgr->Clear(); } void NetSessions::GetStats(SessionStats& s) const @@ -1152,13 +605,13 @@ void NetSessions::GetStats(SessionStats& s) const s.cumulative_UDP_conns = stats.cumulative_UDP_conns; s.num_ICMP_conns = icmp_conns.size(); s.cumulative_ICMP_conns = stats.cumulative_ICMP_conns; - s.num_fragments = fragments.size(); - s.num_packets = num_packets_processed; + s.num_fragments = detail::fragment_mgr->Size(); + s.num_packets = packet_mgr->PacketsProcessed(); s.max_TCP_conns = stats.max_TCP_conns; s.max_UDP_conns = stats.max_UDP_conns; s.max_ICMP_conns = stats.max_ICMP_conns; - s.max_fragments = stats.max_fragments; + s.max_fragments = detail::fragment_mgr->MaxFragments(); } Connection* NetSessions::NewConn(const detail::ConnIDKey& k, double t, const ConnID* id, @@ -1393,7 +846,7 @@ unsigned int NetSessions::MemoryAllocation() + (tcp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type))) + (udp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type))) + (icmp_conns.size() * (sizeof(ConnectionMap::key_type) + sizeof(ConnectionMap::value_type))) - + (fragments.size() * (sizeof(FragmentMap::key_type) + sizeof(FragmentMap::value_type))) + + detail::fragment_mgr->MemoryAllocation(); // FIXME: MemoryAllocation() not implemented for rest. ; } diff --git a/src/Sessions.h b/src/Sessions.h index 991eeacd5a..3286c70123 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -15,20 +15,16 @@ ZEEK_FORWARD_DECLARE_NAMESPACED(EncapsulationStack, zeek); ZEEK_FORWARD_DECLARE_NAMESPACED(EncapsulatingConn, zeek); ZEEK_FORWARD_DECLARE_NAMESPACED(Packet, zeek); -ZEEK_FORWARD_DECLARE_NAMESPACED(PacketProfiler, zeek::detail); ZEEK_FORWARD_DECLARE_NAMESPACED(Connection, zeek); class ConnCompressor; namespace zeek { struct ConnID; } using ConnID [[deprecated("Remove in v4.1. Use zeek::ConnID.")]] = zeek::ConnID; -ZEEK_FORWARD_DECLARE_NAMESPACED(Discarder, zeek::detail); ZEEK_FORWARD_DECLARE_NAMESPACED(SteppingStoneManager, zeek, analyzer::stepping_stone); namespace zeek { -namespace detail { class IPTunnelTimer; } - struct SessionStats { size_t num_TCP_conns; size_t max_TCP_conns; @@ -53,23 +49,17 @@ public: ~NetSessions(); // Main entry point for packet processing. + [[deprecated("Remove in v4.1. Do not call this method directly. Packet processing should start with a call to packet_mgr->ProcessPacket().")]] void NextPacket(double t, const Packet* pkt); void Done(); // call to drain events before destructing - // Returns a reassembled packet, or nil if there are still - // some missing fragments. - detail::FragReassembler* NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt); - // Looks up the connection referred to by the given Val, // which should be a conn_id record. Returns nil if there's // no such connection or the Val is ill-formed. Connection* FindConnection(Val* v); void Remove(Connection* c); - void Remove(detail::FragReassembler* f); - void Insert(Connection* c); // Generating connection_pending events for all connections @@ -86,9 +76,9 @@ public: void Weird(const char* name, const IP_Hdr* ip, const EncapsulationStack* encap = nullptr, const char* addl = ""); - detail::PacketFilter* GetPacketFilter() + detail::PacketFilter* GetPacketFilter(bool init=true) { - if ( ! packet_filter ) + if ( ! packet_filter && init ) packet_filter = new detail::PacketFilter(detail::packet_filter_default); return packet_filter; } @@ -100,48 +90,14 @@ public: return tcp_conns.size() + udp_conns.size() + icmp_conns.size(); } + /** + * Main entry point for processing packets destined for session analyzers. This + * method is called by the packet analysis manager when after it has processed + * an IP-based packet, and shouldn't be called directly from other places. + */ void DoNextPacket(double t, const Packet *pkt, const IP_Hdr* ip_hdr, const EncapsulationStack* encapsulation); - /** - * Wrapper that recurses on DoNextPacket for encapsulated IP packets. - * - * @param t Network time. - * @param pkt If the outer pcap header is available, this pointer can be set - * so that the fake pcap header passed to DoNextPacket will use - * the same timeval. The caplen and len fields of the fake pcap - * header are always set to the TotalLength() of \a inner. - * @param inner Pointer to IP header wrapper of the inner packet, ownership - * of the pointer's memory is assumed by this function. - * @param prev Any previous encapsulation stack of the caller, not including - * the most-recently found depth of encapsulation. - * @param ec The most-recently found depth of encapsulation. - */ - void DoNextInnerPacket(double t, const Packet *pkt, - const IP_Hdr* inner, const EncapsulationStack* prev, - const EncapsulatingConn& ec); - - /** - * Recurses on DoNextPacket for encapsulated Ethernet/IP packets. - * - * @param t Network time. - * @param pkt If the outer pcap header is available, this pointer can be - * set so that the fake pcap header passed to DoNextPacket will use - * the same timeval. - * @param caplen number of captured bytes remaining - * @param len number of bytes remaining as claimed by outer framing - * @param data the remaining packet data - * @param link_type layer 2 link type used for initializing inner packet - * @param prev Any previous encapsulation stack of the caller, not - * including the most-recently found depth of encapsulation. - * @param ec The most-recently found depth of encapsulation. - */ - void DoNextInnerPacket(double t, const Packet* pkt, - uint32_t caplen, uint32_t len, - const u_char* data, int link_type, - const EncapsulationStack* prev, - const EncapsulatingConn& ec); - /** * Returns a wrapper IP_Hdr object if \a pkt appears to be a valid IPv4 * or IPv6 header based on whether it's long enough to contain such a header, @@ -172,12 +128,15 @@ public: unsigned int MemoryAllocation(); analyzer::tcp::TCPStateStats tcp_stats; // keeps statistics on TCP states + // Record the given packet (if a dumper is active). If len=0 + // then the whole packet is recorded, otherwise just the first + // len bytes. + void DumpPacket(const Packet *pkt, int len=0); + protected: friend class ConnCompressor; - friend class detail::IPTunnelTimer; using ConnectionMap = std::map; - using FragmentMap = std::map; Connection* NewConn(const detail::ConnIDKey& k, double t, const ConnID* id, const u_char* data, int proto, uint32_t flow_label, @@ -203,11 +162,6 @@ protected: TransportProto transport_proto, uint8_t tcp_flags, bool& flip_roles); - // Record the given packet (if a dumper is active). If len=0 - // then the whole packet is recorded, otherwise just the first - // len bytes. - void DumpPacket(const Packet *pkt, int len=0); - // For a given protocol, checks whether the header's length as derived // from lower-level headers or the length actually captured is less // than that protocol's minimum header size. @@ -224,55 +178,13 @@ protected: ConnectionMap tcp_conns; ConnectionMap udp_conns; ConnectionMap icmp_conns; - FragmentMap fragments; SessionStats stats; - using IPPair = std::pair; - using TunnelActivity = std::pair; - using IPTunnelMap = std::map; - IPTunnelMap ip_tunnels; - analyzer::stepping_stone::SteppingStoneManager* stp_manager; - detail::Discarder* discarder; detail::PacketFilter* packet_filter; - uint64_t num_packets_processed; - detail::PacketProfiler* pkt_profiler; }; -namespace detail { - -class IPTunnelTimer final : public Timer { -public: - IPTunnelTimer(double t, NetSessions::IPPair p) - : Timer(t + BifConst::Tunnel::ip_tunnel_timeout, - TIMER_IP_TUNNEL_INACTIVITY), tunnel_idx(p) {} - - ~IPTunnelTimer() override {} - - void Dispatch(double t, bool is_expire) override; - -protected: - NetSessions::IPPair tunnel_idx; -}; - - -class FragReassemblerTracker { -public: - FragReassemblerTracker(NetSessions* s, FragReassembler* f) - : net_sessions(s), frag_reassembler(f) - { } - - ~FragReassemblerTracker() - { net_sessions->Remove(frag_reassembler); } - -private: - NetSessions* net_sessions; - FragReassembler* frag_reassembler; -}; - -} // namespace detail - // Manager for the currently active sessions. extern NetSessions* sessions; @@ -280,7 +192,6 @@ extern NetSessions* sessions; using SessionStats [[deprecated("Remove in v4.1. Use zeek::SessionStats.")]] = zeek::SessionStats; using NetSessions [[deprecated("Remove in v4.1. Use zeek::NetSessions.")]] = zeek::NetSessions; -using IPTunnelTimer [[deprecated("Remove in v4.1. Use zeek::detail::IPTunnelTimer.")]] = zeek::detail::IPTunnelTimer; using FragReassemblerTracker [[deprecated("Remove in v4.1. Use zeek::detail::FragReassemblerTracker.")]] = zeek::detail::FragReassemblerTracker; extern zeek::NetSessions*& sessions [[deprecated("Remove in v4.1. Use zeek:sessions.")]]; diff --git a/src/analyzer/protocol/ayiya/AYIYA.cc b/src/analyzer/protocol/ayiya/AYIYA.cc index ebafa9cf30..0f6b3a7d4b 100644 --- a/src/analyzer/protocol/ayiya/AYIYA.cc +++ b/src/analyzer/protocol/ayiya/AYIYA.cc @@ -1,6 +1,8 @@ +// See the file "COPYING" in the main distribution directory for copyright. #include "AYIYA.h" #include "Func.h" +#include "packet_analysis/protocol/iptunnel/IPTunnel.h" namespace zeek::analyzer::ayiya { @@ -48,9 +50,10 @@ void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 if ( result == 0 ) { ProtocolConfirmation(); + const zeek::EncapsulationStack* e = Conn()->GetEncapsulation(); EncapsulatingConn ec(Conn(), BifEnum::Tunnel::AYIYA); - sessions->DoNextInnerPacket(run_state::network_time, nullptr, - inner, Conn()->GetEncapsulation(), ec); + packet_analysis::IPTunnel::ip_tunnel_analyzer->ProcessEncapsulatedPacket( + run_state::network_time, nullptr, inner, e, ec); } else if ( result == -2 ) ProtocolViolation("AYIYA next header internal mismatch", diff --git a/src/analyzer/protocol/gtpv1/GTPv1.cc b/src/analyzer/protocol/gtpv1/GTPv1.cc index 139c2ad958..2ef7c2347c 100644 --- a/src/analyzer/protocol/gtpv1/GTPv1.cc +++ b/src/analyzer/protocol/gtpv1/GTPv1.cc @@ -1,6 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. #include "GTPv1.h" +#include "packet_analysis/protocol/iptunnel/IPTunnel.h" #include "events.bif.h" @@ -61,9 +62,10 @@ void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint6 std::move(gtp_hdr_val), inner->ToPktHdrVal()); + const zeek::EncapsulationStack* e = Conn()->GetEncapsulation(); EncapsulatingConn ec(Conn(), BifEnum::Tunnel::GTPv1); - sessions->DoNextInnerPacket(run_state::network_time, nullptr, - inner, Conn()->GetEncapsulation(), ec); + zeek::packet_analysis::IPTunnel::ip_tunnel_analyzer->ProcessEncapsulatedPacket( + run_state::network_time, nullptr, inner, e, ec); } else if ( result == -2 ) ProtocolViolation("Invalid IP version in wrapped packet", diff --git a/src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac b/src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac index 855b36abd6..b1d14d810c 100644 --- a/src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac +++ b/src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac @@ -714,7 +714,6 @@ flow GTPv1_Flow(is_orig: bool) %{ ZeekAnalyzer a = connection()->zeek_analyzer(); zeek::Connection* c = a->Conn(); - const zeek::EncapsulationStack* e = c->GetEncapsulation(); if ( ${pdu.packet}.length() < (int)sizeof(struct ip) ) { diff --git a/src/analyzer/protocol/teredo/Teredo.cc b/src/analyzer/protocol/teredo/Teredo.cc index 67ab721b1e..15d1fe3212 100644 --- a/src/analyzer/protocol/teredo/Teredo.cc +++ b/src/analyzer/protocol/teredo/Teredo.cc @@ -7,6 +7,7 @@ #include "Sessions.h" #include "ZeekString.h" #include "RunState.h" +#include "packet_analysis/protocol/iptunnel/IPTunnel.h" #include "events.bif.h" @@ -233,7 +234,8 @@ void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, EncapsulatingConn ec(Conn(), BifEnum::Tunnel::TEREDO); - sessions->DoNextInnerPacket(run_state::network_time, nullptr, inner, e, ec); + packet_analysis::IPTunnel::ip_tunnel_analyzer->ProcessEncapsulatedPacket( + run_state::network_time, nullptr, inner, e, ec); } } // namespace zeek::analyzer::teredo diff --git a/src/analyzer/protocol/vxlan/VXLAN.cc b/src/analyzer/protocol/vxlan/VXLAN.cc index 8f67ece511..2469c94575 100644 --- a/src/analyzer/protocol/vxlan/VXLAN.cc +++ b/src/analyzer/protocol/vxlan/VXLAN.cc @@ -10,6 +10,7 @@ #include "Sessions.h" #include "Reporter.h" #include "packet_analysis/Manager.h" +#include "packet_analysis/protocol/iptunnel/IPTunnel.h" #include "events.bif.h" @@ -47,16 +48,27 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, return; } - const EncapsulationStack* estack = Conn()->GetEncapsulation(); + EncapsulationStack* outer = Conn()->GetEncapsulation(); - if ( estack && estack->Depth() >= BifConst::Tunnel::max_depth ) + if ( outer && outer->Depth() >= BifConst::Tunnel::max_depth ) { reporter->Weird(Conn(), "tunnel_depth"); return; } + bool delete_outer = false; + if ( ! outer ) + { + outer = new EncapsulationStack(); + delete_outer = true; + } + + EncapsulatingConn inner(Conn(), BifEnum::Tunnel::VXLAN); + outer->Add(inner); + int vni = (data[4] << 16) + (data[5] << 8) + (data[6] << 0); + // Skip over the VXLAN header and create a new packet. data += vxlan_len; caplen -= vxlan_len; len -= vxlan_len; @@ -65,10 +77,14 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, ts.tv_sec = (time_t) run_state::current_timestamp; ts.tv_usec = (suseconds_t) ((run_state::current_timestamp - (double)ts.tv_sec) * 1000000); Packet pkt(DLT_EN10MB, &ts, caplen, len, data); + pkt.key_store["encap"] = outer; packet_mgr->ProcessPacket(&pkt); if ( ! pkt.l2_valid ) { + if ( delete_outer ) + delete outer; + ProtocolViolation("VXLAN invalid inner ethernet frame", (const char*) data, len); return; @@ -78,15 +94,15 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, len -= pkt.hdr_size; caplen -= pkt.hdr_size; - IP_Hdr* inner = nullptr; + IP_Hdr* inner_hdr = nullptr; int res = 0; switch ( pkt.l3_proto ) { case L3_IPV4: - res = sessions->ParseIPPacket(len, data, IPPROTO_IPV4, inner); + res = sessions->ParseIPPacket(len, data, IPPROTO_IPV4, inner_hdr); break; case L3_IPV6: - res = sessions->ParseIPPacket(len, data, IPPROTO_IPV6, inner); + res = sessions->ParseIPPacket(len, data, IPPROTO_IPV6, inner_hdr); break; default: return; @@ -94,7 +110,10 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, if ( res < 0 ) { - delete inner; + delete inner_hdr; + if ( delete_outer ) + delete outer; + ProtocolViolation("Truncated VXLAN or invalid inner IP", (const char*) data, len); return; @@ -104,10 +123,10 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, if ( vxlan_packet ) Conn()->EnqueueEvent(vxlan_packet, nullptr, ConnVal(), - inner->ToPktHdrVal(), val_mgr->Count(vni)); + inner_hdr->ToPktHdrVal(), val_mgr->Count(vni)); - EncapsulatingConn ec(Conn(), BifEnum::Tunnel::VXLAN); - sessions->DoNextInnerPacket(run_state::network_time, &pkt, inner, estack, ec); + if ( delete_outer ) + delete outer; } } // namespace zeek::analyzer::vxlan diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc index 5a8339add0..a32873045b 100644 --- a/src/iosource/Packet.cc +++ b/src/iosource/Packet.cc @@ -45,7 +45,6 @@ void Packet::Init(int arg_link_type, pkt_timeval *arg_ts, uint32_t arg_caplen, else data = arg_data; - session_analysis = false; dump_packet = false; time = ts.tv_sec + double(ts.tv_usec) / 1e6; @@ -75,9 +74,9 @@ const IP_Hdr Packet::IP() const return IP_Hdr((struct ip *) (data + hdr_size), false); } -void Packet::Weird(const char* name) +void Packet::Weird(const char* name, const EncapsulationStack* encap) { - sessions->Weird(name, this); + sessions->Weird(name, this, encap); } RecordValPtr Packet::ToRawPktHdrVal() const diff --git a/src/iosource/Packet.h b/src/iosource/Packet.h index 5c46b548b1..91bb95a64a 100644 --- a/src/iosource/Packet.h +++ b/src/iosource/Packet.h @@ -2,10 +2,11 @@ #include "zeek-config.h" -#include - #include #include // for u_char +#include +#include +#include #if defined(__OpenBSD__) #include @@ -18,6 +19,7 @@ ZEEK_FORWARD_DECLARE_NAMESPACED(ODesc, zeek); ZEEK_FORWARD_DECLARE_NAMESPACED(Val, zeek); ZEEK_FORWARD_DECLARE_NAMESPACED(RecordVal, zeek); ZEEK_FORWARD_DECLARE_NAMESPACED(IP_Hdr, zeek); +ZEEK_FORWARD_DECLARE_NAMESPACED(EncapsulationStack, zeek); namespace zeek { @@ -207,19 +209,18 @@ public: */ bool l3_checksummed; - /** - * Indicates whether the packet should be processed by zeek's - * session analysis in NetSessions. - */ - bool session_analysis; - /** * Indicates whether this packet should be recorded. */ mutable bool dump_packet; - // Wrapper to generate a packet-level weird. Has to be public for packet analyzers to use it. - void Weird(const char* name); + /** + * Key/value store for use by the packet analyzers to pass information between them. + */ + std::map key_store; + + // Wrapper to generate a packet-level weird. Has to be public for llanalyzers to use it. + void Weird(const char* name, const EncapsulationStack* encap = nullptr); private: // Renders an MAC address into its ASCII representation. diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 60521426cb..82caa11a88 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -162,22 +162,7 @@ void PktSrc::Process() if ( ! ExtractNextPacketInternal() ) return; - // This is set here to avoid having to pass the packet source down into the processing - // methods unnecessarily. - run_state::detail::current_iosrc = this; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - run_state::detail::current_pktsrc = this; -#pragma GCC diagnostic pop - - packet_mgr->ProcessPacket(¤t_packet); - run_state::detail::dispatch_packet(¤t_packet); - - run_state::detail::current_iosrc = nullptr; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - run_state::detail::current_pktsrc = nullptr; -#pragma GCC diagnostic pop + run_state::detail::dispatch_packet(¤t_packet, this); have_packet = false; DoneWithPacket(); diff --git a/src/packet_analysis/Analyzer.h b/src/packet_analysis/Analyzer.h index 241787135e..b60553f541 100644 --- a/src/packet_analysis/Analyzer.h +++ b/src/packet_analysis/Analyzer.h @@ -69,14 +69,16 @@ public: * in the header. In this case, derived classes may use ForwardPacket() to * forward the payload to the corresponding analyzer. * - * @param len The number of bytes passed in. + * @param len The number of bytes passed in. As we move along the chain of + * analyzers, this is the number of bytes we have left of the packet to + * process. * @param data Pointer to the input to process. * @param packet Object that maintains the packet's meta data. * * @return false if the analysis failed, else true. */ virtual bool AnalyzePacket(size_t len, const uint8_t* data, - Packet* packet) = 0; + Packet* packet) = 0; /** * Dumps out debug information to the \c analyzer debug stream. @@ -124,7 +126,7 @@ protected: * @return false if the analysis failed, else true. */ bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet, - uint32_t identifier) const; + uint32_t identifier) const; /** * Triggers default analysis of the encapsulated packet if the default analyzer diff --git a/src/packet_analysis/Manager.cc b/src/packet_analysis/Manager.cc index 4229bfb33a..39a3d07e2b 100644 --- a/src/packet_analysis/Manager.cc +++ b/src/packet_analysis/Manager.cc @@ -4,6 +4,10 @@ #include "Analyzer.h" #include "Dispatcher.h" +#include "zeek-bif.h" +#include "Stats.h" +#include "zeek/Sessions.h" +#include "zeek/RunState.h" using namespace zeek::packet_analysis; @@ -12,6 +16,11 @@ Manager::Manager() { } +Manager::~Manager() + { + delete pkt_profiler; + } + void Manager::InitPostScript() { // Instantiate objects for all available analyzers @@ -26,6 +35,13 @@ void Manager::InitPostScript() analyzer->Initialize(); root_analyzer = analyzers["Root"]; + + static auto pkt_profile_file = id::find_val("pkt_profile_file"); + + if ( detail::pkt_profile_mode && detail::pkt_profile_freq > 0 && pkt_profile_file ) + pkt_profiler = new detail::PacketProfiler(detail::pkt_profile_mode, + detail::pkt_profile_freq, + pkt_profile_file->AsFile()); } void Manager::Done() @@ -69,9 +85,37 @@ void Manager::ProcessPacket(Packet* packet) static size_t counter = 0; DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time); #endif + + zeek::detail::SegmentProfiler prof(detail::segment_logger, "dispatching-packet"); + if ( pkt_profiler ) + pkt_profiler->ProfilePkt(zeek::run_state::processing_start_time, packet->cap_len); + + ++num_packets_processed; + + bool dumped_packet = false; + if ( packet->dump_packet || zeek::detail::record_all_packets ) + { + // TODO: should this stay in Session? + sessions->DumpPacket(packet); + dumped_packet = true; + } + // Start packet analysis packet->l2_valid = root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type); + + if ( raw_packet ) + event_mgr.Enqueue(raw_packet, packet->ToRawPktHdrVal()); + + // Check whether packet should be recorded based on session analysis + if ( packet->dump_packet && ! dumped_packet ) + // TODO: should this stay in Session? + sessions->DumpPacket(packet); + } + +bool Manager::ProcessInnerPacket(Packet* packet) + { + return root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type); } AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag) diff --git a/src/packet_analysis/Manager.h b/src/packet_analysis/Manager.h index 059d8537ea..ff68a1e94c 100644 --- a/src/packet_analysis/Manager.h +++ b/src/packet_analysis/Manager.h @@ -8,6 +8,8 @@ #include "iosource/Packet.h" #include "Dispatcher.h" +ZEEK_FORWARD_DECLARE_NAMESPACED(PacketProfiler, zeek::detail); + namespace zeek { namespace packet_analysis { @@ -24,7 +26,7 @@ public: /** * Destructor. */ - ~Manager() = default; + ~Manager(); /** * Second-stage initialization of the manager. This is called late @@ -69,6 +71,18 @@ public: */ void ProcessPacket(Packet* packet); + /** + * Process the inner packet of an encapsulation. This can be used by tunnel + * analyzers to process a inner packet from the "beginning" directly through + * the root analyzer. This short-circuits some of the additional processing + * that happens in ProcessPacket(). + * + * @param packet The packet to process. + */ + bool ProcessInnerPacket(Packet* packet); + + uint64_t PacketsProcessed() const { return num_packets_processed; } + private: /** * Instantiates a new analyzer instance. @@ -92,6 +106,9 @@ private: std::map analyzers; AnalyzerPtr root_analyzer = nullptr; + + uint64_t num_packets_processed = 0; + detail::PacketProfiler* pkt_profiler = nullptr; }; } // namespace packet_analysis diff --git a/src/packet_analysis/protocol/CMakeLists.txt b/src/packet_analysis/protocol/CMakeLists.txt index 10103d7dca..4d9d12ba2c 100644 --- a/src/packet_analysis/protocol/CMakeLists.txt +++ b/src/packet_analysis/protocol/CMakeLists.txt @@ -15,5 +15,5 @@ add_subdirectory(linux_sll) add_subdirectory(arp) add_subdirectory(ip) -add_subdirectory(ipv4) -add_subdirectory(ipv6) +add_subdirectory(gre) +add_subdirectory(iptunnel) diff --git a/src/packet_analysis/protocol/ipv4/CMakeLists.txt b/src/packet_analysis/protocol/gre/CMakeLists.txt similarity index 63% rename from src/packet_analysis/protocol/ipv4/CMakeLists.txt rename to src/packet_analysis/protocol/gre/CMakeLists.txt index 80c8d9c5c0..4456675dd7 100644 --- a/src/packet_analysis/protocol/ipv4/CMakeLists.txt +++ b/src/packet_analysis/protocol/gre/CMakeLists.txt @@ -3,6 +3,6 @@ include(ZeekPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -zeek_plugin_begin(PacketAnalyzer IPv4) -zeek_plugin_cc(IPv4.cc Plugin.cc) +zeek_plugin_begin(PacketAnalyzer GRE) +zeek_plugin_cc(GRE.cc Plugin.cc) zeek_plugin_end() diff --git a/src/packet_analysis/protocol/gre/GRE.cc b/src/packet_analysis/protocol/gre/GRE.cc new file mode 100644 index 0000000000..756fa50add --- /dev/null +++ b/src/packet_analysis/protocol/gre/GRE.cc @@ -0,0 +1,218 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "GRE.h" +#include "zeek/Sessions.h" +#include "zeek/RunState.h" +#include "zeek/IP.h" +#include "zeek/Reporter.h" + +#include "pcap.h" // For DLT_ constants + +using namespace zeek::packet_analysis::GRE; + +static unsigned int gre_header_len(uint16_t flags) + { + unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type. + + if ( flags & 0x8000 ) + // Checksum/Reserved1 present. + len += 4; + + // Not considering routing presence bit since it's deprecated ... + + if ( flags & 0x2000 ) + // Key present. + len += 4; + + if ( flags & 0x1000 ) + // Sequence present. + len += 4; + + if ( flags & 0x0080 ) + // Acknowledgement present. + len += 4; + + return len; + } + +GREAnalyzer::GREAnalyzer() + : zeek::packet_analysis::Analyzer("GRE") + { + } + +bool GREAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) + { + EncapsulationStack* encapsulation = nullptr; + auto it = packet->key_store.find("encap"); + if ( it != packet->key_store.end() ) + encapsulation = std::any_cast(it->second); + + it = packet->key_store.find("ip_hdr"); + if ( it == packet->key_store.end() ) + { + reporter->InternalError("GREAnalyzer: ip_hdr not found in packet keystore"); + return false; + } + + IP_Hdr* ip_hdr = std::any_cast(it->second); + + int proto = -1; + it = packet->key_store.find("proto"); + if ( it != packet->key_store.end() ) + proto = std::any_cast(proto); + + if ( ! BifConst::Tunnel::enable_gre ) + { + sessions->Weird("GRE_tunnel", ip_hdr, encapsulation); + return false; + } + + int gre_link_type = DLT_RAW; + + uint16_t flags_ver = ntohs(*((uint16_t*)(data + 0))); + uint16_t proto_typ = ntohs(*((uint16_t*)(data + 2))); + int gre_version = flags_ver & 0x0007; + + unsigned int eth_len = 0; + unsigned int gre_len = gre_header_len(flags_ver); + unsigned int ppp_len = gre_version == 1 ? 4 : 0; + unsigned int erspan_len = 0; + + if ( gre_version != 0 && gre_version != 1 ) + { + sessions->Weird("unknown_gre_version", ip_hdr, encapsulation, + util::fmt("%d", gre_version)); + return false; + } + + if ( gre_version == 0 ) + { + if ( proto_typ == 0x6558 ) + { + // transparent ethernet bridging + if ( len > gre_len + 14 ) + { + eth_len = 14; + gre_link_type = DLT_EN10MB; + proto_typ = ntohs(*((uint16_t*)(data + gre_len + eth_len - 2))); + } + else + { + sessions->Weird("truncated_GRE", ip_hdr, encapsulation); + return false; + } + } + + else if ( proto_typ == 0x88be ) + { + // ERSPAN type II + if ( len > gre_len + 14 + 8 ) + { + erspan_len = 8; + eth_len = 14; + gre_link_type = DLT_EN10MB; + proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2))); + } + else + { + sessions->Weird("truncated_GRE", ip_hdr, encapsulation); + return false; + } + } + + else if ( proto_typ == 0x22eb ) + { + // ERSPAN type III + if ( len > gre_len + 14 + 12 ) + { + erspan_len = 12; + eth_len = 14; + gre_link_type = DLT_EN10MB; + + auto flags = data + gre_len + erspan_len - 1; + bool have_opt_header = ((*flags & 0x01) == 0x01); + + if ( have_opt_header ) + { + if ( len > gre_len + erspan_len + 8 + eth_len ) + erspan_len += 8; + else + { + sessions->Weird("truncated_GRE", ip_hdr, encapsulation); + return false; + } + } + + proto_typ = ntohs(*((uint16_t*)(data + gre_len + erspan_len + eth_len - 2))); + } + else + { + sessions->Weird("truncated_GRE", ip_hdr, encapsulation); + return false; + } + } + } + + else // gre_version == 1 + { + if ( proto_typ != 0x880b ) + { + // Enhanced GRE payload must be PPP. + sessions->Weird("egre_protocol_type", ip_hdr, encapsulation, + util::fmt("%d", proto_typ)); + return false; + } + } + + if ( flags_ver & 0x4000 ) + { + // RFC 2784 deprecates the variable length routing field + // specified by RFC 1701. It could be parsed here, but easiest + // to just skip for now. + sessions->Weird("gre_routing", ip_hdr, encapsulation); + return false; + } + + if ( flags_ver & 0x0078 ) + { + // Expect last 4 bits of flags are reserved, undefined. + sessions->Weird("unknown_gre_flags", ip_hdr, encapsulation); + return false; + } + + if ( len < gre_len + ppp_len + eth_len + erspan_len ) + { + sessions->Weird("truncated_GRE", ip_hdr, encapsulation); + return false; + } + + if ( gre_version == 1 ) + { + uint16_t ppp_proto = ntohs(*((uint16_t*)(data + gre_len + 2))); + + if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 ) + { + sessions->Weird("non_ip_packet_in_encap", ip_hdr, encapsulation); + return false; + } + + proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6; + } + + data += gre_len + ppp_len + erspan_len; + len -= gre_len + ppp_len + erspan_len; + + // Treat GRE tunnel like IP tunnels, fallthrough to logic below now + // that GRE header is stripped and only payload packet remains. + // The only thing different is the tunnel type enum value to use. + BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::GRE; + + packet->key_store["tunnel_type"] = tunnel_type; + packet->key_store["gre_version"] = gre_version; + packet->key_store["gre_link_type"] = gre_link_type; + packet->key_store["proto"] = proto; + + ForwardPacket(len, data, packet); + + return true; + } diff --git a/src/packet_analysis/protocol/ipv4/IPv4.h b/src/packet_analysis/protocol/gre/GRE.h similarity index 65% rename from src/packet_analysis/protocol/ipv4/IPv4.h rename to src/packet_analysis/protocol/gre/GRE.h index 4a4833abef..b90dfad0fc 100644 --- a/src/packet_analysis/protocol/ipv4/IPv4.h +++ b/src/packet_analysis/protocol/gre/GRE.h @@ -5,18 +5,18 @@ #include #include -namespace zeek::packet_analysis::IPv4 { +namespace zeek::packet_analysis::GRE { -class IPv4Analyzer : public Analyzer { +class GREAnalyzer : public Analyzer { public: - IPv4Analyzer(); - ~IPv4Analyzer() override = default; + GREAnalyzer(); + ~GREAnalyzer() override = default; bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override; static zeek::packet_analysis::AnalyzerPtr Instantiate() { - return std::make_shared(); + return std::make_shared(); } }; diff --git a/src/packet_analysis/protocol/ipv6/Plugin.cc b/src/packet_analysis/protocol/gre/Plugin.cc similarity index 54% rename from src/packet_analysis/protocol/ipv6/Plugin.cc rename to src/packet_analysis/protocol/gre/Plugin.cc index 474926e000..4a3aefd52e 100644 --- a/src/packet_analysis/protocol/ipv6/Plugin.cc +++ b/src/packet_analysis/protocol/gre/Plugin.cc @@ -1,23 +1,24 @@ // See the file "COPYING" in the main distribution directory for copyright. +#include "GRE.h" #include "plugin/Plugin.h" -#include "IPv6.h" #include "packet_analysis/Component.h" -namespace zeek::plugin::Zeek_IPv6 { +namespace zeek::plugin::Zeek_GRE { class Plugin : public zeek::plugin::Plugin { public: zeek::plugin::Configuration Configure() { - AddComponent(new zeek::packet_analysis::Component("IPv6", - zeek::packet_analysis::IPv6::IPv6Analyzer::Instantiate)); + AddComponent(new zeek::packet_analysis::Component("GRE", + zeek::packet_analysis::GRE::GREAnalyzer::Instantiate)); zeek::plugin::Configuration config; - config.name = "Zeek::IPv6"; - config.description = "IPv6 packet analyzer"; + config.name = "Zeek::GRE"; + config.description = "GRE packet analyzer"; return config; } + } plugin; } diff --git a/src/packet_analysis/protocol/ip/IP.cc b/src/packet_analysis/protocol/ip/IP.cc index 2153ee0ebb..bba6750307 100644 --- a/src/packet_analysis/protocol/ip/IP.cc +++ b/src/packet_analysis/protocol/ip/IP.cc @@ -1,37 +1,274 @@ // See the file "COPYING" in the main distribution directory for copyright. #include "IP.h" -#include "NetVar.h" +#include "zeek/NetVar.h" +#include "zeek/IP.h" +#include "zeek/Discard.h" +#include "zeek/PacketFilter.h" +#include "zeek/Sessions.h" +#include "zeek/RunState.h" +#include "zeek/Frag.h" +#include "zeek/Event.h" +#include "zeek/TunnelEncapsulation.h" using namespace zeek::packet_analysis::IP; IPAnalyzer::IPAnalyzer() : zeek::packet_analysis::Analyzer("IP") + { + discarder = new detail::Discarder(); + if ( ! discarder->IsActive() ) + { + delete discarder; + discarder = nullptr; + } + } + +IPAnalyzer::~IPAnalyzer() { } bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) { - // Assume we're pointing at IP. Just figure out which version. - if ( sizeof(struct ip) >= len ) + EncapsulationStack* encapsulation = nullptr; + auto it = packet->key_store.find("encap"); + if ( it != packet->key_store.end() ) + encapsulation = std::any_cast(it->second); + + // Check to make sure we have enough data left for an IP header to be here. Note we only + // check ipv4 here. We'll check ipv6 later once we determine we have an ipv6 header. + if ( len < sizeof(struct ip) ) { - packet->Weird("packet_analyzer_truncated_header"); + packet->Weird("truncated_IP"); return false; } + // TODO: i feel like this could be generated as we move along the header hierarchy. + // TODO: the sessions code expects that the header size does not include the ip header. Should + // this change? + packet->hdr_size = static_cast(data - packet->data); + + // Cast the current data pointer to an IP header pointer so we can use it to get some + // data about the header. auto ip = (const struct ip *)data; uint32_t protocol = ip->ip_v; - auto inner_analyzer = Lookup(protocol); - if ( inner_analyzer == nullptr ) + std::unique_ptr ip_hdr = nullptr; + if ( protocol == 4 ) { - DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.", - GetAnalyzerName(), protocol); - packet->Weird("no_suitable_analyzer_found"); + ip_hdr = std::make_unique(ip, false); + packet->l3_proto = L3_IPV4; + } + else if ( protocol == 6 ) + { + if ( len < sizeof(struct ip6_hdr) ) + { + packet->Weird("truncated_IP"); + return false; + } + + ip_hdr = std::make_unique((const struct ip6_hdr*) data, false, len); + packet->l3_proto = L3_IPV6; + } + else + { + packet->Weird("unknown_ip_version"); return false; } - DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", - GetAnalyzerName(), protocol); - return inner_analyzer->AnalyzePacket(len, data, packet); - } \ No newline at end of file + const struct ip* ip4 = ip_hdr->IP4_Hdr(); + + // total_len is the length of the packet minus all of the headers so far, including IP + uint32_t total_len = ip_hdr->TotalLen(); + if ( total_len == 0 ) + { + // TCP segmentation offloading can zero out the ip_len field. + packet->Weird("ip_hdr_len_zero", encapsulation); + + // Cope with the zero'd out ip_len field by using the caplen. + total_len = packet->cap_len - packet->hdr_size; + } + + if ( packet->len < total_len + packet->hdr_size ) + { + packet->Weird("truncated_IP", encapsulation); + return false; + } + + // For both of these it is safe to pass ip_hdr because the presence + // is guaranteed for the functions that pass data to us. + uint16_t ip_hdr_len = ip_hdr->HdrLen(); + if ( ip_hdr_len > total_len ) + { + sessions->Weird("invalid_IP_header_size", ip_hdr.get(), encapsulation); + return false; + } + + if ( ip_hdr_len > len ) + { + sessions->Weird("internally_truncated_header", ip_hdr.get(), encapsulation); + return false; + } + + if ( ip_hdr->IP4_Hdr() ) + { + if ( ip_hdr_len < sizeof(struct ip) ) + { + packet->Weird("IPv4_min_header_size"); + return false; + } + } + else + { + if ( ip_hdr_len < sizeof(struct ip6_hdr) ) + { + packet->Weird("IPv6_min_header_size"); + return false; + } + } + + // Ignore if packet matches packet filter. + detail::PacketFilter* packet_filter = sessions->GetPacketFilter(false); + if ( packet_filter && packet_filter->Match(ip_hdr.get(), total_len, len) ) + return false; + + if ( ! packet->l2_checksummed && ! detail::ignore_checksums && ip4 && + detail::in_cksum(reinterpret_cast(ip4), ip_hdr_len) != 0xffff ) + { + sessions->Weird("bad_IP_checksum", packet, encapsulation); + return false; + } + + if ( discarder && discarder->NextPacket(ip_hdr.get(), total_len, len) ) + return false; + + detail::FragReassembler* f = nullptr; + + if ( ip_hdr->IsFragment() ) + { + packet->dump_packet = true; // always record fragments + + if ( len < total_len ) + { + sessions->Weird("incompletely_captured_fragment", ip_hdr.get(), encapsulation); + + // Don't try to reassemble, that's doomed. + // Discard all except the first fragment (which + // is useful in analyzing header-only traces) + if ( ip_hdr->FragOffset() != 0 ) + return false; + } + else + { + f = detail::fragment_mgr->NextFragment(run_state::processing_start_time, ip_hdr.get(), packet->data + packet->hdr_size); + IP_Hdr* ih = f->ReassembledPkt(); + if ( ! ih ) + // It didn't reassemble into anything yet. + return true; + + ip4 = ih->IP4_Hdr(); + + // Delete the old ip_hdr and replace it with this one. + ip_hdr.reset(ih); + + len = total_len = ip_hdr->TotalLen(); + ip_hdr_len = ip_hdr->HdrLen(); + packet->cap_len = total_len + packet->hdr_size; + + // TODO: in the old code, the data pointer is updated to point at the IP header's + // payload, so it contains all of the data when it's processed. This isn't a big + // deal for when we pass it down into the session analyzers, since that does the + // same itself. should it be updated here for the case where a fragmented packet + // is actually tunneled? is that a thing that can happen? Does updating the data + // pointer without also updating the one in packet cause any problems? + + if ( ip_hdr_len > total_len ) + { + sessions->Weird("invalid_IP_header_size", ip_hdr.get(), encapsulation); + return false; + } + } + } + + detail::FragReassemblerTracker frt(f); + + // We stop building the chain when seeing IPPROTO_ESP so if it's + // there, it's always the last. + if ( ip_hdr->LastHeader() == IPPROTO_ESP ) + { + packet->dump_packet = true; + if ( esp_packet ) + event_mgr.Enqueue(esp_packet, ip_hdr->ToPktHdrVal()); + + // Can't do more since upper-layer payloads are going to be encrypted. + return true; + } + +#ifdef ENABLE_MOBILE_IPV6 + // We stop building the chain when seeing IPPROTO_MOBILITY so it's always + // last if present. + if ( ip_hdr->LastHeader() == IPPROTO_MOBILITY ) + { + dump_this_packet = true; + + if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff ) + { + sessions->Weird("bad_MH_checksum", packet, encapsulation); + return false; + } + + if ( mobile_ipv6_message ) + event_mgr.Enqueue(mobile_ipv6_message, ip_hdr->ToPktHdrVal()); + + if ( ip_hdr->NextProto() != IPPROTO_NONE ) + sessions->Weird("mobility_piggyback", packet, encapsulation); + + return true; + } +#endif + + // Advance the data pointer past the IP header based on the header length + data += ip_hdr_len; + len -= ip_hdr_len; + + bool return_val = true; + int proto = ip_hdr->NextProto(); + + packet->key_store["ip_hdr"] = ip_hdr.get(); + packet->key_store["proto"] = proto; + + switch ( proto ) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + sessions->DoNextPacket(run_state::processing_start_time, packet, ip_hdr.get(), encapsulation); + break; + case IPPROTO_NONE: + // If the packet is encapsulated in Teredo, then it was a bubble and + // the Teredo analyzer may have raised an event for that, else we're + // not sure the reason for the No Next header in the packet. + if ( ! ( encapsulation && + encapsulation->LastType() == BifEnum::Tunnel::TEREDO ) ) + { + sessions->Weird("ipv6_no_next", packet); + return_val = false; + } + break; + default: + // For everything else, pass it on to another analyzer. If there's no one to handle that, + // it'll report a Weird. + return_val = ForwardPacket(len, data, packet, proto); + break; + } + + if ( f ) + { + // If this was a fragment, we need to release the pointer here so that it doesn't get + // deleted. Deleting this one will be the responsibility of the fragment tracker. + ip_hdr.release(); + f->DeleteTimer(); + } + + return return_val; + } diff --git a/src/packet_analysis/protocol/ip/IP.h b/src/packet_analysis/protocol/ip/IP.h index 22f3b015b7..bf7bd1461d 100644 --- a/src/packet_analysis/protocol/ip/IP.h +++ b/src/packet_analysis/protocol/ip/IP.h @@ -2,15 +2,18 @@ #pragma once -#include -#include +#include "zeek/packet_analysis/Analyzer.h" +#include "zeek/packet_analysis/Component.h" +#include "zeek/Frag.h" + +ZEEK_FORWARD_DECLARE_NAMESPACED(Discarder, zeek::detail); namespace zeek::packet_analysis::IP { class IPAnalyzer : public Analyzer { public: IPAnalyzer(); - ~IPAnalyzer() override = default; + ~IPAnalyzer() override; bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override; @@ -18,6 +21,15 @@ public: { return std::make_shared(); } + +private: + + // Returns a reassembled packet, or nil if there are still + // some missing fragments. + zeek::detail::FragReassembler* NextFragment(double t, const IP_Hdr* ip, + const u_char* pkt); + + zeek::detail::Discarder* discarder = nullptr; }; } diff --git a/src/packet_analysis/protocol/ipv6/CMakeLists.txt b/src/packet_analysis/protocol/iptunnel/CMakeLists.txt similarity index 60% rename from src/packet_analysis/protocol/ipv6/CMakeLists.txt rename to src/packet_analysis/protocol/iptunnel/CMakeLists.txt index f2614beedf..3f79212fc0 100644 --- a/src/packet_analysis/protocol/ipv6/CMakeLists.txt +++ b/src/packet_analysis/protocol/iptunnel/CMakeLists.txt @@ -3,6 +3,6 @@ include(ZeekPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -zeek_plugin_begin(PacketAnalyzer IPv6) -zeek_plugin_cc(IPv6.cc Plugin.cc) +zeek_plugin_begin(PacketAnalyzer IPTunnel) +zeek_plugin_cc(IPTunnel.cc Plugin.cc) zeek_plugin_end() diff --git a/src/packet_analysis/protocol/iptunnel/IPTunnel.cc b/src/packet_analysis/protocol/iptunnel/IPTunnel.cc new file mode 100644 index 0000000000..285557274c --- /dev/null +++ b/src/packet_analysis/protocol/iptunnel/IPTunnel.cc @@ -0,0 +1,238 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IPTunnel.h" +#include "zeek/Sessions.h" +#include "zeek/RunState.h" +#include "zeek/IP.h" +#include "zeek/TunnelEncapsulation.h" + +#include "pcap.h" // For DLT_ constants + +namespace zeek::packet_analysis::IPTunnel { + +IPTunnelAnalyzer* ip_tunnel_analyzer; + +IPTunnelAnalyzer::IPTunnelAnalyzer() + : zeek::packet_analysis::Analyzer("IPTunnel") + { + ip_tunnel_analyzer = this; + } + +bool IPTunnelAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) + { + EncapsulationStack* encapsulation = nullptr; + auto it = packet->key_store.find("encap"); + if ( it != packet->key_store.end() ) + encapsulation = std::any_cast(it->second); + + it = packet->key_store.find("ip_hdr"); + if ( it == packet->key_store.end() ) + { + reporter->InternalError("IPTunnelAnalyzer: ip_hdr not found in packet keystore"); + return false; + } + + IP_Hdr* ip_hdr = std::any_cast(it->second); + + int proto = -1; + it = packet->key_store.find("proto"); + if ( it != packet->key_store.end() ) + proto = std::any_cast(it->second); + + int gre_version = -1; + it = packet->key_store.find("gre_version"); + if ( it != packet->key_store.end() ) + gre_version = std::any_cast(it->second); + + BifEnum::Tunnel::Type tunnel_type = BifEnum::Tunnel::IP; + it = packet->key_store.find("tunnel_type"); + if ( it != packet->key_store.end() ) + tunnel_type = std::any_cast(it->second); + + int gre_link_type = DLT_RAW; + it = packet->key_store.find("gre_link_type"); + if ( it != packet->key_store.end() ) + gre_link_type = std::any_cast(it->second); + + if ( ! BifConst::Tunnel::enable_ip ) + { + sessions->Weird("IP_tunnel", ip_hdr, encapsulation); + return false; + } + + if ( encapsulation && + encapsulation->Depth() >= BifConst::Tunnel::max_depth ) + { + sessions->Weird("exceeded_tunnel_max_depth", ip_hdr, encapsulation); + return false; + } + + IP_Hdr* inner = nullptr; + + if ( gre_version != 0 ) + { + // Check for a valid inner packet first. + int result = sessions->ParseIPPacket(len, data, proto, inner); + if ( result == -2 ) + sessions->Weird("invalid_inner_IP_version", ip_hdr, encapsulation); + else if ( result < 0 ) + sessions->Weird("truncated_inner_IP", ip_hdr, encapsulation); + else if ( result > 0 ) + sessions->Weird("inner_IP_payload_length_mismatch", ip_hdr, encapsulation); + + if ( result != 0 ) + { + delete inner; + return false; + } + } + + // Look up to see if we've already seen this IP tunnel, identified + // by the pair of IP addresses, so that we can always associate the + // same UID with it. + IPPair tunnel_idx; + if ( ip_hdr->SrcAddr() < ip_hdr->DstAddr() ) + tunnel_idx = IPPair(ip_hdr->SrcAddr(), ip_hdr->DstAddr()); + else + tunnel_idx = IPPair(ip_hdr->DstAddr(), ip_hdr->SrcAddr()); + + IPTunnelMap::iterator tunnel_it = ip_tunnels.find(tunnel_idx); + + if ( tunnel_it == ip_tunnels.end() ) + { + EncapsulatingConn ec(ip_hdr->SrcAddr(), ip_hdr->DstAddr(), + tunnel_type); + ip_tunnels[tunnel_idx] = TunnelActivity(ec, run_state::network_time); + zeek::detail::timer_mgr->Add(new detail::IPTunnelTimer(run_state::network_time, tunnel_idx, this)); + } + else + tunnel_it->second.second = zeek::run_state::network_time; + + if ( gre_version == 0 ) + ProcessEncapsulatedPacket(run_state::processing_start_time, packet, len, len, data, gre_link_type, + encapsulation, ip_tunnels[tunnel_idx].first); + else + ProcessEncapsulatedPacket(run_state::processing_start_time, packet, inner, encapsulation, + ip_tunnels[tunnel_idx].first); + + return true; + } + +/** + * Handles a packet that contains an IP header directly after the tunnel header. + */ +bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, + const IP_Hdr* inner, const EncapsulationStack* prev, + const EncapsulatingConn& ec) + { + uint32_t caplen, len; + caplen = len = inner->TotalLen(); + + pkt_timeval ts; + int link_type; + + if ( pkt ) + ts = pkt->ts; + else + { + ts.tv_sec = (time_t) run_state::network_time; + ts.tv_usec = (suseconds_t) + ((run_state::network_time - (double)ts.tv_sec) * 1000000); + } + + const u_char* data = nullptr; + + if ( inner->IP4_Hdr() ) + data = (const u_char*) inner->IP4_Hdr(); + else + data = (const u_char*) inner->IP6_Hdr(); + + EncapsulationStack* outer = prev ? + new EncapsulationStack(*prev) : new EncapsulationStack(); + outer->Add(ec); + + // Construct fake packet for DoNextPacket + Packet p; + p.Init(DLT_RAW, &ts, caplen, len, data, false, ""); + p.key_store["encap"] = outer; + p.key_store["encap_inner_ip"] = inner; + + // Forward the packet back to the IP analyzer. + bool return_val = ForwardPacket(len, data, &p); + + delete inner; + delete outer; + + return return_val; + } + +/** + * Handles a packet that contains a physical-layer header after the tunnel header. + */ +bool IPTunnelAnalyzer::ProcessEncapsulatedPacket(double t, const Packet* pkt, + uint32_t caplen, uint32_t len, + const u_char* data, int link_type, + const EncapsulationStack* prev, + const EncapsulatingConn& ec) + { + pkt_timeval ts; + + if ( pkt ) + ts = pkt->ts; + else + { + ts.tv_sec = (time_t) run_state::network_time; + ts.tv_usec = (suseconds_t) + ((run_state::network_time - (double)ts.tv_sec) * 1000000); + } + + EncapsulationStack* outer = prev ? + new EncapsulationStack(*prev) : new EncapsulationStack(); + outer->Add(ec); + + // Construct fake packet for DoNextPacket + Packet p; + p.Init(link_type, &ts, caplen, len, data, false, ""); + p.key_store["encap"] = outer; + + // Process the packet as if it was a brand new packet by passing it back + // to the packet manager. + bool return_val = packet_mgr->ProcessInnerPacket(&p); + + delete outer; + + return return_val; + } + +namespace detail { + +IPTunnelTimer::IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer) + : Timer(t + BifConst::Tunnel::ip_tunnel_timeout, + zeek::detail::TIMER_IP_TUNNEL_INACTIVITY), + tunnel_idx(p), analyzer(analyzer) + { + } + +void IPTunnelTimer::Dispatch(double t, bool is_expire) + { + IPTunnelAnalyzer::IPTunnelMap::const_iterator it = + analyzer->ip_tunnels.find(tunnel_idx); + + if ( it == analyzer->ip_tunnels.end() ) + return; + + double last_active = it->second.second; + double inactive_time = t > last_active ? t - last_active : 0; + + if ( inactive_time >= BifConst::Tunnel::ip_tunnel_timeout ) + // tunnel activity timed out, delete it from map + analyzer->ip_tunnels.erase(tunnel_idx); + + else if ( ! is_expire ) + // tunnel activity didn't timeout, schedule another timer + zeek::detail::timer_mgr->Add(new IPTunnelTimer(t, tunnel_idx, analyzer)); + } + +} // namespace detail + +} // namespace zeek::packet_analysis::IPTunnel diff --git a/src/packet_analysis/protocol/iptunnel/IPTunnel.h b/src/packet_analysis/protocol/iptunnel/IPTunnel.h new file mode 100644 index 0000000000..5c259135c1 --- /dev/null +++ b/src/packet_analysis/protocol/iptunnel/IPTunnel.h @@ -0,0 +1,98 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include "zeek/IPAddr.h" +#include "zeek/TunnelEncapsulation.h" + +namespace zeek::packet_analysis::IPTunnel { + +namespace detail { class IPTunnelTimer; } + +class IPTunnelAnalyzer : public Analyzer { +public: + + IPTunnelAnalyzer(); + ~IPTunnelAnalyzer() override = default; + + bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override; + + static zeek::packet_analysis::AnalyzerPtr Instantiate() + { + return std::make_shared(); + } + + /** + * Wrapper that handles encapsulated IP packets and passes them back into + * packet analysis. + * + * @param t Network time. + * @param pkt If the outer pcap header is available, this pointer can be set + * so that the fake pcap header passed to DoNextPacket will use + * the same timeval. The caplen and len fields of the fake pcap + * header are always set to the TotalLength() of \a inner. + * @param inner Pointer to IP header wrapper of the inner packet, ownership + * of the pointer's memory is assumed by this function. + * @param prev Any previous encapsulation stack of the caller, not including + * the most-recently found depth of encapsulation. + * @param ec The most-recently found depth of encapsulation. + */ + bool ProcessEncapsulatedPacket(double t, const Packet *pkt, + const IP_Hdr* inner, const EncapsulationStack* prev, + const EncapsulatingConn& ec); + + /** + * Wrapper that handles encapsulated Ethernet/IP packets and passes them back into + * packet analysis. + * + * @param t Network time. + * @param pkt If the outer pcap header is available, this pointer can be + * set so that the fake pcap header passed to DoNextPacket will use + * the same timeval. + * @param caplen number of captured bytes remaining + * @param len number of bytes remaining as claimed by outer framing + * @param data the remaining packet data + * @param link_type layer 2 link type used for initializing inner packet + * @param prev Any previous encapsulation stack of the caller, not + * including the most-recently found depth of encapsulation. + * @param ec The most-recently found depth of encapsulation. + */ + bool ProcessEncapsulatedPacket(double t, const Packet* pkt, + uint32_t caplen, uint32_t len, + const u_char* data, int link_type, + const EncapsulationStack* prev, + const EncapsulatingConn& ec); + +protected: + + friend class detail::IPTunnelTimer; + + using IPPair = std::pair; + using TunnelActivity = std::pair; + using IPTunnelMap = std::map; + IPTunnelMap ip_tunnels; + +}; + +namespace detail { + +class IPTunnelTimer final : public zeek::detail::Timer { +public: + IPTunnelTimer(double t, IPTunnelAnalyzer::IPPair p, IPTunnelAnalyzer* analyzer); + ~IPTunnelTimer() override = default; + + void Dispatch(double t, bool is_expire) override; + +protected: + IPTunnelAnalyzer::IPPair tunnel_idx; + IPTunnelAnalyzer* analyzer; +}; + +} // namespace detail + +// This is temporary until the TCP and UDP analyzers are moved to be packet analyzers. +extern IPTunnelAnalyzer* ip_tunnel_analyzer; + +} diff --git a/src/packet_analysis/protocol/ipv4/Plugin.cc b/src/packet_analysis/protocol/iptunnel/Plugin.cc similarity index 51% rename from src/packet_analysis/protocol/ipv4/Plugin.cc rename to src/packet_analysis/protocol/iptunnel/Plugin.cc index ec865917da..c8305b2b9b 100644 --- a/src/packet_analysis/protocol/ipv4/Plugin.cc +++ b/src/packet_analysis/protocol/iptunnel/Plugin.cc @@ -1,21 +1,21 @@ // See the file "COPYING" in the main distribution directory for copyright. -#include "IPv4.h" +#include "IPTunnel.h" #include "plugin/Plugin.h" #include "packet_analysis/Component.h" -namespace zeek::plugin::Zeek_IPv4 { +namespace zeek::plugin::Zeek_IPTunnel { class Plugin : public zeek::plugin::Plugin { public: zeek::plugin::Configuration Configure() { - AddComponent(new zeek::packet_analysis::Component("IPv4", - zeek::packet_analysis::IPv4::IPv4Analyzer::Instantiate)); + AddComponent(new zeek::packet_analysis::Component("IPTunnel", + zeek::packet_analysis::IPTunnel::IPTunnelAnalyzer::Instantiate)); zeek::plugin::Configuration config; - config.name = "Zeek::IPv4"; - config.description = "IPv4 packet analyzer"; + config.name = "Zeek::IPTunnel"; + config.description = "IPTunnel packet analyzer"; return config; } diff --git a/src/packet_analysis/protocol/ipv4/IPv4.cc b/src/packet_analysis/protocol/ipv4/IPv4.cc deleted file mode 100644 index 1121ea437d..0000000000 --- a/src/packet_analysis/protocol/ipv4/IPv4.cc +++ /dev/null @@ -1,20 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "IPv4.h" - -using namespace zeek::packet_analysis::IPv4; - -IPv4Analyzer::IPv4Analyzer() - : zeek::packet_analysis::Analyzer("IPv4") - { - } - -bool IPv4Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) - { - packet->l3_proto = L3_IPV4; - packet->hdr_size = static_cast(data - packet->data); - packet->session_analysis = true; - - // Leave packet analyzer land - return true; - } diff --git a/src/packet_analysis/protocol/ipv6/IPv6.cc b/src/packet_analysis/protocol/ipv6/IPv6.cc deleted file mode 100644 index 5da788d4b7..0000000000 --- a/src/packet_analysis/protocol/ipv6/IPv6.cc +++ /dev/null @@ -1,20 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "IPv6.h" - -using namespace zeek::packet_analysis::IPv6; - -IPv6Analyzer::IPv6Analyzer() - : zeek::packet_analysis::Analyzer("IPv6") - { - } - -bool IPv6Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) - { - packet->l3_proto = L3_IPV6; - packet->hdr_size = static_cast(data - packet->data); - packet->session_analysis = true; - - // Leave packet analyzer land - return true; - } diff --git a/src/packet_analysis/protocol/ipv6/IPv6.h b/src/packet_analysis/protocol/ipv6/IPv6.h deleted file mode 100644 index a640b3beff..0000000000 --- a/src/packet_analysis/protocol/ipv6/IPv6.h +++ /dev/null @@ -1,23 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#pragma once - -#include -#include - -namespace zeek::packet_analysis::IPv6 { - -class IPv6Analyzer : public Analyzer { -public: - IPv6Analyzer(); - ~IPv6Analyzer() override = default; - - bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override; - - static AnalyzerPtr Instantiate() - { - return std::make_shared(); - } -}; - -} diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index 4d731a507c..d95857aa80 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -47,6 +47,7 @@ extern "C" { #include "Hash.h" #include "Func.h" #include "ScannedFile.h" +#include "Frag.h" #include "supervisor/Supervisor.h" #include "threading/Manager.h" @@ -136,6 +137,9 @@ zeek::detail::ProfileLogger* zeek::detail::segment_logger = nullptr; zeek::detail::ProfileLogger*& segment_logger = zeek::detail::segment_logger; zeek::detail::SampleLogger* zeek::detail::sample_logger = nullptr; zeek::detail::SampleLogger*& sample_logger = zeek::detail::sample_logger; + +zeek::detail::FragmentManager* zeek::detail::fragment_mgr = nullptr; + int signal_val = 0; extern char version[]; const char* zeek::detail::command_line_policy = nullptr; @@ -347,6 +351,7 @@ static void terminate_bro() delete reporter; delete plugin_mgr; delete val_mgr; + delete fragment_mgr; // free the global scope pop_scope(); @@ -486,6 +491,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) reporter = new Reporter(options.abort_on_scripting_errors); thread_mgr = new threading::Manager(); plugin_mgr = new plugin::Manager(); + fragment_mgr = new detail::FragmentManager(); #ifdef DEBUG if ( options.debug_log_streams ) diff --git a/testing/btest/Baseline/core.disable-mobile-ipv6/weird.log b/testing/btest/Baseline/core.disable-mobile-ipv6/weird.log index 4fafd8ceb8..bfd3e9541f 100644 --- a/testing/btest/Baseline/core.disable-mobile-ipv6/weird.log +++ b/testing/btest/Baseline/core.disable-mobile-ipv6/weird.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path weird -#open 2019-08-21-02-16-33 +#open 2020-09-15-17-17-50 #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 -1333663011.602839 - - - - - unknown_protocol 135 F zeek -#close 2019-08-21-02-16-33 +1333663011.602839 - - - - - no_suitable_analyzer_found - F zeek +#close 2020-09-15-17-17-50 diff --git a/testing/btest/Baseline/core.ip-broken-header/weird.log b/testing/btest/Baseline/core.ip-broken-header/weird.log index 8aca8dc371..d6e6ba9e65 100644 --- a/testing/btest/Baseline/core.ip-broken-header/weird.log +++ b/testing/btest/Baseline/core.ip-broken-header/weird.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path weird -#open 2019-06-07-01-59-22 +#open 2020-09-10-22-34-02 #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 - b100:7265::6904:2aff 0 3bbf:ff00:40:21:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek @@ -15,7 +15,7 @@ 1500557630.000000 - b100:7265:6374:6929::6904:ff 0 3b1e:400:ff:0:6929:0:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557630.000000 - b100:7265:6374:6929::6904:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557630.000000 - b100:6500:72:6369:2a29:0:690a:ff 0 3bbf:ff00:40:0:ffef:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek -1500557630.000000 - 255.255.0.0 0 255.255.255.223 0 invalid_inner_IP_version - F zeek +1500557630.000000 - - - - - unknown_ip_version - F zeek 1500557631.000000 - b100:7265:6300:69:7429:0:6904:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557631.000000 - 9c00:7265:6374:6929::6927:ff 0 3bbf:ff00:40:0:ffff:ffff:fbfd:f7ff 0 invalid_inner_IP_version - F zeek 1500557631.000000 - b100:7265:6374:6929::6904:ff 0 3b00:40:ffbf:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek @@ -89,7 +89,6 @@ 1500557631.000000 - 9c00:7265:6374:6929:600:0:6904:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557631.000000 - 9c00:7463:2a72:6929:400:0:6904:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557631.000000 - b000:7265:6374:6929::8004:ff 0 3bbf:ff80:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek -1500557631.000000 - 255.255.0.0 0 255.255.255.237 0 invalid_inner_IP_version - F zeek 1500557631.000000 - 0:7265:6374:6929:ff:27:a800:ff 0 100:0:143:4f4e:5445:4e54:535f:524c 0 invalid_inner_IP_version - F zeek 1500557631.000000 - b100:7265:6374:6929::6904:ff 0 3bbf:f9fe:ffbf:ffff:0:ff28:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557631.000000 - - - - - ip_hdr_len_zero - F zeek @@ -300,7 +299,6 @@ 1500557632.000000 - b100:7200:400:65:ffff:ffff:ffff:ffff 0 ffff:0:ffff:ff3a:2000:82b:0:f7ff 0 invalid_inner_IP_version - F zeek 1500557632.000000 - b100:7265:6300:69:7429:0:6904:ff 0 3bbf:ff00:40:0:ffff:fdff:ffff:f7ff 0 invalid_inner_IP_version - F zeek 1500557632.000000 - 9c00:7265:6374:6929::6127:fb 0 3bbf:6500:6fd:188:4747:4747:61fd:f7ff 0 invalid_inner_IP_version - F zeek -1500557632.000000 - 0.0.0.255 0 11.0.255.0 0 invalid_IP_header_size_in_tunnel - F zeek 1500557632.000000 - b100:7265:63ce:69:7429:0:690a:ff 0 3bbf:ff00:40:0:7fff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557632.000000 - b100:7265:6374:2a29::6904:2aff 0 3bbf:ff00:40:21:27ff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557632.000000 - b100:7265:6374:6929::6904:ff 0 3bbf:ff00:40:0:ffff:ff4e:5654:f7ff 0 invalid_inner_IP_version - F zeek @@ -462,4 +460,4 @@ 1500557634.000000 - b100:7265:6374:6929:ff:ffff:ff04:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557634.000000 - b100:7265:0:ff00:69:2980:0:69 0 c4ff:bf00:ff00:3b:40ff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek 1500557634.000000 - 9c00:7265:6374:69d1::6904:ff 0 3bbf:ff00:40:0:ffff:ffff:fffd:f7ff 0 invalid_inner_IP_version - F zeek -#close 2019-06-07-01-59-22 +#close 2020-09-10-22-34-02 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 8af64df840..a5cb9597eb 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 2020-09-08-08-14-03 +#open 2020-09-10-23-14-33 #fields name #types string scripts/base/init-bare.zeek @@ -48,6 +48,10 @@ scripts/base/init-bare.zeek scripts/base/packet-protocols/vlan/main.zeek scripts/base/packet-protocols/mpls/__load__.zeek scripts/base/packet-protocols/mpls/main.zeek + scripts/base/packet-protocols/gre/__load__.zeek + scripts/base/packet-protocols/gre/main.zeek + scripts/base/packet-protocols/iptunnel/__load__.zeek + scripts/base/packet-protocols/iptunnel/main.zeek scripts/base/init-frameworks-and-bifs.zeek scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/main.zeek @@ -216,4 +220,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 2020-09-08-08-14-03 +#close 2020-09-10-23-14-33 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 c38a701e86..a0e5808d45 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 @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2020-09-22-17-14-48 +#open 2020-09-23-19-37-26 #fields name #types string scripts/base/init-bare.zeek @@ -48,6 +48,10 @@ scripts/base/init-bare.zeek scripts/base/packet-protocols/vlan/main.zeek scripts/base/packet-protocols/mpls/__load__.zeek scripts/base/packet-protocols/mpls/main.zeek + scripts/base/packet-protocols/gre/__load__.zeek + scripts/base/packet-protocols/gre/main.zeek + scripts/base/packet-protocols/iptunnel/__load__.zeek + scripts/base/packet-protocols/iptunnel/main.zeek scripts/base/init-frameworks-and-bifs.zeek scripts/base/frameworks/logging/__load__.zeek scripts/base/frameworks/logging/main.zeek @@ -412,4 +416,4 @@ scripts/base/init-default.zeek scripts/base/misc/find-filtered-trace.zeek scripts/base/misc/version.zeek scripts/policy/misc/loaded-scripts.zeek -#close 2020-09-22-17-14-48 +#close 2020-09-23-19-37-26 diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 2c37aabc58..616f82111e 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, policy=Weird::log_policy])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy])) -> -0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1602789493.024881, 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, policy=Weird::log_policy])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy])) -> -0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::write, , (PacketFilter::LOG, [ts=1602789493.024881, 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, , ()) -> @@ -555,7 +555,7 @@ 0.000000 MetaHookPost CallFunction(PacketFilter::build, , ()) -> 0.000000 MetaHookPost CallFunction(PacketFilter::combine_filters, , (ip or not ip, and, )) -> 0.000000 MetaHookPost CallFunction(PacketFilter::install, , ()) -> -0.000000 MetaHookPost CallFunction(PacketFilter::log_policy, , ([ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=])) -> +0.000000 MetaHookPost CallFunction(PacketFilter::log_policy, , ([ts=1602789493.024881, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=])) -> 0.000000 MetaHookPost CallFunction(Pcap::install_pcap_filter, , (PacketFilter::DefaultPcapFilter)) -> 0.000000 MetaHookPost CallFunction(Pcap::precompile_pcap_filter, , (PacketFilter::DefaultPcapFilter, ip or not ip)) -> 0.000000 MetaHookPost CallFunction(SumStats::add_observe_plugin_dependency, , (SumStats::STD_DEV, SumStats::VARIANCE)) -> @@ -847,6 +847,7 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/find-filtered-trace.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ftp) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/geoip-distance.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/gre) -> -1 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 @@ -859,6 +860,7 @@ 0.000000 MetaHookPost LoadFile(0, base<...>/input.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/intel) -> -1 0.000000 MetaHookPost LoadFile(0, base<...>/ip) -> -1 +0.000000 MetaHookPost LoadFile(0, base<...>/iptunnel) -> -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 @@ -1229,7 +1231,7 @@ 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird, policy=Weird::log_policy])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy])) -0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::__write, , (PacketFilter::LOG, [ts=1602789493.024881, 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)) @@ -1410,7 +1412,7 @@ 0.000000 MetaHookPre CallFunction(Log::create_stream, , (Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird, policy=Weird::log_policy])) 0.000000 MetaHookPre CallFunction(Log::create_stream, , (X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy])) 0.000000 MetaHookPre CallFunction(Log::create_stream, , (mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy])) -0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::write, , (PacketFilter::LOG, [ts=1602789493.024881, 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, , ()) @@ -1501,7 +1503,7 @@ 0.000000 MetaHookPre CallFunction(PacketFilter::build, , ()) 0.000000 MetaHookPre CallFunction(PacketFilter::combine_filters, , (ip or not ip, and, )) 0.000000 MetaHookPre CallFunction(PacketFilter::install, , ()) -0.000000 MetaHookPre CallFunction(PacketFilter::log_policy, , ([ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=])) +0.000000 MetaHookPre CallFunction(PacketFilter::log_policy, , ([ts=1602789493.024881, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=])) 0.000000 MetaHookPre CallFunction(Pcap::install_pcap_filter, , (PacketFilter::DefaultPcapFilter)) 0.000000 MetaHookPre CallFunction(Pcap::precompile_pcap_filter, , (PacketFilter::DefaultPcapFilter, ip or not ip)) 0.000000 MetaHookPre CallFunction(SumStats::add_observe_plugin_dependency, , (SumStats::STD_DEV, SumStats::VARIANCE)) @@ -1793,6 +1795,7 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/find-filtered-trace.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/ftp) 0.000000 MetaHookPre LoadFile(0, base<...>/geoip-distance.zeek) +0.000000 MetaHookPre LoadFile(0, base<...>/gre) 0.000000 MetaHookPre LoadFile(0, base<...>/hash) 0.000000 MetaHookPre LoadFile(0, base<...>/hash_hrw.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/http) @@ -1805,6 +1808,7 @@ 0.000000 MetaHookPre LoadFile(0, base<...>/input.bif.zeek) 0.000000 MetaHookPre LoadFile(0, base<...>/intel) 0.000000 MetaHookPre LoadFile(0, base<...>/ip) +0.000000 MetaHookPre LoadFile(0, base<...>/iptunnel) 0.000000 MetaHookPre LoadFile(0, base<...>/irc) 0.000000 MetaHookPre LoadFile(0, base<...>/krb) 0.000000 MetaHookPre LoadFile(0, base<...>/linux_sll) @@ -2174,7 +2178,7 @@ 0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird, policy=Weird::log_policy]) 0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy]) 0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy]) -0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1602789493.024881, 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) @@ -2355,7 +2359,7 @@ 0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=Weird::Info, ev=Weird::log_weird, path=weird, policy=Weird::log_policy]) 0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=X509::Info, ev=X509::log_x509, path=x509, policy=X509::log_policy]) 0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=MySQL::Info, ev=MySQL::log_mysql, path=mysql, policy=MySQL::log_policy]) -0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1602789493.024881, 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() @@ -2446,7 +2450,7 @@ 0.000000 | HookCallFunction PacketFilter::build() 0.000000 | HookCallFunction PacketFilter::combine_filters(ip or not ip, and, ) 0.000000 | HookCallFunction PacketFilter::install() -0.000000 | HookCallFunction PacketFilter::log_policy([ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=]) +0.000000 | HookCallFunction PacketFilter::log_policy([ts=1602789493.024881, node=zeek, filter=ip or not ip, init=T, success=T], PacketFilter::LOG, [name=default, writer=Log::WRITER_ASCII, pred=, path=packet_filter, path_func=, include=, exclude=, log_local=T, log_remote=T, field_name_map={}, scope_sep=., ext_prefix=_, ext_func=lambda_<2528247166937952945>, interv=0 secs, postprocessor=, config={}, policy=]) 0.000000 | HookCallFunction Pcap::install_pcap_filter(PacketFilter::DefaultPcapFilter) 0.000000 | HookCallFunction Pcap::precompile_pcap_filter(PacketFilter::DefaultPcapFilter, ip or not ip) 0.000000 | HookCallFunction SumStats::add_observe_plugin_dependency(SumStats::STD_DEV, SumStats::VARIANCE) @@ -2750,6 +2754,7 @@ 0.000000 | HookLoadFile base<...>/find-filtered-trace.zeek 0.000000 | HookLoadFile base<...>/ftp 0.000000 | HookLoadFile base<...>/geoip-distance.zeek +0.000000 | HookLoadFile base<...>/gre 0.000000 | HookLoadFile base<...>/hash 0.000000 | HookLoadFile base<...>/hash_hrw.zeek 0.000000 | HookLoadFile base<...>/http @@ -2762,6 +2767,7 @@ 0.000000 | HookLoadFile base<...>/input.bif.zeek 0.000000 | HookLoadFile base<...>/intel 0.000000 | HookLoadFile base<...>/ip +0.000000 | HookLoadFile base<...>/iptunnel 0.000000 | HookLoadFile base<...>/irc 0.000000 | HookLoadFile base<...>/krb 0.000000 | HookLoadFile base<...>/linux_sll @@ -2831,7 +2837,7 @@ 0.000000 | HookLoadFile base<...>/xmpp 0.000000 | HookLoadFile base<...>/zeek.bif.zeek 0.000000 | HookLogInit packet_filter 1/1 {ts (time), node (string), filter (string), init (bool), success (bool)} -0.000000 | HookLogWrite packet_filter [ts=1601496515.916419, node=zeek, filter=ip or not ip, init=T, success=T] +0.000000 | HookLogWrite packet_filter [ts=1602789493.024881, 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()