From: Bhagya Tholpady (bbantwal) Date: Fri, 25 Sep 2020 17:37:39 +0000 (+0000) Subject: Merge pull request #2477 in SNORT/snort3 from ~OKHOMIAK/snort3:update_s5_trace to... X-Git-Tag: 3.0.3-2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b609554ca7dc8077de23985c30a22422ab0ddee1;p=thirdparty%2Fsnort3.git Merge pull request #2477 in SNORT/snort3 from ~OKHOMIAK/snort3:update_s5_trace to master Squashed commit of the following: commit ec9f6a8e1b7deb16e663fac1c5f38c085f06136d Author: Oleksii Khomiakovskyi Date: Tue Sep 8 12:34:45 2020 +0300 stream_tcp: update trace messages to use trace framework --- diff --git a/src/stream/tcp/CMakeLists.txt b/src/stream/tcp/CMakeLists.txt index 09f8e1dd3..0380349e6 100644 --- a/src/stream/tcp/CMakeLists.txt +++ b/src/stream/tcp/CMakeLists.txt @@ -66,6 +66,8 @@ add_library( stream_tcp OBJECT tcp_stream_session.h tcp_stream_tracker.cc tcp_stream_tracker.h + tcp_trace.cc + tcp_trace.h ${TEST_FILES} ) diff --git a/src/stream/tcp/tcp_module.cc b/src/stream/tcp/tcp_module.cc index cfc771269..d1642490c 100644 --- a/src/stream/tcp/tcp_module.cc +++ b/src/stream/tcp/tcp_module.cc @@ -27,6 +27,9 @@ #include "main/snort_config.h" #include "profiler/profiler_defs.h" #include "stream/paf.h" +#include "trace/trace.h" + +#include "tcp_trace.h" using namespace snort; @@ -36,6 +39,16 @@ using namespace snort; THREAD_LOCAL ProfileStats s5TcpPerfStats; +THREAD_LOCAL const Trace* stream_tcp_trace = nullptr; + +static const TraceOption stream_tcp_trace_options[] = +{ + { "segments", TRACE_SEGMENTS, "enable stream TCP segments trace logging" }, + { "state", TRACE_STATE, "enable stream TCP state trace logging" }, + + { nullptr, 0, nullptr } +}; + const PegInfo tcp_pegs[] = { SESSION_PEGS("tcp"), @@ -239,6 +252,12 @@ StreamTcpModule::StreamTcpModule() : config = nullptr; } +void StreamTcpModule::set_trace(const Trace* trace) const +{ stream_tcp_trace = trace; } + +const TraceOption* StreamTcpModule::get_trace_options() const +{ return stream_tcp_trace_options; } + const RuleMap* StreamTcpModule::get_rules() const { return stream_tcp_rules; } diff --git a/src/stream/tcp/tcp_module.h b/src/stream/tcp/tcp_module.h index f651e3bb6..9fd3d7a7d 100644 --- a/src/stream/tcp/tcp_module.h +++ b/src/stream/tcp/tcp_module.h @@ -51,6 +51,7 @@ extern const PegInfo tcp_pegs[]; +extern THREAD_LOCAL const snort::Trace* stream_tcp_trace; extern THREAD_LOCAL snort::ProfileStats s5TcpPerfStats; struct TcpStats @@ -119,11 +120,6 @@ extern THREAD_LOCAL struct TcpStats tcpStats; #define STREAM_TCP_MOD_NAME "stream_tcp" #define STREAM_TCP_MOD_HELP "stream inspector for TCP flow tracking and stream normalization and reassembly" -namespace snort -{ -struct SnortConfig; -} - class StreamTcpModule : public snort::Module { public: @@ -149,6 +145,9 @@ public: bool is_bindable() const override { return true; } + void set_trace(const snort::Trace*) const override; + const snort::TraceOption* get_trace_options() const override; + private: TcpStreamConfig* config; }; diff --git a/src/stream/tcp/tcp_reassembler.cc b/src/stream/tcp/tcp_reassembler.cc index 222089b49..56f411bfb 100644 --- a/src/stream/tcp/tcp_reassembler.cc +++ b/src/stream/tcp/tcp_reassembler.cc @@ -62,34 +62,6 @@ static void purge_alerts_callback_ips(IpsContext* c) session->client.reassembler.purge_alerts(); } -void TcpReassembler::trace_segments(TcpReassemblerState& trs) -{ - TcpSegmentNode* tsn = trs.sos.seglist.head; - uint32_t sx = trs.tracker->r_win_base; - unsigned segs = 0, bytes = 0; - - while ( tsn ) - { - if (SEQ_LT(sx, tsn->i_seq)) - fprintf(stdout, " +%u", tsn->i_seq - sx); - else if (SEQ_GT(sx, tsn->i_seq)) - fprintf(stdout, " -%u", sx - tsn->i_seq); - - fprintf(stdout, " %hu", tsn->i_len); - - if ( tsn->c_len and tsn->c_len != tsn->i_len ) - fprintf(stdout, "(%hu|%hu|%d)", - tsn->offset, tsn->c_len, tsn->i_len-tsn->offset-tsn->c_len); - - segs++; - bytes += tsn->i_len; - sx = tsn->i_seq + tsn->i_len; - tsn = tsn->next; - } - assert(trs.sos.seg_count == segs); - assert(trs.sos.seg_bytes_logical == bytes); -} - bool TcpReassembler::is_segment_pending_flush(TcpReassemblerState& trs) { return ( get_pending_segment_count(trs, 1) > 0 ); diff --git a/src/stream/tcp/tcp_reassembler.h b/src/stream/tcp/tcp_reassembler.h index ea609984c..a77d12eb7 100644 --- a/src/stream/tcp/tcp_reassembler.h +++ b/src/stream/tcp/tcp_reassembler.h @@ -38,7 +38,6 @@ public: virtual bool is_segment_pending_flush(TcpReassemblerState&); virtual int flush_on_data_policy(TcpReassemblerState&, snort::Packet*); virtual int flush_on_ack_policy(TcpReassemblerState&, snort::Packet*); - virtual void trace_segments(TcpReassemblerState&); virtual bool add_alert(TcpReassemblerState&, uint32_t gid, uint32_t sid); virtual bool check_alerted(TcpReassemblerState&, uint32_t gid, uint32_t sid); virtual int update_alert(TcpReassemblerState&, uint32_t gid, uint32_t sid, diff --git a/src/stream/tcp/tcp_reassemblers.h b/src/stream/tcp/tcp_reassemblers.h index 928a8da53..9e961c167 100644 --- a/src/stream/tcp/tcp_reassemblers.h +++ b/src/stream/tcp/tcp_reassemblers.h @@ -82,9 +82,6 @@ public: int flush_on_ack_policy(snort::Packet* p) { return reassembler->flush_on_ack_policy(trs, p); } - void trace_segments() - { reassembler->trace_segments(trs); } - void set_seglist_base_seq(uint32_t seglist_base_seq) { trs.sos.seglist_base_seq = seglist_base_seq; } @@ -139,6 +136,7 @@ public: private: TcpReassembler* reassembler = nullptr; TcpReassemblerState trs; + friend inline void TraceSegments(const TcpReassemblerPolicy&, const snort::Packet* p); }; #endif diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 3fe36e117..3d1a4e091 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -56,13 +56,13 @@ #include "protocols/eth.h" #include "stream_tcp.h" -#include "tcp_debug_trace.h" #include "tcp_ha.h" #include "tcp_module.h" #include "tcp_normalizers.h" #include "tcp_reassemblers.h" #include "tcp_segment_node.h" #include "tcp_state_machine.h" +#include "tcp_trace.h" using namespace snort; @@ -1058,12 +1058,12 @@ bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd) return ( pkt_action_mask & ACTION_BAD_PKT ) ? false : true; } -int TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd) +int TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd, const Packet* p) { tsm->eval(tsd); check_events_and_actions(tsd); - S5TraceTCP(tsd); + S5TraceTCP(tsd, p); return ACTION_NOTHING; } @@ -1086,7 +1086,7 @@ int TcpSession::process(Packet* p) { TcpSegmentDescriptor ma_tsd(flow, p, tcp_mack->tcp_ack_seq_num, tcp_mack->tcp_window_size); init_tcp_packet_analysis(ma_tsd); - process_tcp_packet(ma_tsd); + process_tcp_packet(ma_tsd, p); tcpStats.meta_acks++; } @@ -1097,7 +1097,7 @@ int TcpSession::process(Packet* p) && !handle_syn_on_reset_session(tsd) ) return ACTION_NOTHING; - return process_tcp_packet(tsd); + return process_tcp_packet(tsd, p); } void TcpSession::flush() diff --git a/src/stream/tcp/tcp_session.h b/src/stream/tcp/tcp_session.h index 06f570a19..42e4d40bf 100644 --- a/src/stream/tcp/tcp_session.h +++ b/src/stream/tcp/tcp_session.h @@ -73,7 +73,7 @@ public: { return tcp_config->midstream_allowed(tsd.get_pkt()); } private: - int process_tcp_packet(TcpSegmentDescriptor&); + int process_tcp_packet(TcpSegmentDescriptor&, const snort::Packet*); void process_tcp_stream(TcpSegmentDescriptor&); int process_tcp_data(TcpSegmentDescriptor&); void set_os_policy() override; diff --git a/src/stream/tcp/tcp_stream_tracker.h b/src/stream/tcp/tcp_stream_tracker.h index 490c5650f..4da152f26 100644 --- a/src/stream/tcp/tcp_stream_tracker.h +++ b/src/stream/tcp/tcp_stream_tracker.h @@ -247,7 +247,7 @@ public: void set_flush_policy(FlushPolicy policy) { flush_policy = policy; } - FlushPolicy get_flush_policy() + FlushPolicy get_flush_policy() const { return flush_policy; } virtual void init_tcp_state(); diff --git a/src/stream/tcp/tcp_debug_trace.h b/src/stream/tcp/tcp_trace.cc similarity index 53% rename from src/stream/tcp/tcp_debug_trace.h rename to src/stream/tcp/tcp_trace.cc index 21c2a6b65..e9f5af14a 100644 --- a/src/stream/tcp/tcp_debug_trace.h +++ b/src/stream/tcp/tcp_trace.cc @@ -16,18 +16,24 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -// tcp_debug_trace.h author davis mcpherson -// Created on: Aug 5, 2015 +// tcp_trace.cc author Oleksii Khomiakovskyi +// based on work by davis mcpherson -#ifndef TCP_DEBUG_TRACE_H -#define TCP_DEBUG_TRACE_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tcp_trace.h" +#include "main/snort_debug.h" #include "utils/stats.h" -#include "tcp_reassemblers.h" +#include "tcp_module.h" +#include "tcp_session.h" +#include "tcp_stream_tracker.h" -#ifndef REG_TEST -#define S5TraceTCP(tsd) +#ifndef DEBUG_MSGS +void S5TraceTCP(const TcpSegmentDescriptor&, const snort::Packet*) { } #else #define LCL(p, x) ((p).x() - (p).get_iss()) #define RMT(p, x, q) ((p).x - (q).get_iss()) @@ -40,24 +46,23 @@ static const char* const statext[] = static const char* const flushxt[] = { "IGN", "FPR", "PRE", "PRO", "PAF" }; -static THREAD_LOCAL int s5_trace_enabled = -1; // FIXIT-L should use module trace feature - -inline void TraceEvent(const TcpSegmentDescriptor& tsd, uint32_t txd, uint32_t rxd) +inline void TraceEvent(const TcpSegmentDescriptor& tsd, uint32_t txd, uint32_t rxd, + const snort::Packet* p) { char flags[7] = "UAPRSF"; const snort::tcp::TCPHdr* h = tsd.get_tcph(); const char* order = ""; const char* meta_ack_marker = tsd.is_meta_ack_packet() ? "M" : " "; - if (!h) + if ( !h ) return; for (int i = 0; i < 6; i++) - if (!((1 << (5 - i)) & h->th_flags)) + if ( !((1 << (5 - i)) & h->th_flags) ) flags[i] = '-'; // force relative ack to zero if not conveyed - if (flags[1] != 'A') + if ( flags[1] != 'A' ) rxd = tsd.get_ack(); // FIXIT-L SYN's seen with ack > 0 and ACK flag not set... if ( tsd.are_packet_flags_set(PKT_STREAM_ORDER_OK) ) @@ -65,54 +70,96 @@ inline void TraceEvent(const TcpSegmentDescriptor& tsd, uint32_t txd, uint32_t r else if ( tsd.are_packet_flags_set(PKT_STREAM_ORDER_BAD) ) order = " (oos)"; - uint32_t rseq = ( txd ) ? tsd.get_seq() - txd : tsd.get_seq(); - uint32_t rack = ( rxd ) ? tsd.get_ack() - rxd : tsd.get_ack(); - fprintf(stdout, "\n" FMTu64("-3") " %s %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4hu%s\n", + uint32_t rseq = txd ? tsd.get_seq() - txd : tsd.get_seq(); + uint32_t rack = rxd ? tsd.get_ack() - rxd : tsd.get_ack(); + + debug_logf(stream_tcp_trace, TRACE_STATE, p, + FMTu64("-3") " %s %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4hu%s\n", tsd.get_packet_number(), meta_ack_marker, flags, h->th_flags, rseq, rack, tsd.get_wnd(), tsd.get_len(), order); } -inline void TraceSession(const snort::Flow* flow) +inline void TraceSession(const snort::Flow* flow, const snort::Packet* p) { - fprintf(stdout, " LWS: ST=0x%x SF=0x%x CP=%hu SP=%hu\n", (unsigned)flow->session_state, + debug_logf(stream_tcp_trace, TRACE_STATE, p, + " LWS: ST=0x%x SF=0x%x CP=%hu SP=%hu\n", (unsigned)flow->session_state, flow->ssn_state.session_flags, flow->client_port, flow->server_port); } -inline void TraceState(TcpStreamTracker& a, TcpStreamTracker& b, const char* s) +inline void TraceSegments(const TcpReassemblerPolicy& trp, const snort::Packet* p) +{ + const TcpSegmentNode* tsn = trp.trs.sos.seglist.head; + uint32_t sx = trp.trs.tracker->r_win_base; + unsigned segs = 0; + unsigned bytes = 0; + std::stringstream ss; + + if ( !trace_enabled(stream_tcp_trace, TRACE_SEGMENTS) ) + return; + + while ( tsn ) + { + if ( SEQ_LT(sx, tsn->i_seq) ) + ss << " +" << tsn->i_seq - sx; + else if ( SEQ_GT(sx, tsn->i_seq) ) + ss << " -" << sx - tsn->i_seq; + + ss << " " << tsn->i_len; + + if ( tsn->c_len and tsn->c_len != tsn->i_len ) + { + ss << "(" << tsn->offset << "|" << tsn->c_len; + ss << "|" << tsn->i_len-tsn->offset-tsn->c_len << ")"; + } + + segs++; + bytes += tsn->i_len; + sx = tsn->i_seq + tsn->i_len; + tsn = tsn->next; + } + + if ( !ss.str().empty() ) + debug_logf(stream_tcp_trace, TRACE_SEGMENTS, p, " %s\n", ss.str().c_str()); + + assert(trp.trs.sos.seg_count == segs); + assert(trp.trs.sos.seg_bytes_logical == bytes); +} + +inline void TraceState(const TcpStreamTracker& a, const TcpStreamTracker& b, const char* s, + const snort::Packet* p) { uint32_t ua = a.get_snd_una() ? LCL(a, get_snd_una) : 0; uint32_t ns = a.get_snd_nxt() ? LCL(a, get_snd_nxt) : 0; - fprintf(stdout, - " %s ST=%s UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ISS=%-4u IRS=%-4u ", + debug_logf(stream_tcp_trace, TRACE_STATE, p, + " %s ST=%s UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ISS=%-4u IRS=%-4u\n", s, statext[a.get_tcp_state()], ua, ns, a.get_snd_wnd( ), RMT(a, rcv_nxt, b), RMT(a, r_win_base, b), a.get_iss(), a.get_irs()); - fprintf(stdout, "\n"); - unsigned paf = ( a.is_splitter_paf() ) ? 2 : 0; + unsigned paf = a.is_splitter_paf() ? 2 : 0; unsigned fpt = a.get_flush_policy() ? 192 : 0; - fprintf(stdout, " FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u", + debug_logf(stream_tcp_trace, TRACE_STATE, p, + " FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u\n", flushxt[a.get_flush_policy() + paf], fpt, a.reassembler.get_seg_count(), a.reassembler.get_flush_count(), a.reassembler.get_seg_bytes_logical(), a.reassembler.get_seglist_base_seq() - b.get_iss()); - if ( s5_trace_enabled == 2 ) - a.reassembler.trace_segments(); - - fprintf(stdout, "\n"); + TraceSegments(a.reassembler, p); } -inline void TraceTCP(const TcpSegmentDescriptor& tsd) +void S5TraceTCP(const TcpSegmentDescriptor& tsd, const snort::Packet* p) { TcpSession* ssn = (TcpSession*)tsd.get_flow()->session; assert(ssn); - TcpStreamTracker& srv = ssn->server; - TcpStreamTracker& cli = ssn->client; + const TcpStreamTracker& srv = ssn->server; + const TcpStreamTracker& cli = ssn->client; - const char* cdir = "?", * sdir = "?"; - uint32_t txd = 0, rxd = 0; + const char* cdir = "?"; + const char* sdir = "?"; + uint32_t txd = 0; + uint32_t rxd = 0; if ( tsd.is_packet_from_client() ) { @@ -129,37 +176,14 @@ inline void TraceTCP(const TcpSegmentDescriptor& tsd) rxd = srv.get_irs(); } - TraceEvent(tsd, txd, rxd); + TraceEvent(tsd, txd, rxd, p); if ( ssn->lws_init ) - TraceSession(tsd.get_flow()); - - TraceState(cli, srv, cdir); - TraceState(srv, cli, sdir); -} - -inline void S5TraceTCP(const TcpSegmentDescriptor& tsd) -{ - if ( !s5_trace_enabled ) - return; + TraceSession(tsd.get_flow(), p); - if ( s5_trace_enabled < 0 ) - { - const char* s5t = getenv("S5_TRACE"); - - if ( !s5t ) - { - s5_trace_enabled = 0; - return; - } - - // no error checking required - atoi() is sufficient - s5_trace_enabled = atoi(s5t); - } - - TraceTCP(tsd); + TraceState(cli, srv, cdir, p); + TraceState(srv, cli, sdir, p); } -#endif // REG_TEST -#endif +#endif // DEBUG_MSGS diff --git a/src/stream/tcp/tcp_trace.h b/src/stream/tcp/tcp_trace.h new file mode 100644 index 000000000..d035b62fc --- /dev/null +++ b/src/stream/tcp/tcp_trace.h @@ -0,0 +1,42 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// tcp_trace.h author Oleksii Khomiakovskyi + +#ifndef TCP_TRACE_H +#define TCP_TRACE_H + +#include "main/thread.h" + +namespace snort +{ +struct Packet; +} + +class TcpSegmentDescriptor; + +enum +{ + TRACE_SEGMENTS = 0, + TRACE_STATE, +}; + +void S5TraceTCP(const TcpSegmentDescriptor&, const snort::Packet*); + +#endif +