// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_debug_trace.h author davis mcpherson <davmcphe@cisco.com>
-// Created on: Aug 5, 2015
+// tcp_trace.cc author Oleksii Khomiakovskyi <okhomiak@cisco.com>
+// based on work by davis mcpherson <davmcphe@cisco.com>
-#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())
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) )
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() )
{
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