#define STREAM_STATE_TIMEDOUT 0x0080
#define STREAM_STATE_UNREACH 0x0100
#define STREAM_STATE_CLOSED 0x0800
-#define STREAM_STATE_IGNORE 0x1000
-#define STREAM_STATE_NO_PICKUP 0x2000
-#define STREAM_STATE_BLOCK_PENDING 0x4000
+#define STREAM_STATE_BLOCK_PENDING 0x1000
class BitOp;
class Session;
inline uint16_t raw_src_port() const
{ return th_sport; }
- inline uint16_t raw_dst_len() const
+ inline uint16_t raw_dst_port() const
{ return th_dport; }
inline uint32_t raw_seq() const
}
bool has_expired()
- {
- return expired;
- }
+ { return expired; }
TcpStreamTracker& get_tracker() const { return tracker; }
DAQ_Msg_h get_daq_msg() const { return daq_msg; }
// Return the timeout in milliseconds.
uint32_t get_timeout() const
- {
- return timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
- }
+ { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
- bool empty() const { return q.empty(); }
+ bool empty() const
+ { return q.empty(); }
// This must be called at reload time only, with now = reload time.
// Return true if, upon exit, there are expired packets in the queue.
//-------------------------------------------------------------------------
static Module* size_mod_ctor()
-{
- return new SizeModule;
-}
+{ return new SizeModule; }
static void mod_dtor(Module* m)
-{
- delete m;
-}
+{ delete m; }
static IpsOption* size_ctor(Module* p, OptTreeNode*)
{
}
static void opt_dtor(IpsOption* p)
-{
- delete p;
-}
+{ delete p; }
static const IpsApi size_api =
{
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// segment_overlap_editor.cc author davis mcpherson <davmcphe@@cisco.com>
+// segment_overlap_editor.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Oct 11, 2015
#ifdef HAVE_CONFIG_H
#include "segment_overlap_editor.h"
+#include "detection/detection_engine.h"
#include "log/messages.h"
-#include "packet_tracer/packet_tracer.h"
#include "tcp_module.h"
#include "tcp_normalizers.h"
using namespace snort;
-static void set_retransmit_flag(Packet* p)
-{
- if ( PacketTracer::is_active() )
- {
- PacketTracer::log("Packet was retransmitted and %s from the retry queue.\n",
- p->is_retry() ? "is" : "is not");
- }
-
- // Mark the packet as being a re-transmit if it's not from the retry
- // queue. That way we can avoid adding re-transmitted packets to
- // the retry queue.
- if ( !p->is_retry() )
- p->packet_flags |= PKT_RETRANSMIT;
-}
-
void SegmentOverlapState::init_sos(TcpSession* ssn, StreamPolicy pol)
{
session = ssn;
this->left = left;
this->right = right;
- seq = tsd.get_seg_seq();
+ seq = tsd.get_seq();
seq_end = tsd.get_end_seq();
- len = tsd.get_seg_len();
+ len = tsd.get_len();
overlap = 0;
slide = 0;
trunc_len = 0;
rdata = tsd.get_pkt()->data;
- rsize = tsd.get_seg_len();
- rseq = tsd.get_seg_seq();
+ rsize = tsd.get_len();
+ rseq = tsd.get_seq();
keep_segment = true;
}
// Don't want to count retransmits as overlaps or do anything
// else with them. Account for retransmits of multiple PDUs
// in one segment.
- bool* pb = (trs.sos.rseq == trs.sos.tsd->get_seg_seq()) ? full_retransmit : nullptr;
+ bool* pb = (trs.sos.rseq == trs.sos.tsd->get_seq()) ? full_retransmit : nullptr;
if ( trs.sos.right->is_retransmit(trs.sos.rdata, trs.sos.rsize,
trs.sos.rseq, trs.sos.right->i_len, pb) )
{
- set_retransmit_flag(trs.sos.tsd->get_pkt());
+ trs.sos.tsd->set_retransmit_flag();
if ( !(*full_retransmit) )
{
if ( trs.sos.rsize == 0 )
{
// All data was retransmitted
- trs.sos.session->retransmit_process(trs.sos.tsd->get_pkt());
+ snort::DetectionEngine::disable_content(trs.sos.tsd->get_pkt());
trs.sos.keep_segment = false;
}
return false;
}
-int SegmentOverlapEditor::eval_left(TcpReassemblerState& trs)
+void SegmentOverlapEditor::eval_left(TcpReassemblerState& trs)
{
- int rc = STREAM_INSERT_OK;
-
if ( trs.sos.left )
- rc = insert_left_overlap(trs);
-
- return rc;
+ insert_left_overlap(trs);
}
-int SegmentOverlapEditor::eval_right(TcpReassemblerState& trs)
+void SegmentOverlapEditor::eval_right(TcpReassemblerState& trs)
{
while ( trs.sos.right && SEQ_LT(trs.sos.right->i_seq, trs.sos.seq_end) )
{
// Treat sequence number overlap as a retransmission,
// only check right side since left side happens rarely
- trs.sos.session->retransmit_handle(trs.sos.tsd->get_pkt());
-
+ trs.sos.session->flow->call_handlers(trs.sos.tsd->get_pkt(), false);
if ( trs.sos.overlap < trs.sos.right->i_len )
{
if ( trs.sos.right->is_retransmit(trs.sos.rdata, trs.sos.rsize,
trs.sos.rseq, trs.sos.right->i_len, nullptr) )
{
- set_retransmit_flag(trs.sos.tsd->get_pkt());
-
// All data was retransmitted
- trs.sos.session->retransmit_process(trs.sos.tsd->get_pkt());
+ trs.sos.tsd->set_retransmit_flag();
+ snort::DetectionEngine::disable_content(trs.sos.tsd->get_pkt());
trs.sos.keep_segment = false;
}
else
tcpStats.overlaps++;
trs.sos.overlap_count++;
- int rc = insert_full_overlap(trs);
- if ( rc != STREAM_INSERT_OK )
- return rc;
+ insert_full_overlap(trs);
}
}
-
- return STREAM_INSERT_OK;
}
void SegmentOverlapEditor::drop_old_segment(TcpReassemblerState& trs)
delete_reassembly_segment(trs, drop_seg);
}
-int SegmentOverlapEditor::left_overlap_keep_first(TcpReassemblerState& trs)
+void SegmentOverlapEditor::left_overlap_keep_first(TcpReassemblerState& trs)
{
// NOTE that overlap will always be less than left->size since
// seq is always greater than left->seq
assert(SEQ_GT(trs.sos.seq, trs.sos.left->i_seq));
- trs.sos.len = trs.sos.tsd->get_seg_len();
+ trs.sos.len = trs.sos.tsd->get_len();
trs.sos.overlap = trs.sos.left->i_seq + trs.sos.left->i_len - trs.sos.seq;
if ( trs.sos.len < trs.sos.overlap )
{
if (trs.sos.tcp_ips_data == NORM_MODE_ON)
{
- unsigned offset = trs.sos.tsd->get_seg_seq() - trs.sos.left->i_seq;
- memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data),
- trs.sos.left->data + offset, trs.sos.tsd->get_seg_len());
- trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+ unsigned offset = trs.sos.tsd->get_seq() - trs.sos.left->i_seq;
+ trs.sos.tsd->rewrite_payload(0, trs.sos.left->data + offset);
}
tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
}
{
if ( trs.sos.tcp_ips_data == NORM_MODE_ON )
{
- unsigned offset = trs.sos.tsd->get_seg_seq() - trs.sos.left->i_seq;
- unsigned length = trs.sos.left->i_seq + trs.sos.left->i_len -
- trs.sos.tsd->get_seg_seq();
- memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data),
- trs.sos.left->data + offset, length);
- trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+ unsigned offset = trs.sos.tsd->get_seq() - trs.sos.left->i_seq;
+ unsigned length =
+ trs.sos.left->i_seq + trs.sos.left->i_len - trs.sos.tsd->get_seq();
+ trs.sos.tsd->rewrite_payload(0, trs.sos.left->data + offset, length);
}
tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
trs.sos.seq += trs.sos.overlap;
}
-
- return STREAM_INSERT_OK;
}
-int SegmentOverlapEditor::left_overlap_trim_first(TcpReassemblerState& trs)
+void SegmentOverlapEditor::left_overlap_trim_first(TcpReassemblerState& trs)
{
assert(SEQ_GT(trs.sos.seq, trs.sos.left->i_seq));
- trs.sos.len = trs.sos.tsd->get_seg_len();
+ trs.sos.len = trs.sos.tsd->get_len();
trs.sos.overlap = trs.sos.left->i_seq + trs.sos.left->i_len - trs.sos.seq;
if ( trs.sos.overlap > 0 )
trs.sos.seg_bytes_logical -= trs.sos.overlap;
}
}
-
- return STREAM_INSERT_OK;
}
-int SegmentOverlapEditor::left_overlap_keep_last(TcpReassemblerState& trs)
+void SegmentOverlapEditor::left_overlap_keep_last(TcpReassemblerState& trs)
{
assert(SEQ_GT(trs.sos.seq, trs.sos.left->i_seq));
- trs.sos.len = trs.sos.tsd->get_seg_len();
+ trs.sos.len = trs.sos.tsd->get_len();
trs.sos.overlap = trs.sos.left->i_seq + trs.sos.left->i_len - trs.sos.seq;
if ( trs.sos.overlap > 0 )
* Need to duplicate left. Adjust that seq by + (seq + len) and
* size by - (seq + len - left->i_seq).
*/
- int rc = dup_reassembly_segment(trs, trs.sos.left, &trs.sos.right);
-
- if ( rc != STREAM_INSERT_OK )
- return rc;
+ dup_reassembly_segment(trs, trs.sos.left, &trs.sos.right);
- trs.sos.left->c_len -= ( int16_t )trs.sos.overlap;
- trs.sos.left->i_len -= ( int16_t )trs.sos.overlap;
+ trs.sos.left->c_len -= (int16_t)trs.sos.overlap;
+ trs.sos.left->i_len -= (int16_t)trs.sos.overlap;
trs.sos.right->i_seq = trs.sos.seq + trs.sos.len;
trs.sos.right->c_seq = trs.sos.right->i_seq;
- uint16_t delta = ( int16_t )( trs.sos.right->i_seq - trs.sos.left->i_seq );
+ uint16_t delta = (int16_t)(trs.sos.right->i_seq - trs.sos.left->i_seq);
trs.sos.right->c_len -= delta;
trs.sos.right->i_len -= delta;
trs.sos.right->offset += delta;
else
{
trs.sos.left->c_len -= (int16_t)trs.sos.overlap;
- trs.sos.left->i_len -= ( int16_t )trs.sos.overlap;
+ trs.sos.left->i_len -= (int16_t)trs.sos.overlap;
trs.sos.seg_bytes_logical -= trs.sos.overlap;
}
}
-
- return STREAM_INSERT_OK;
}
void SegmentOverlapEditor::right_overlap_truncate_existing(TcpReassemblerState& trs)
{
if (trs.sos.tcp_ips_data == NORM_MODE_ON)
{
- unsigned offset = trs.sos.right->i_seq - trs.sos.tsd->get_seg_seq();
- unsigned length = trs.sos.tsd->get_seg_seq() + trs.sos.tsd->get_seg_len() -
- trs.sos.right->i_seq;
- memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data) + offset,
- trs.sos.right->data, length);
- trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+ unsigned offset = trs.sos.right->i_seq - trs.sos.tsd->get_seq();
+ unsigned length =
+ trs.sos.tsd->get_seq() + trs.sos.tsd->get_len() - trs.sos.right->i_seq;
+ trs.sos.tsd->rewrite_payload(offset, trs.sos.right->data, length);
}
tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
// REASSEMBLY_POLICY_FIRST:
// REASSEMBLY_POLICY_VISTA:
-int SegmentOverlapEditor::full_right_overlap_truncate_new(TcpReassemblerState& trs)
+void SegmentOverlapEditor::full_right_overlap_truncate_new(TcpReassemblerState& trs)
{
if ( trs.sos.tcp_ips_data == NORM_MODE_ON )
{
- unsigned offset = trs.sos.right->i_seq - trs.sos.tsd->get_seg_seq();
- memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data) + offset,
- trs.sos.right->data, trs.sos.right->i_len);
- trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+ unsigned offset = trs.sos.right->i_seq - trs.sos.tsd->get_seq();
+ trs.sos.tsd->rewrite_payload(offset, trs.sos.right->data, trs.sos.right->i_len);
}
tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
/* Adjusted seq is fully overlapped */
if ( SEQ_EQ(trs.sos.seq, trs.sos.seq_end) )
- return STREAM_INSERT_OK;
+ return;
}
else
{
/* insert this one, and see if we need to chunk it up
Adjust slide so that is correct relative to orig seq */
- trs.sos.slide = trs.sos.seq - trs.sos.tsd->get_seg_seq();
- int rc = add_reassembly_segment(trs, *trs.sos.tsd, trs.sos.len, trs.sos.slide,
+ trs.sos.slide = trs.sos.seq - trs.sos.tsd->get_seq();
+ add_reassembly_segment(trs, *trs.sos.tsd, trs.sos.len, trs.sos.slide,
trs.sos.trunc_len, trs.sos.seq, trs.sos.left);
- if ( rc != STREAM_INSERT_OK )
- return rc;
// Set seq to end of right since overlap was greater than or equal to right->size and
// inserted seq has been truncated to beginning of right and reset trunc length to 0
trs.sos.right = trs.sos.right->next;
trs.sos.trunc_len = 0;
}
-
- return STREAM_INSERT_OK;
}
// REASSEMBLY_POLICY_WINDOWS:
// REASSEMBLY_POLICY_WINDOWS2K3:
// REASSEMBLY_POLICY_BSD:
// REASSEMBLY_POLICY_MACOS:
-int SegmentOverlapEditor::full_right_overlap_os1(TcpReassemblerState& trs)
+void SegmentOverlapEditor::full_right_overlap_os1(TcpReassemblerState& trs)
{
if ( SEQ_GEQ(trs.sos.seq_end, trs.sos.right->i_seq + trs.sos.right->i_len) and
SEQ_LT(trs.sos.seq, trs.sos.right->i_seq) )
drop_old_segment(trs);
}
else
- {
- int rc = full_right_overlap_truncate_new(trs);
- if ( rc != STREAM_INSERT_OK )
- return rc;
- }
-
- return STREAM_INSERT_OK;
+ full_right_overlap_truncate_new(trs);
}
// REASSEMBLY_POLICY_LINUX:
// REASSEMBLY_POLICY_HPUX10:
// REASSEMBLY_POLICY_IRIX:
-int SegmentOverlapEditor::full_right_overlap_os2(TcpReassemblerState& trs)
+void SegmentOverlapEditor::full_right_overlap_os2(TcpReassemblerState& trs)
{
if ( SEQ_GEQ(trs.sos.seq_end, trs.sos.right->i_seq + trs.sos.right->i_len) and
SEQ_LT(trs.sos.seq, trs.sos.right->i_seq) )
drop_old_segment(trs);
}
else
- {
- int rc = full_right_overlap_truncate_new(trs);
- if ( rc != STREAM_INSERT_OK )
- return rc;
- }
-
- return STREAM_INSERT_OK;
+ full_right_overlap_truncate_new(trs);
}
// REASSEMBLY_POLICY_HPUX11:
// REASSEMBLY_POLICY_SOLARIS:
-int SegmentOverlapEditor::full_right_overlap_os3(TcpReassemblerState& trs)
+void SegmentOverlapEditor::full_right_overlap_os3(TcpReassemblerState& trs)
{
// If this packet is wholly overlapping and the same size as a previous one and we have not
// received the one immediately preceding, we take the FIRST.
trs.sos.right = trs.sos.right->next;
}
else
- {
drop_old_segment(trs);
- }
-
- return STREAM_INSERT_OK;
}
// REASSEMBLY_POLICY_OLD_LINUX:
// REASSEMBLY_POLICY_LAST:
-int SegmentOverlapEditor::full_right_overlap_os4(TcpReassemblerState& trs)
-{
- drop_old_segment(trs);
- return STREAM_INSERT_OK;
-}
+void SegmentOverlapEditor::full_right_overlap_os4(TcpReassemblerState& trs)
+{ drop_old_segment(trs); }
-int SegmentOverlapEditor::full_right_overlap_os5(TcpReassemblerState& trs)
+void SegmentOverlapEditor::full_right_overlap_os5(TcpReassemblerState& trs)
{
- return full_right_overlap_truncate_new(trs);
+ full_right_overlap_truncate_new(trs);
}
void SegmentOverlapEditor::print(TcpReassemblerState& trs)
LogMessage(" seg_bytes_total: %d\n", trs.sos.seg_bytes_total);
LogMessage(" seg_bytes_logical: %d\n", trs.sos.seg_bytes_logical);
}
-
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// segment_overlap_editor.h author davis mcpherson <davmcphe@@cisco.com>
+// segment_overlap_editor.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Oct 11, 2015
#ifndef SEGMENT_OVERLAP_EDITOR_H
class TcpSession;
class TcpStreamTracker;
-#define STREAM_INSERT_OK 0 // FIXIT-RC replace with bool CRC: if useful else just delete
-
struct SegmentOverlapState
{
TcpSession* session;
SegmentOverlapEditor() { }
virtual ~SegmentOverlapEditor() = default;
- int eval_left(TcpReassemblerState&);
- int eval_right(TcpReassemblerState&);
+ void eval_left(TcpReassemblerState&);
+ void eval_right(TcpReassemblerState&);
virtual bool is_segment_retransmit(TcpReassemblerState&, bool*);
virtual void drop_old_segment(TcpReassemblerState&);
- virtual int left_overlap_keep_first(TcpReassemblerState&);
- virtual int left_overlap_trim_first(TcpReassemblerState&);
- virtual int left_overlap_keep_last(TcpReassemblerState&);
+ virtual void left_overlap_keep_first(TcpReassemblerState&);
+ virtual void left_overlap_trim_first(TcpReassemblerState&);
+ virtual void left_overlap_keep_last(TcpReassemblerState&);
virtual void right_overlap_truncate_existing(TcpReassemblerState&);
virtual void right_overlap_truncate_new(TcpReassemblerState&);
- virtual int full_right_overlap_truncate_new(TcpReassemblerState&);
- virtual int full_right_overlap_os1(TcpReassemblerState&);
- virtual int full_right_overlap_os2(TcpReassemblerState&);
- virtual int full_right_overlap_os3(TcpReassemblerState&);
- virtual int full_right_overlap_os4(TcpReassemblerState&);
- virtual int full_right_overlap_os5(TcpReassemblerState&);
-
- virtual int insert_left_overlap(TcpReassemblerState&) = 0;
+ virtual void full_right_overlap_truncate_new(TcpReassemblerState&);
+ virtual void full_right_overlap_os1(TcpReassemblerState&);
+ virtual void full_right_overlap_os2(TcpReassemblerState&);
+ virtual void full_right_overlap_os3(TcpReassemblerState&);
+ virtual void full_right_overlap_os4(TcpReassemblerState&);
+ virtual void full_right_overlap_os5(TcpReassemblerState&);
+
+ virtual void insert_left_overlap(TcpReassemblerState&) = 0;
virtual void insert_right_overlap(TcpReassemblerState&) = 0;
- virtual int insert_full_overlap(TcpReassemblerState&) = 0;
+ virtual void insert_full_overlap(TcpReassemblerState&) = 0;
- virtual int add_reassembly_segment(
+ virtual void add_reassembly_segment(
TcpReassemblerState&, TcpSegmentDescriptor&, uint16_t, uint32_t,
uint32_t, uint32_t, TcpSegmentNode*) = 0;
- virtual int dup_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*, TcpSegmentNode**) = 0;
+ virtual void dup_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*, TcpSegmentNode**) = 0;
virtual int delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*) = 0;
virtual void print(TcpReassemblerState&);
};
void StreamTcp::show(const SnortConfig*) const
{
- if ( !config )
- return;
-
+ assert( config );
config->show();
}
#include "tcp_reassemblers.h"
#ifndef REG_TEST
-#define S5TraceTCP(pkt, flow, tsd, evt)
+#define S5TraceTCP(tsd)
#else
-#define LCL(p, x) ((p)->x() - (p)->get_iss())
-#define RMT(p, x, q) ((p)->x - ((q) ? (q)->get_iss() : 0))
+#define LCL(p, x) ((p).x() - (p).get_iss())
+#define RMT(p, x, q) ((p).x - (q).get_iss())
static const char* const statext[] =
{
static THREAD_LOCAL int s5_trace_enabled = -1; // FIXIT-L should use module trace feature
-inline void TraceEvent(
- const snort::Packet* p, TcpSegmentDescriptor*, uint32_t txd, uint32_t rxd)
+inline void TraceEvent(const TcpSegmentDescriptor& tsd, uint32_t txd, uint32_t rxd)
{
- int i;
char flags[7] = "UAPRSF";
- const snort::tcp::TCPHdr* h = p->ptrs.tcph;
+ const snort::tcp::TCPHdr* h = tsd.get_tcph();
const char* order = "";
+ const char* meta_ack_marker = tsd.is_meta_ack_packet() ? "M" : " ";
if (!h)
return;
- for (i = 0; i < 6; i++)
+ for (int i = 0; i < 6; i++)
if (!((1 << (5 - i)) & h->th_flags))
flags[i] = '-';
// force relative ack to zero if not conveyed
if (flags[1] != 'A')
- rxd = h->ack(); // FIXIT-L SYN's seen with ack > 0 and ACK flag not set...
+ rxd = tsd.get_ack(); // FIXIT-L SYN's seen with ack > 0 and ACK flag not set...
- if (p->packet_flags & PKT_STREAM_ORDER_OK)
+ if ( tsd.are_packet_flags_set(PKT_STREAM_ORDER_OK) )
order = " (ins)";
- else if (p->packet_flags & PKT_STREAM_ORDER_BAD)
+ else if ( tsd.are_packet_flags_set(PKT_STREAM_ORDER_BAD) )
order = " (oos)";
- uint32_t rseq = ( txd ) ? h->seq() - txd : h->seq();
- uint32_t rack = ( rxd ) ? h->ack() - rxd : h->ack();
- fprintf(stdout, "\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4hu Len=%-4hu%s\n",
- //"\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u End=%-4u%s\n",
- p->context->packet_number, flags, h->th_flags, rseq, rack, h->win(), p->dsize, order);
+ 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",
+ 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* lws)
+inline void TraceSession(const snort::Flow* flow)
{
- fprintf(stdout, " LWS: ST=0x%x SF=0x%x CP=%hu SP=%hu\n", (unsigned)lws->session_state,
- lws->ssn_state.session_flags, lws->client_port, lws->server_port);
+ fprintf(stdout, " 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 TraceState(TcpStreamTracker& a, TcpStreamTracker& b, const char* s)
{
- 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;
+ 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 ",
- 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());
+ " %s ST=%s UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ISS=%-4u IRS=%-4u ",
+ 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->splitter and a->splitter->is_paf()) ? 2 : 0;
- unsigned fpt = a->flush_policy ? 192 : 0;
+ unsigned paf = (a.splitter and a.splitter->is_paf()) ? 2 : 0;
+ unsigned fpt = a.flush_policy ? 192 : 0;
- fprintf(stdout, " FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
- flushxt[a->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());
+ fprintf(stdout, " FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
+ flushxt[a.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();
+ if ( s5_trace_enabled == 2 )
+ a.reassembler.trace_segments();
fprintf(stdout, "\n");
}
-inline void TraceTCP(
- const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
+inline void TraceTCP(const TcpSegmentDescriptor& tsd)
{
- TcpSession* ssn = (TcpSession*)lws->session;
- TcpStreamTracker* srv = ssn ? &ssn->server : nullptr;
- TcpStreamTracker* cli = ssn ? &ssn->client : nullptr;
+ TcpSession* ssn = (TcpSession*)tsd.get_flow()->session;
+ assert(ssn);
+ TcpStreamTracker& srv = ssn->server;
+ TcpStreamTracker& cli = ssn->client;
const char* cdir = "?", * sdir = "?";
uint32_t txd = 0, rxd = 0;
- if (p->is_from_server())
+ if ( tsd.is_packet_from_client() )
+ {
+ sdir = "SRV<";
+ cdir = "CLI>";
+ txd = cli.get_iss();
+ rxd = cli.get_irs();
+ }
+ else
{
sdir = "SRV>";
cdir = "CLI<";
-
- txd = srv->get_iss();
- rxd = srv->get_irs();
+ txd = srv.get_iss();
+ rxd = srv.get_irs();
}
- else if ( p->is_from_client() )
- {
- sdir = "SRV<";
- cdir = "CLI>";
- txd = cli->get_iss();
- rxd = cli->get_irs();
- }
- TraceEvent(p, tsd, txd, rxd);
+ TraceEvent(tsd, txd, rxd);
- if ( lws && ssn->lws_init)
- TraceSession(lws);
+ if ( ssn->lws_init )
+ TraceSession(tsd.get_flow());
- if (lws && !event)
- {
- TraceState(cli, srv, cdir);
- TraceState(srv, cli, sdir);
- }
+ TraceState(cli, srv, cdir);
+ TraceState(srv, cli, sdir);
}
-inline void S5TraceTCP(
- const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
+inline void S5TraceTCP(const TcpSegmentDescriptor& tsd)
{
- if (!s5_trace_enabled)
+ if ( !s5_trace_enabled )
return;
- if (s5_trace_enabled < 0)
+ if ( s5_trace_enabled < 0 )
{
const char* s5t = getenv("S5_TRACE");
- if (!s5t)
+ if ( !s5t )
{
s5_trace_enabled = 0;
return;
s5_trace_enabled = atoi(s5t);
}
- TraceTCP(p, lws, tsd, event);
+ TraceTCP(tsd);
}
#endif // REG_TEST
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_event_logger.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_event_logger.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifdef HAVE_CONFIG_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_event_logger.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_event_logger.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifndef TCP_EVENT_LOGGER_H
{ CountType::SUM, "syn_acks", "number of syn-ack packets" },
{ CountType::SUM, "resets", "number of reset packets" },
{ CountType::SUM, "fins", "number of fin packets" },
+ { CountType::SUM, "meta_acks", "number of meta acks processed" },
{ CountType::SUM, "packets_held", "number of packets held" },
{ CountType::SUM, "held_packet_rexmits", "number of retransmits of held packets" },
{ CountType::SUM, "held_packets_dropped", "number of held packets dropped" },
PegCount syn_acks;
PegCount resets;
PegCount fins;
+ PegCount meta_acks;
PegCount total_packets_held;
PegCount held_packet_rexmits;
PegCount held_packets_dropped;
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_normalization.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_normalization.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 31, 2015
#ifdef HAVE_CONFIG_H
#include "tcp_normalizer.h"
-#include "packet_io/active.h"
-
#include "tcp_stream_session.h"
#include "tcp_stream_tracker.h"
{
if (mode == NORM_MODE_ON)
{
- uint16_t fat = tsd.get_seg_len() - max;
- tsd.set_seg_len(max);
- tsd.get_pkt()->packet_flags |= PKT_RESIZED;
+ uint16_t fat = tsd.get_len() - max;
+ tsd.set_len(max);
+ tsd.set_packet_flags(PKT_RESIZED);
tsd.set_end_seq(tsd.get_end_seq() - fat);
}
{
// set raw option bytes to nops
memset((void*)opt, (uint32_t)tcp::TcpOptCode::NOP, tcp::TCPOLEN_TIMESTAMP);
- tsd.get_pkt()->packet_flags |= PKT_MODIFIED;
+ tsd.set_packet_flags(PKT_MODIFIED);
return true;
}
if (mode == NORM_MODE_ON)
{
- Packet* p = tsd.get_pkt();
- p->active->drop_packet(p);
- p->active->set_drop_reason("stream");
+ tsd.drop_packet();
return true;
}
void TcpNormalizer::trim_syn_payload(
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tsd.get_seg_len() > max)
+ if (tsd.get_len() > max)
trim_payload(tns, tsd, max, (NormMode)tns.trim_syn, PC_TCP_TRIM_SYN);
}
void TcpNormalizer::trim_rst_payload(
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tsd.get_seg_len() > max)
+ if (tsd.get_len() > max)
trim_payload(tns, tsd, max, (NormMode)tns.trim_rst, PC_TCP_TRIM_RST);
}
void TcpNormalizer::trim_win_payload(
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tsd.get_seg_len() > max)
+ if (tsd.get_len() > max)
trim_payload(tns, tsd, max, (NormMode)tns.trim_win, PC_TCP_TRIM_WIN);
}
void TcpNormalizer::trim_mss_payload(
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tsd.get_seg_len() > max)
+ if (tsd.get_len() > max)
trim_payload(tns, tsd, max, (NormMode)tns.trim_mss, PC_TCP_TRIM_MSS);
}
}
void TcpNormalizer::ecn_stripper(
- TcpNormalizerState& tns, Packet* p)
+ TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
{
- if (!tns.session->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
+ if (!tns.session->ecn && (tcph->th_flags & (TH_ECE | TH_CWR)))
{
if (tns.strip_ecn == NORM_MODE_ON)
{
- (const_cast<tcp::TCPHdr*>(p->ptrs.tcph))->th_flags &= ~(TH_ECE | TH_CWR);
- p->packet_flags |= PKT_MODIFIED;
+ (const_cast<tcp::TCPHdr*>(tcph))->th_flags &= ~(TH_ECE | TH_CWR);
+ tsd.set_packet_flags(PKT_MODIFIED);
}
tcp_norm_stats[PC_TCP_ECN_SSN][tns.strip_ecn]++;
uint32_t TcpNormalizer::get_tcp_timestamp(
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, bool strip)
{
+ if ( tsd.is_meta_ack_packet() )
+ return TF_NONE;
+
if ( tsd.get_pkt()->ptrs.decode_flags & DECODE_TCP_TS )
{
tcp::TcpOptIterator iter(tsd.get_tcph(), tsd.get_pkt() );
if (!stripped)
{
- tsd.set_ts(extract_32bits(opt.data) );
+ tsd.set_timestamp(extract_32bits(opt.data) );
return TF_TSTAMP;
}
}
}
}
- tsd.set_ts(0);
+ tsd.set_timestamp(0);
return TF_NONE;
}
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
{
// FIXIT-M check for rcv_nxt == 0 is hack for uninitialized rcv_nxt
- if ( ( tns.tracker->rcv_nxt == 0 ) || SEQ_GEQ(tsd.get_seg_seq(), tns.tracker->rcv_nxt) )
+ if ( ( tns.tracker->rcv_nxt == 0 ) || SEQ_GEQ(tsd.get_seq(), tns.tracker->rcv_nxt) )
return true;
return false;
if ( SEQ_GEQ(tsd.get_end_seq(), tns.tracker->r_win_base))
{
// reset must be admitted when window closed
- if (SEQ_LEQ(tsd.get_seg_seq(), tns.tracker->r_win_base + get_stream_window(tns, tsd)))
+ if (SEQ_LEQ(tsd.get_seq(), tns.tracker->r_win_base + get_stream_window(tns, tsd)))
return true;
}
uint32_t expected_seq = tns.tracker->rcv_nxt + tns.tracker->get_fin_seq_adjust();
// FIXIT-M check for rcv_nxt == 0 is hack for uninitialized rcv_nxt
- if ( ( tns.tracker->rcv_nxt == 0 ) || SEQ_EQ(tsd.get_seg_seq(), expected_seq) )
+ if ( ( tns.tracker->rcv_nxt == 0 ) || SEQ_EQ(tsd.get_seq(), expected_seq) )
return true;
return false;
TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
{
const uint32_t peer_ts_last = tns.peer_tracker->get_ts_last();
- if ( peer_ts_last && ( ( (int)( ( tsd.get_ts() - peer_ts_last ) + tns.paws_ts_fudge ) ) < 0 ) )
+ if ( peer_ts_last && ( ( (int)( ( tsd.get_timestamp() - peer_ts_last ) + tns.paws_ts_fudge ) ) < 0 ) )
{
if ( tsd.get_pkt()->is_retry() )
{
// Retry packets can legitimately have old timestamps
// in TCP options (if a re-transmit comes in before
// the retry) so don't consider it an error.
- tsd.set_ts(tns.peer_tracker->get_ts_last());
+ tsd.set_timestamp(tns.peer_tracker->get_ts_last());
return ACTION_NOTHING;
}
else
}
}
else if ( ( tns.peer_tracker->get_ts_last() != 0 )
- && ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec > tns.peer_tracker->get_ts_last_packet() +
+ && ( ( uint32_t )tsd.get_packet_timestamp() > tns.peer_tracker->get_ts_last_packet() +
PAWS_24DAYS ) )
{
/* this packet is from way too far into the future */
tns.session->tel.set_tcp_event(EVENT_NO_TIMESTAMP);
/* Ignore the timestamp for this first packet, next one will checked. */
- if ( tns.session->config->policy == StreamPolicy::OS_SOLARIS )
+ if ( tns.session->tcp_config->policy == StreamPolicy::OS_SOLARIS )
tns.tracker->clear_tf_flags(TF_TSTAMP);
packet_dropper(tns, tsd, NORM_TCP_OPT);
if (!(tns.peer_tracker->get_tf_flags() & TF_TSTAMP))
{
// SYN skipped, may have missed talker's timestamp , so set it now.
- if (tsd.get_ts() == 0)
+ if (tsd.get_timestamp() == 0)
tns.peer_tracker->set_tf_flags(TF_TSTAMP | TF_TSTAMP_ZERO);
else
tns.peer_tracker->set_tf_flags(TF_TSTAMP);
// Only valid to test this if listener is using timestamps. Otherwise, timestamp
// in this packet is not used, regardless of its value.
- if ( ( tns.paws_drop_zero_ts && ( tsd.get_ts() == 0 ) ) &&
+ if ( ( tns.paws_drop_zero_ts && ( tsd.get_timestamp() == 0 ) ) &&
( tns.tracker->get_tf_flags() & TF_TSTAMP ) )
{
tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_normalizer.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_normalizer.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 31, 2015
#ifndef TCP_NORMALIZER_H
virtual void trim_win_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
virtual void trim_mss_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
virtual void ecn_tracker(State&, const snort::tcp::TCPHdr*, bool req3way);
- virtual void ecn_stripper(State&, snort::Packet*);
+ virtual void ecn_stripper(State&, TcpSegmentDescriptor&);
virtual uint32_t get_stream_window(State&, TcpSegmentDescriptor&);
virtual uint32_t get_tcp_timestamp(State&, TcpSegmentDescriptor&, bool strip);
virtual int handle_paws(State&, TcpSegmentDescriptor&);
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_normalizers.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_normalizers.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Sep 22, 2015
#ifdef HAVE_CONFIG_H
/* Windows has some strange behavior here. If the sequence of the reset is the
* next expected sequence, it Resets. Otherwise it ignores the 2nd SYN.
*/
- if ( SEQ_EQ(tsd.get_seg_seq(), listener->rcv_nxt) )
+ if ( SEQ_EQ(tsd.get_seq(), listener->rcv_nxt) )
{
session->flow->set_session_flags(SSNFLAG_RESET);
talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
TcpStreamTracker* talker, const TcpSegmentDescriptor& tsd, TcpStreamSession* session)
{
/* If its not a retransmission of the actual SYN... RESET */
- if ( !SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()) )
+ if ( !SEQ_EQ(tsd.get_seq(), talker->get_iss()) )
{
session->flow->set_session_flags(SSNFLAG_RESET);
talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
if ( talker->get_tf_flags() & TF_TSTAMP_ZERO )
{
talker->clear_tf_flags(TF_TSTAMP_ZERO);
- if ( SEQ_EQ(listener->rcv_nxt, tsd.get_seg_seq() ) )
+ if ( SEQ_EQ(listener->rcv_nxt, tsd.get_seq() ) )
{
// Ignore timestamp for this first packet, save to check on next
- talker->set_ts_last(tsd.get_ts() );
+ talker->set_ts_last(tsd.get_timestamp());
check_ts = false;
}
}
{
/* HPUX 11 ignores timestamps for out of order segments */
if ( (tns.tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tns.tracker->rcv_nxt,
- tsd.get_seg_seq()) )
+ tsd.get_seq()) )
return false;
else
return true;
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_normalizers.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_normalizers.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Sep 22, 2015
#ifndef TCP_NORMALIZERS_H
void ecn_tracker(const snort::tcp::TCPHdr* tcph, bool req3way)
{ norm->ecn_tracker(tns, tcph, req3way); }
- void ecn_stripper(snort::Packet* p)
- { norm->ecn_stripper(tns, p); }
+ void ecn_stripper(TcpSegmentDescriptor& tsd)
+ { norm->ecn_stripper(tns, tsd); }
uint32_t get_stream_window(TcpSegmentDescriptor& tsd)
{ return norm->get_stream_window(tns, tsd); }
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_reassembler.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_reassembler.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 31, 2015
#ifdef HAVE_CONFIG_H
bool TcpReassembler::is_segment_fasttrack(
TcpReassemblerState&, TcpSegmentNode* tail, const TcpSegmentDescriptor& tsd)
{
- if ( SEQ_EQ(tsd.get_seg_seq(), tail->i_seq + tail->i_len) )
+ if ( SEQ_EQ(tsd.get_seq(), tail->i_seq + tail->i_len) )
return true;
return false;
}
-int TcpReassembler::add_reassembly_segment(
+void TcpReassembler::add_reassembly_segment(
TcpReassemblerState& trs, TcpSegmentDescriptor& tsd, uint16_t len, uint32_t slide,
uint32_t trunc_len, uint32_t seq, TcpSegmentNode* left)
{
// Zero size data because of trimming. Don't insert it.
inc_tcp_discards();
trs.tracker->normalizer.trim_win_payload(tsd);
-
- return STREAM_INSERT_OK;
+ return;
}
// FIXIT-L don't allocate overlapped part
tsn->c_len = (uint16_t)new_size;
tsn->i_len = (uint16_t)new_size;
tsn->i_seq = tsn->c_seq = seq;
- tsn->ts = tsd.get_ts();
+ tsn->ts = tsd.get_timestamp();
// FIXIT-M the urgent ptr handling is broken... urg_offset could be set here but currently
// not actually referenced anywhere else. In 2.9.7 the FlushStream function did reference
trs.sos.seg_bytes_logical += tsn->c_len;
trs.sos.total_bytes_queued += tsn->c_len;
- tsd.get_pkt()->packet_flags |= PKT_STREAM_INSERT;
-
- return STREAM_INSERT_OK;
+ tsd.set_packet_flags(PKT_STREAM_INSERT);
}
-int TcpReassembler::dup_reassembly_segment(
+void TcpReassembler::dup_reassembly_segment(
TcpReassemblerState& trs, TcpSegmentNode* left, TcpSegmentNode** retSeg)
{
TcpSegmentNode* tsn = TcpSegmentNode::init(*left);
queue_reassembly_segment(trs, left, tsn);
*retSeg = tsn;
- return STREAM_INSERT_OK;
}
void TcpReassembler::purge_alerts(TcpReassemblerState& trs)
void TcpReassembler::show_rebuilt_packet(TcpReassemblerState& trs, Packet* pkt)
{
- if ( trs.sos.session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
+ if ( trs.sos.session->tcp_config->flags & STREAM_CONFIG_SHOW_PACKETS )
{
// FIXIT-L setting conf here is required because this is called before context start
pkt->context->conf = SnortConfig::get_conf();
EncodeFlags enc_flags = 0;
DAQ_PktHdr_t pkth;
- trs.sos.session->GetPacketHeaderFoo(&pkth, pkt_flags);
+ trs.sos.session->get_packet_header_foo(&pkth, pkt_flags);
PacketManager::format_tcp(enc_flags, p, pdu, PSEUDO_PKT_TCP, &pkth, pkth.opaque);
prep_pdu(trs, trs.sos.session->flow, p, pkt_flags, pdu);
assert(pdu->pkth == pdu->context->pkth);
delete trk.splitter;
trk.splitter = new AtomSplitter(!server_side, max);
trk.paf_state.paf = StreamSplitter::START;
- ++tcpStats.partial_fallbacks;
+ tcpStats.partial_fallbacks++;
}
void TcpReassembler::fallback(TcpStreamTracker& tracker, bool server_side)
{
- uint16_t max = tracker.session->config->paf_max;
+ uint16_t max = tracker.session->tcp_config->paf_max;
::fallback(tracker, server_side, max);
Flow* flow = tracker.session->flow;
if ( flow->gadget and both_splitters_aborted(flow) )
{
flow->clear_gadget();
- ++tcpStats.inspector_fallbacks;
+ tcpStats.inspector_fallbacks++;
}
}
const tcp::TCPHdr* tcph = tsd.get_tcph();
uint32_t overlap = 0;
- uint32_t seq = tsd.get_seg_seq();
+ uint32_t seq = tsd.get_seq();
if ( tcph->is_syn() )
seq++;
if ( SEQ_GT(trs.tracker->r_win_base, seq) )
{
- overlap = trs.tracker->r_win_base - tsd.get_seg_seq();
+ overlap = trs.tracker->r_win_base - tsd.get_seq();
- if ( overlap >= tsd.get_seg_len() )
+ if ( overlap >= tsd.get_len() )
return;
}
{
overlap = trs.sos.seglist_base_seq- seq - overlap;
- if ( overlap >= tsd.get_seg_len() )
+ if ( overlap >= tsd.get_len() )
return;
}
// BLOCK add new block to trs.sos.seglist containing data
add_reassembly_segment(
- trs, tsd, tsd.get_seg_len(), overlap, 0, seq + overlap, nullptr);
+ trs, tsd, tsd.get_len(), overlap, 0, seq + overlap, nullptr);
}
if ( trs.sos.seglist.head && trs.sos.seglist.tail )
{
- if ( SEQ_GT(tsd.get_seg_seq(), trs.sos.seglist.head->i_seq) )
- dist_head = tsd.get_seg_seq() - trs.sos.seglist.head->i_seq;
+ if ( SEQ_GT(tsd.get_seq(), trs.sos.seglist.head->i_seq) )
+ dist_head = tsd.get_seq() - trs.sos.seglist.head->i_seq;
else
- dist_head = trs.sos.seglist.head->i_seq - tsd.get_seg_seq();
+ dist_head = trs.sos.seglist.head->i_seq - tsd.get_seq();
- if ( SEQ_GT(tsd.get_seg_seq(), trs.sos.seglist.tail->i_seq) )
- dist_tail = tsd.get_seg_seq() - trs.sos.seglist.tail->i_seq;
+ if ( SEQ_GT(tsd.get_seq(), trs.sos.seglist.tail->i_seq) )
+ dist_tail = tsd.get_seq() - trs.sos.seglist.tail->i_seq;
else
- dist_tail = trs.sos.seglist.tail->i_seq - tsd.get_seg_seq();
+ dist_tail = trs.sos.seglist.tail->i_seq - tsd.get_seq();
}
if ( SEQ_LEQ(dist_head, dist_tail) )
{
right = tsn;
- if ( SEQ_GEQ(right->i_seq, tsd.get_seg_seq() ) )
+ if ( SEQ_GEQ(right->i_seq, tsd.get_seq() ) )
break;
left = right;
{
left = tsn;
- if ( SEQ_LT(left->i_seq, tsd.get_seg_seq() ) )
+ if ( SEQ_LT(left->i_seq, tsd.get_seq() ) )
break;
right = left;
trs.sos.init_soe(tsd, left, right);
}
-int TcpReassembler::insert_segment_in_seglist(
+void TcpReassembler::insert_segment_in_seglist(
TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
{
- int rc = STREAM_INSERT_OK;
-
// NORM fast tracks are in sequence - no norms
if ( trs.sos.seglist.tail && is_segment_fasttrack(trs, trs.sos.seglist.tail, tsd) )
{
/* segment fit cleanly at the end of the segment list */
- rc = add_reassembly_segment(
- trs, tsd, tsd.get_seg_len(), 0, 0, tsd.get_seg_seq(), trs.sos.seglist.tail);
- return rc;
+ add_reassembly_segment(
+ trs, tsd, tsd.get_len(), 0, 0, tsd.get_seq(), trs.sos.seglist.tail);
+ return;
}
init_overlap_editor(trs, tsd);
- rc = eval_left(trs);
-
- if ( rc != STREAM_INSERT_OK )
- return rc;
-
- rc = eval_right(trs);
-
- if ( rc != STREAM_INSERT_OK )
- return rc;
+ eval_left(trs);
+ eval_right(trs);
if ( trs.sos.keep_segment )
{
/* Adjust slide so that is correct relative to orig seq */
- trs.sos.slide = trs.sos.seq - tsd.get_seg_seq();
+ trs.sos.slide = trs.sos.seq - tsd.get_seq();
// FIXIT-L for some reason length - slide - trunc_len is sometimes negative
if (trs.sos.len - trs.sos.slide - trs.sos.trunc_len < 0)
- return STREAM_INSERT_OK;
- rc = add_reassembly_segment(
+ return;
+
+ add_reassembly_segment(
trs, tsd, trs.sos.len, trs.sos.slide, trs.sos.trunc_len, trs.sos.seq, trs.sos.left);
}
- else
- rc = STREAM_INSERT_OK;
-
- return rc;
}
-int TcpReassembler::queue_packet_for_reassembly(
+void TcpReassembler::queue_packet_for_reassembly(
TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
{
- int rc = STREAM_INSERT_OK;
-
if ( trs.sos.seg_count == 0 )
{
insert_segment_in_empty_seglist(trs, tsd);
- return STREAM_INSERT_OK;
+ return;
}
- if ( SEQ_GT(trs.tracker->r_win_base, tsd.get_seg_seq() ) )
+ if ( SEQ_GT(trs.tracker->r_win_base, tsd.get_seq() ) )
{
- const int32_t offset = trs.tracker->r_win_base - tsd.get_seg_seq();
+ const int32_t offset = trs.tracker->r_win_base - tsd.get_seq();
- if ( offset < tsd.get_seg_len() )
+ if ( offset < tsd.get_len() )
{
tsd.slide_segment_in_rcv_window(offset);
- rc = insert_segment_in_seglist(trs, tsd);
+ insert_segment_in_seglist(trs, tsd);
tsd.slide_segment_in_rcv_window(-offset);
}
}
else
- rc = insert_segment_in_seglist(trs, tsd);
-
- return rc;
+ insert_segment_in_seglist(trs, tsd);
}
uint32_t TcpReassembler::perform_partial_flush(TcpReassemblerState& trs, Flow* flow)
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_reassembly.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_reassembly.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 31, 2015
#ifndef TCP_REASSEMBLER_H
class TcpReassembler : public SegmentOverlapEditor
{
public:
- virtual int queue_packet_for_reassembly(TcpReassemblerState&, TcpSegmentDescriptor&);
+ virtual void queue_packet_for_reassembly(TcpReassemblerState&, TcpSegmentDescriptor&);
virtual void purge_segment_list(TcpReassemblerState&);
virtual void purge_flushed_ackd(TcpReassemblerState&);
virtual int flush_stream(
protected:
TcpReassembler() = default;
- int add_reassembly_segment(
+ void add_reassembly_segment(
TcpReassemblerState&, TcpSegmentDescriptor&, uint16_t len, uint32_t slide,
uint32_t trunc, uint32_t seq, TcpSegmentNode* left) override;
- int dup_reassembly_segment(
+ void dup_reassembly_segment(
TcpReassemblerState&, TcpSegmentNode* left, TcpSegmentNode** retSeg) override;
int delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*) override;
virtual void insert_segment_in_empty_seglist(TcpReassemblerState&, TcpSegmentDescriptor&);
- virtual int insert_segment_in_seglist(TcpReassemblerState&, TcpSegmentDescriptor&);
+ virtual void insert_segment_in_seglist(TcpReassemblerState&, TcpSegmentDescriptor&);
virtual uint32_t get_pending_segment_count(TcpReassemblerState&, unsigned max);
bool flush_data_ready(TcpReassemblerState&);
int trim_delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*, uint32_t flush_seq);
void update_next(TcpReassemblerState&, const TcpSegmentNode&);
uint32_t perform_partial_flush(TcpReassemblerState&, snort::Packet*, uint32_t flushed = 0);
-
};
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_reassemblers.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_reassemblers.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Oct 9, 2015
#ifdef HAVE_CONFIG_H
TcpReassemblerFirst() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_new(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os5(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os5(trs); }
};
class TcpReassemblerLast : public TcpReassembler
TcpReassemblerLast() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_last(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_last(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os4(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os4(trs); }
};
class TcpReassemblerLinux : public TcpReassembler
TcpReassemblerLinux() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os2(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os2(trs); }
};
class TcpReassemblerOldLinux : public TcpReassembler
TcpReassemblerOldLinux() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os4(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os4(trs); }
};
class TcpReassemblerBSD : public TcpReassembler
TcpReassemblerBSD() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os1(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os1(trs); }
};
class TcpReassemblerMacOS : public TcpReassembler
TcpReassemblerMacOS() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os1(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os1(trs); }
};
class TcpReassemblerSolaris : public TcpReassembler
TcpReassemblerSolaris() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_trim_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_trim_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_new(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os3(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os3(trs); }
};
class TcpReassemblerIrix : public TcpReassembler
TcpReassemblerIrix() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os2(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os2(trs); }
};
class TcpReassemblerHpux11 : public TcpReassembler
TcpReassemblerHpux11() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_trim_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_trim_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_new(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os3(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os3(trs); }
};
class TcpReassemblerHpux10 : public TcpReassembler
TcpReassemblerHpux10() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os2(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os2(trs); }
};
class TcpReassemblerWindows : public TcpReassembler
TcpReassemblerWindows() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os1(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os1(trs); }
};
class TcpReassemblerWindows2K3 : public TcpReassembler
TcpReassemblerWindows2K3() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_existing(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os1(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os1(trs); }
};
class TcpReassemblerVista : public TcpReassembler
TcpReassemblerVista() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_new(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os5 (trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os5 (trs); }
};
class TcpReassemblerProxy : public TcpReassemblerFirst
TcpReassemblerProxy() = default;
private:
- int insert_left_overlap(TcpReassemblerState& trs) override
- { return left_overlap_keep_first(trs); }
+ void insert_left_overlap(TcpReassemblerState& trs) override
+ { left_overlap_keep_first(trs); }
void insert_right_overlap(TcpReassemblerState& trs) override
{ right_overlap_truncate_new(trs); }
- int insert_full_overlap(TcpReassemblerState& trs) override
- { return full_right_overlap_os5(trs); }
+ void insert_full_overlap(TcpReassemblerState& trs) override
+ { full_right_overlap_os5(trs); }
};
void TcpReassemblerPolicy::init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol, bool server)
}
void TcpReassemblerPolicy::reset()
-{
- init(nullptr, nullptr, StreamPolicy::OS_DEFAULT, false);
-}
+{ init(nullptr, nullptr, StreamPolicy::OS_DEFAULT, false); }
TcpReassembler* TcpReassemblerFactory::reassemblers[StreamPolicy::OS_END_OF_LIST];
void init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol, bool server);
void reset();
- int queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
- { return reassembler->queue_packet_for_reassembly(trs, tsd); }
+ void queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
+ { reassembler->queue_packet_for_reassembly(trs, tsd); }
void purge_alerts()
{ reassembler->purge_alerts(trs); }
#include "tcp_segment_descriptor.h"
#include "detection/rules.h"
+#include "packet_tracer/packet_tracer.h"
#include "protocols/tcp_options.h"
#include "stream/tcp/tcp_defs.h"
+#include "stream/tcp/tcp_stream_tracker.h"
using namespace snort;
-TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* flow_, Packet* pkt_, TcpEventLogger& tel) :
- flow(flow_),
- pkt(pkt_),
- tcph(pkt->ptrs.tcph),
- src_port(tcph->src_port()),
- dst_port(tcph->dst_port()),
- seg_seq(tcph->seq()),
- seg_ack(tcph->ack()),
- seg_wnd(tcph->win()),
- end_seq(seg_seq + (uint32_t)pkt->dsize)
+static THREAD_LOCAL Packet* ma_pseudo_packet;
+static THREAD_LOCAL tcp::TCPHdr ma_pseudo_tcph;
+
+TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* f, Packet* p, TcpEventLogger& tel)
+ : flow(f), pkt(p), tcph(pkt->ptrs.tcph),
+ packet_number(p->context->packet_number),
+ seq(tcph->seq()),
+ ack(tcph->ack()),
+ wnd(tcph->win()),
+ end_seq(seq + (uint32_t)pkt->dsize),
+ timestamp_option(0),
+ src_port(tcph->src_port()),
+ dst_port(tcph->dst_port())
{
+ packet_timestamp = p->pkth->ts.tv_sec;
+ packet_from_client = p->is_from_client();
+
// don't bump end_seq for fin here we will bump if/when fin is processed
if ( tcph->is_syn() )
{
}
}
+TcpSegmentDescriptor::TcpSegmentDescriptor
+ (snort::Flow* f, snort::Packet* p, uint32_t meta_ack, uint16_t window)
+ : flow(f), pkt(ma_pseudo_packet), tcph(&ma_pseudo_tcph),
+ packet_number(p->context->packet_number)
+{
+ // init tcp header fields for meta-ack packet
+ ma_pseudo_tcph.th_dport = p->ptrs.tcph->raw_src_port();
+ ma_pseudo_tcph.th_sport = p->ptrs.tcph->raw_dst_port();
+ ma_pseudo_tcph.th_seq = p->ptrs.tcph->raw_ack();
+ ma_pseudo_tcph.th_ack = htonl(meta_ack);
+ ma_pseudo_tcph.th_offx2 = 0;
+ ma_pseudo_tcph.th_flags = TH_ACK;
+ ma_pseudo_tcph.th_win = htons(window);
+ ma_pseudo_tcph.th_sum = 0;
+ ma_pseudo_tcph.th_urp = 0;
+
+ // init meta-ack Packet fields stream cares about for TCP ack processing
+ pkt->flow = p->flow;
+ pkt->context = p->context;
+ pkt->dsize = 0;
+
+ seq = tcph->seq();
+ ack = tcph->ack();
+ wnd = tcph->win();
+ end_seq = seq;
+ timestamp_option = 0;
+ src_port = tcph->src_port();
+ dst_port = tcph->dst_port();
+
+ packet_timestamp = p->pkth->ts.tv_sec;
+ packet_from_client = !p->is_from_client();
+ meta_ack_packet = true;
+}
+
+void TcpSegmentDescriptor::setup()
+{ ma_pseudo_packet = new Packet(false); }
+
+void TcpSegmentDescriptor::clear()
+{ delete ma_pseudo_packet; }
+
uint32_t TcpSegmentDescriptor::init_mss(uint16_t* value)
{
if ( pkt->ptrs.decode_flags & DECODE_TCP_MSS )
return ( init_wscale(&wscale) & TF_WSCALE ) != TF_NONE;
}
+void TcpSegmentDescriptor::set_retransmit_flag()
+{
+ assert(!meta_ack_packet);
+
+ if ( PacketTracer::is_active() )
+ {
+ PacketTracer::log("Packet was retransmitted and %s from the retry queue.\n",
+ pkt->is_retry() ? "is" : "is not");
+ }
+
+ // Mark the packet as being a re-transmit if it's not from the retry
+ // queue. That way we can avoid adding re-transmitted packets to
+ // the retry queue.
+ if ( !pkt->is_retry() )
+ pkt->packet_flags |= PKT_RETRANSMIT;
+}
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_segment_descriptor.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_segment_descriptor.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifndef TCP_SEGMENT_DESCRIPTOR_H
#define TCP_SEGMENT_DESCRIPTOR_H
+#include <cassert>
+
+#include <daq_common.h>
+
#include "flow/flow.h"
+#include "detection/ips_context.h"
+#include "packet_io/active.h"
#include "protocols/packet.h"
#include "protocols/tcp.h"
#include "stream/tcp/tcp_event_logger.h"
+class TcpStreamTracker;
+
class TcpSegmentDescriptor
{
public:
TcpSegmentDescriptor(snort::Flow*, snort::Packet*, TcpEventLogger&);
+ TcpSegmentDescriptor(snort::Flow*, snort::Packet*, uint32_t meta_ack, uint16_t window);
+
virtual ~TcpSegmentDescriptor() = default;
+ static void setup();
+ static void clear();
+
+ bool is_policy_inline()
+ { return pkt->context->conf->inline_mode(); }
+
uint32_t init_mss(uint16_t* value);
uint32_t init_wscale(uint16_t* value);
bool has_wscale();
+ void set_retransmit_flag();
snort::Flow* get_flow() const
- {
- return flow;
- }
+ { return flow; }
snort::Packet* get_pkt() const
- {
- return pkt;
- }
+ { return pkt; }
const snort::tcp::TCPHdr* get_tcph() const
- {
- return tcph;
- }
+ { return tcph; }
- void set_seg_seq(uint32_t seq)
- {
- seg_seq = seq;
- }
+ void set_seq(uint32_t seq_num)
+ { seq = seq_num; }
- void update_seg_seq(int32_t offset)
- {
- seg_seq += offset;
- }
+ void update_seq(int32_t offset)
+ { seq += offset; }
- uint32_t get_seg_seq() const
- {
- return seg_seq;
- }
+ uint32_t get_seq() const
+ { return seq; }
- uint32_t get_seg_ack() const
- {
- return seg_ack;
- }
+ uint32_t get_ack() const
+ { return ack; }
- void set_seg_ack(uint32_t ack)
- {
- this->seg_ack = ack;
- }
+ void set_ack(uint32_t ack_num)
+ { ack = ack_num; }
- void set_end_seq(uint32_t end_seq)
- {
- this->end_seq = end_seq;
- }
+ void set_end_seq(uint32_t seq)
+ { end_seq = seq; }
uint32_t get_end_seq() const
- {
- return end_seq;
- }
+ { return end_seq; }
- void set_ts(uint32_t ts)
- {
- this->ts = ts;
- }
+ void set_timestamp(uint32_t timestamp)
+ { timestamp_option = timestamp; }
- uint32_t get_ts() const
- {
- return ts;
- }
+ uint32_t get_timestamp() const
+ { return timestamp_option; }
- void scale_seg_wnd(uint16_t wscale)
- {
- seg_wnd <<= wscale;
- }
+ void scale_wnd(uint16_t wscale)
+ { wnd <<= wscale; }
- uint32_t get_seg_wnd() const
- {
- return seg_wnd;
- }
+ uint32_t get_wnd() const
+ { return wnd; }
uint16_t get_dst_port() const
- {
- return dst_port;
- }
+ { return dst_port; }
uint16_t get_src_port() const
- {
- return src_port;
- }
+ { return src_port; }
uint8_t get_direction() const
+ { return flow->ssn_state.direction; }
+
+ uint16_t get_len() const
+ { return pkt->dsize; }
+
+ void set_len(uint16_t seg_len)
{
- return flow->ssn_state.direction;
+ assert(!meta_ack_packet);
+ pkt->dsize = seg_len;
}
- uint16_t get_seg_len() const
+ void update_len(int32_t offset)
{
- return pkt->dsize;
+ assert(!meta_ack_packet);
+ pkt->dsize += offset;
}
- void set_seg_len(uint16_t seg_len)
+ bool is_packet_from_client() const
+ { return packet_from_client; }
+
+ bool is_packet_from_server() const
+ { return !packet_from_client; }
+
+ void slide_segment_in_rcv_window(int32_t offset)
{
- // Reset segment size to seg_len
- pkt->dsize = seg_len;
+ assert(!meta_ack_packet);
+ seq += offset;
+ pkt->data += offset;
+ pkt->dsize -= offset;
}
- void update_seg_len(int32_t offset)
+ void set_packet_flags(uint32_t flags) const
{
- // Increase segment size by offset
- pkt->dsize += offset;
+ assert(!meta_ack_packet);
+ pkt->packet_flags |= flags;
}
- bool is_packet_from_server()
+ bool are_packet_flags_set(uint32_t flags) const
+ { return (pkt->packet_flags & flags) == flags; }
+
+ uint32_t get_packet_timestamp() const
+ { return packet_timestamp; }
+
+ void drop_packet() const
{
- return pkt->is_from_server();
+ pkt->active->drop_packet(pkt);
+ pkt->active->set_drop_reason("stream");
}
- void slide_segment_in_rcv_window(int32_t offset)
+ bool is_meta_ack_packet() const
+ { return meta_ack_packet; }
+
+ uint64_t get_packet_number() const
+ { return packet_number; }
+
+ void rewrite_payload(uint16_t offset, uint8_t* from, uint16_t length)
{
- // This actually deletes the first offset bytes of the segment, no sliding involved
- seg_seq += offset;
- pkt->data += offset;
- pkt->dsize -= offset;
+ assert(!meta_ack_packet);
+ memcpy(const_cast<uint8_t*>(pkt->data + offset), from, length);
+ set_packet_flags(PKT_MODIFIED);
}
+ void rewrite_payload(uint16_t offset, uint8_t* from)
+ { rewrite_payload(offset, from, pkt->dsize); }
+
+ TcpStreamTracker* get_listener() const
+ { return listener; }
+
+ void set_listener(TcpStreamTracker& tracker)
+ { listener = &tracker; }
+
+ TcpStreamTracker* get_talker() const
+ { return talker; }
+
+ void set_talker(TcpStreamTracker& tracker)
+ { talker = &tracker; }
+
private:
snort::Flow* const flow;
snort::Packet* const pkt;
-
const snort::tcp::TCPHdr* const tcph;
- const uint16_t src_port;
- const uint16_t dst_port;
- uint32_t seg_seq;
- uint32_t seg_ack;
- uint32_t seg_wnd;
+ TcpStreamTracker* talker = nullptr;
+ TcpStreamTracker* listener = nullptr;
+
+ const uint64_t packet_number;
+ uint32_t seq;
+ uint32_t ack;
+ uint32_t wnd;
uint32_t end_seq;
- uint32_t ts = 0;
+ uint32_t timestamp_option;
+ uint16_t src_port;
+ uint16_t dst_port;
+ uint32_t packet_timestamp;
+ bool packet_from_client;
+ bool meta_ack_packet = false;
};
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_segment.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_segment.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Sep 21, 2015
#ifdef HAVE_CONFIG_H
TcpSegmentNode* TcpSegmentNode::init(const TcpSegmentDescriptor& tsd)
{
- return create(tsd.get_pkt()->pkth->ts, tsd.get_pkt()->data, tsd.get_seg_len());
+ return create(tsd.get_pkt()->pkth->ts, tsd.get_pkt()->data, tsd.get_len());
}
TcpSegmentNode* TcpSegmentNode::init(TcpSegmentNode& tns)
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_segment_node.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_segment_node.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Sep 21, 2015
#ifndef TCP_SEGMENT_H
uint16_t c_len; // length of data remaining for reassembly
uint16_t offset;
uint16_t size; // actual allocated size (overlaps cause i_len to differ)
-
uint8_t data[1];
};
using namespace snort;
void TcpSession::sinit()
-{ TcpSegmentNode::setup(); }
+{
+ TcpSegmentDescriptor::setup();
+ TcpSegmentNode::setup();
+}
void TcpSession::sterm()
-{ TcpSegmentNode::clear(); }
+{
+ TcpSegmentDescriptor::clear();
+ TcpSegmentNode::clear();
+}
TcpSession::TcpSession(Flow* f) : TcpStreamSession(f)
{
TcpStreamSession::setup(p);
splitter_init = false;
- const TcpStreamConfig* cfg = get_tcp_cfg(flow->ssn_server);
- flow->set_default_session_timeout(cfg->session_timeout, false);
+ tcp_config = get_tcp_cfg(flow->ssn_server);
+ flow->set_default_session_timeout(tcp_config->session_timeout, false);
+ set_os_policy();
SESSION_STATS_ADD(tcpStats)
tcpStats.setups++;
bool TcpSession::flow_exceeds_config_thresholds(const TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+
if ( listener->flush_policy == STREAM_FLPOLICY_IGNORE )
- {
return true;
- }
// FIXIT-M any discards must be counted and in many cases alerted as well
// (count all but alert at most once per flow)
// three cases in this function; look for others
- if ( ( config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !flow->two_way_traffic() )
+ if ( ( tcp_config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !flow->two_way_traffic() )
return true;
- if ( config->max_consec_small_segs )
+ if ( tcp_config->max_consec_small_segs )
{
- if ( tsd.get_seg_len() >= config->max_consec_small_seg_size )
+ if ( tsd.get_len() >= tcp_config->max_consec_small_seg_size )
listener->small_seg_count = 0;
- else if ( ++listener->small_seg_count == config->max_consec_small_segs )
+ else if ( ++listener->small_seg_count == tcp_config->max_consec_small_segs )
tel.set_tcp_event(EVENT_MAX_SMALL_SEGS_EXCEEDED);
}
- if ( config->max_queued_bytes
- && ( listener->reassembler.get_seg_bytes_total() > config->max_queued_bytes ) )
+ if ( tcp_config->max_queued_bytes
+ && ( listener->reassembler.get_seg_bytes_total() > tcp_config->max_queued_bytes ) )
{
tcpStats.exceeded_max_bytes++;
// FIXIT-M add one alert per flow per above
return true;
}
- if ( config->max_queued_segs
- && ( listener->reassembler.get_seg_count() + 1 > config->max_queued_segs ) )
+ if ( tcp_config->max_queued_segs
+ && ( listener->reassembler.get_seg_count() + 1 > tcp_config->max_queued_segs ) )
{
tcpStats.exceeded_max_segs++;
// FIXIT-M add one alert per flow per above
void TcpSession::process_tcp_stream(TcpSegmentDescriptor& tsd)
{
- if (tsd.get_pkt()->packet_flags & PKT_IGNORE)
+ if ( tsd.are_packet_flags_set(PKT_IGNORE) )
return;
- SetPacketHeaderFoo(tsd.get_pkt());
+ set_packet_header_foo(tsd);
if ( flow_exceeds_config_thresholds(tsd) )
return;
+ TcpStreamTracker* listener = tsd.get_listener();
+
listener->reassembler.queue_packet_for_reassembly(tsd);
// Alert if overlap limit exceeded
- if ( ( config->overlap_limit )
- && ( listener->reassembler.get_overlap_count() > config->overlap_limit ) )
+ if ( (tcp_config->overlap_limit)
+ && (listener->reassembler.get_overlap_count() > tcp_config->overlap_limit) )
{
tel.set_tcp_event(EVENT_EXCESSIVE_OVERLAP);
listener->reassembler.set_overlap_count(0);
void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool aligned)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+
switch ( listener->order )
{
case 0:
if ( aligned )
- tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_OK;
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
else
listener->order = 1;
break;
case 1:
if ( aligned )
{
- tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_OK;
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
listener->order = 2;
}
break;
default:
if ( aligned )
- tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_OK;
+ tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
else
{
if ( !(flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD) )
flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
- tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_BAD;
+ tsd.set_packet_flags(PKT_STREAM_ORDER_BAD);
}
}
}
int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
const tcp::TCPHdr* tcph = tsd.get_tcph();
- uint32_t seq = tsd.get_seg_seq();
+ uint32_t seq = tsd.get_seq();
if ( tcph->is_syn() )
{
if (seq == listener->rcv_nxt)
{
/* check if we're in the window */
- if (config->policy != StreamPolicy::OS_PROXY
+ if (tcp_config->policy != StreamPolicy::OS_PROXY
and listener->normalizer.get_stream_window(tsd) == 0)
{
listener->normalizer.trim_win_payload(tsd);
// FIXIT-L for ips, must move all the way to first hole or right end
listener->rcv_nxt = tsd.get_end_seq();
- if (tsd.get_seg_len() != 0)
+ if (tsd.get_len() != 0)
{
update_stream_order(tsd, true);
process_tcp_stream(tsd);
// some cases.
/* check if we're in the window */
- if (config->policy != StreamPolicy::OS_PROXY
+ if (tcp_config->policy != StreamPolicy::OS_PROXY
and listener->normalizer.get_stream_window(tsd) == 0)
{
listener->normalizer.trim_win_payload(tsd);
return STREAM_UNALIGNED;
}
- if (tsd.get_seg_len() != 0)
+ if (tsd.get_len() != 0)
{
update_stream_order(tsd, false);
process_tcp_stream(tsd);
void TcpSession::set_os_policy()
{
StreamPolicy client_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
+ static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
StreamPolicy server_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
+ static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
client.normalizer.init(client_os_policy, this, &client, &server);
server.normalizer.init(server_os_policy, this, &server, &client);
void TcpSession::update_timestamp_tracking(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
+
talker->set_tf_flags(listener->normalizer.get_timestamp_flags());
if (listener->normalizer.handling_timestamps()
- && SEQ_EQ(listener->rcv_nxt, tsd.get_seg_seq()))
+ && SEQ_EQ(listener->rcv_nxt, tsd.get_seq()))
{
- talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
- talker->set_ts_last(tsd.get_ts());
+ talker->set_ts_last_packet(tsd.get_packet_timestamp());
+ talker->set_ts_last(tsd.get_timestamp());
}
}
bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
const tcp::TCPHdr* tcph = tsd.get_tcph();
- if ( ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED )
- || ( talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ) )
+
+ if ( (listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)
+ || (talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED) )
{
// Listener previously issued a reset Talker is re-SYN-ing
flow->set_ttl(tsd.get_pkt(), true);
init_session_on_syn(tsd);
tcpStats.resyns++;
- listener = &server;
- talker = &client;
- listener->normalizer.ecn_tracker(tcph, config->require_3whs());
+ listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
}
else if ( tcph->is_syn_ack() )
{
- if (config->midstream_allowed(tsd.get_pkt()))
+ if ( tcp_config->midstream_allowed(tsd.get_pkt()) )
{
flow->ssn_state.direction = FROM_SERVER;
flow->session_state = STREAM_STATE_SYN_ACK;
tcpStats.resyns++;
}
- listener = &client;
- talker = &server;
- listener->normalizer.ecn_tracker(tcph, config->require_3whs());
+ listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
flow->update_session_flags(SSNFLAG_SEEN_SERVER);
}
}
void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
{
+ if ( tsd.is_meta_ack_packet() )
+ return;
+
+ Packet* p = tsd.get_pkt();
// FIXIT-L why flush here instead of just purge?
// s5_ignored_session() may be disabling detection too soon if we really want to flush
- if (Stream::ignored_flow(flow, tsd.get_pkt()))
+ if ( Stream::ignored_flow(flow, p) )
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
+
if ( talker && ( talker->get_tf_flags() & TF_FORCE_FLUSH ) )
{
- flush_talker(tsd.get_pkt() );
+ flush_talker(p);
talker->clear_tf_flags(TF_FORCE_FLUSH);
}
if ( listener && ( listener->get_tf_flags() & TF_FORCE_FLUSH ) )
{
- flush_listener(tsd.get_pkt());
+ flush_listener(p);
listener->clear_tf_flags(TF_FORCE_FLUSH);
}
- tsd.get_pkt()->packet_flags |= PKT_IGNORE;
+ tsd.set_packet_flags(PKT_IGNORE);
pkt_action_mask |= ACTION_DISABLE_INSPECTION;
+ tcpStats.ignored++;
}
}
void TcpSession::handle_data_on_syn(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
+
/* MacOS accepts data on SYN, so don't alert if policy is MACOS */
- if (talker->normalizer.get_os_policy() == StreamPolicy::OS_MACOS)
- {
+ if ( talker->normalizer.get_os_policy() == StreamPolicy::OS_MACOS )
handle_data_segment(tsd);
- }
else
{
listener->normalizer.trim_syn_payload(tsd);
void TcpSession::update_session_on_rst(TcpSegmentDescriptor& tsd, bool flush)
{
+ Packet* p = tsd.get_pkt();
+
if ( flush )
{
- flush_listener(tsd.get_pkt(), true);
- flush_talker(tsd.get_pkt(), true);
+ flush_listener(p, true);
+ flush_talker(p, true);
set_splitter(true, nullptr);
set_splitter(false, nullptr);
}
- talker->update_on_rst_sent( );
+ tsd.get_talker()->update_on_rst_sent();
}
void TcpSession::update_paws_timestamps(TcpSegmentDescriptor& tsd)
{
- // update PAWS timestamps
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
if ( listener->normalizer.handling_timestamps()
- && SEQ_EQ(listener->r_win_base, tsd.get_seg_seq() ) )
+ && SEQ_EQ(listener->r_win_base, tsd.get_seq()) )
{
- if ( ( (int32_t)(tsd.get_ts() - talker->get_ts_last() ) >= 0 )
- ||
- ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec
- >= talker->get_ts_last_packet() + PAWS_24DAYS ) )
+ if ( ((int32_t)(tsd.get_timestamp() - talker->get_ts_last()) >= 0 )
+ || (tsd.get_packet_timestamp() >= talker->get_ts_last_packet() + PAWS_24DAYS) )
{
- talker->set_ts_last(tsd.get_ts());
- talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
+ talker->set_ts_last(tsd.get_timestamp());
+ talker->set_ts_last_packet(tsd.get_packet_timestamp());
}
}
}
void TcpSession::check_for_session_hijack(TcpSegmentDescriptor& tsd)
{
- if (!(tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
+
+ Packet* p = tsd.get_pkt();
+ if ( !(p->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING) )
{
- if ( tsd.get_pkt()->is_eth() )
+ if ( p->is_eth() )
{
- // if flag is set, guaranteed to have an eth layer
- Packet* p = tsd.get_pkt();
const eth::EtherHdr* eh = layer::get_eth_layer(p);
bool t_hijack = !talker->compare_mac_addresses(eh->ether_src);
bool l_hijack = !listener->compare_mac_addresses(eh->ether_dst);
// if both seem hijacked then swap src/dst check, it that matches probably a tap
- if ( ( t_hijack & l_hijack ) &&
- ( talker->compare_mac_addresses(eh->ether_dst) &&
- listener->compare_mac_addresses(eh->ether_src) ) )
+ if ( (t_hijack & l_hijack) && (talker->compare_mac_addresses(eh->ether_dst) &&
+ listener->compare_mac_addresses(eh->ether_src)) )
return;
uint32_t event_code = 0;
event_code |= EVENT_SESSION_HIJACK_CLIENT;
}
- if (event_code)
+ if ( event_code )
tel.set_tcp_event(event_code);
}
}
bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
{
- if ( config->max_window && (tsd.get_seg_wnd() > config->max_window ) )
+ TcpStreamTracker* listener = tsd.get_listener();
+
+ if ( tcp_config->max_window && (tsd.get_wnd() > tcp_config->max_window) )
{
/* got a window too large, alert! */
tel.set_tcp_event(EVENT_WINDOW_TOO_LARGE);
pkt_action_mask |= ACTION_BAD_PKT;
return true;
}
- else if ((tsd.get_pkt()->is_from_client())
- && (tsd.get_seg_wnd() <= SLAM_MAX)
- && (tsd.get_seg_ack() == listener->get_iss() + 1)
- && !( tsd.get_tcph()->is_fin() | tsd.get_tcph()->is_rst() )
+ else if ( tsd.is_packet_from_client() && (tsd.get_wnd() <= SLAM_MAX)
+ && (tsd.get_ack() == listener->get_iss() + 1)
+ && !(tsd.get_tcph()->is_fin() | tsd.get_tcph()->is_rst())
&& !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
{
/* got a window slam alert! */
tel.set_tcp_event(EVENT_WINDOW_SLAM);
inc_tcp_discards();
- if (listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK))
+ if ( listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
{
pkt_action_mask |= ACTION_BAD_PKT;
return true;
void TcpSession::mark_packet_for_drop(TcpSegmentDescriptor& tsd)
{
- listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+
+ tsd.get_listener()->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
set_pkt_action_flag(ACTION_BAD_PKT);
}
void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
+
if ( TcpStreamTracker::TCP_CLOSED != talker->get_tcp_state() )
{
uint8_t tcp_options_len = tsd.get_tcph()->options_len();
- if (tsd.is_packet_from_server())
- server.set_tcp_options_len(tcp_options_len);
- else
+ if ( tsd.is_packet_from_client() )
client.set_tcp_options_len(tcp_options_len);
+ else
+ server.set_tcp_options_len(tcp_options_len);
// FIXIT-M move this to normalizer base class, handle OS_PROXY in derived class
- if (config->policy != StreamPolicy::OS_PROXY)
+ if ( tcp_config->policy != StreamPolicy::OS_PROXY )
{
/* check for valid sequence/retrans */
- if (!listener->is_segment_seq_valid(tsd) )
+ if ( !listener->is_segment_seq_valid(tsd) )
return;
// these normalizations can't be done if we missed setup. and
// window is zero in one direction until we've seen both sides.
- if (!(flow->get_session_flags() & SSNFLAG_MIDSTREAM) && flow->two_way_traffic())
+ if ( !(flow->get_session_flags() & SSNFLAG_MIDSTREAM) && flow->two_way_traffic() )
{
// sender of syn w/mss limits payloads from peer since we store mss on
// sender side, use listener mss same reasoning for window size
// FIXIT-H: MSS is not set on client so packets sent to client are not trimmed
// use case?
- if (st->get_mss())
+ if ( st->get_mss() )
st->normalizer.trim_mss_payload(tsd, st->get_mss());
- st->normalizer.ecn_stripper(tsd.get_pkt());
+ st->normalizer.ecn_stripper(tsd);
}
}
// dunno if this is RFC but fragroute testing expects it for the record,
// I've seen FTP data sessions that send data packets with no tcp flags set
- if ((tsd.get_tcph()->th_flags != 0) or (config->policy == StreamPolicy::OS_LINUX)
- or (config->policy == StreamPolicy::OS_PROXY))
+ if ( (tsd.get_tcph()->th_flags != 0) or (tcp_config->policy == StreamPolicy::OS_LINUX)
+ or (tcp_config->policy == StreamPolicy::OS_PROXY) )
{
process_tcp_data(tsd);
}
listener->reassembler.flush_on_data_policy(tsd.get_pkt());
}
-TcpStreamTracker::TcpState TcpSession::get_talker_state()
+TcpStreamTracker::TcpState TcpSession::get_talker_state(TcpSegmentDescriptor& tsd)
{
- return talker->get_tcp_state();
+ return tsd.get_talker()->get_tcp_state();
}
-TcpStreamTracker::TcpState TcpSession::get_listener_state()
+TcpStreamTracker::TcpState TcpSession::get_listener_state(TcpSegmentDescriptor& tsd)
{
- return listener->get_tcp_state();
+ return tsd.get_listener()->get_tcp_state();
}
void TcpSession::check_for_repeated_syn(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
uint32_t action = ACTION_NOTHING;
- if ( !SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()) and
+ if ( !SEQ_EQ(tsd.get_seq(), talker->get_iss()) and
listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
{
action = ACTION_BAD_PKT;
{
action = listener->normalizer.handle_repeated_syn(tsd);
}
+
if (action != ACTION_NOTHING)
{
- /* got a bad SYN on the session, alert! */
tel.set_tcp_event(EVENT_SYN_ON_EST);
pkt_action_mask |= action;
}
server.set_tf_flags(TF_FORCE_FLUSH);
- // If rebuilt packet, don't flush now because we'll overwrite the packet being processed.
+ // don't flush if rebuilt packet, that would overwrite the packet being processed.
if ( p->packet_flags & PKT_REBUILT_STREAM )
- {
- // We'll check & clear the TF_FORCE_FLUSH next time through
- return;
- }
+ return; // We'll check & clear the TF_FORCE_FLUSH next time through
// Need to convert the addresses to network order
if ( server.reassembler.flush_stream(p, PKT_FROM_SERVER) )
// If rebuilt packet, don't flush now because we'll overwrite the packet being processed.
if ( p->packet_flags & PKT_REBUILT_STREAM )
- {
- // We'll check & clear the TF_FORCE_FLUSH next time through
- return;
- }
+ return; // TF_FORCE_FLUSH checked & cleared next time through
if ( client.reassembler.flush_stream(p, PKT_FROM_CLIENT) )
client.reassembler.purge_flushed_ackd();
void TcpSession::flush_tracker(
TcpStreamTracker& tracker, Packet* p, uint32_t dir, bool final_flush)
{
- if ( final_flush && ( !tracker.splitter || !tracker.splitter->finish(flow) ) )
+ if ( final_flush && (!tracker.splitter || !tracker.splitter->finish(flow)) )
return;
tracker.set_tf_flags(TF_FORCE_FLUSH);
st.reassembler.set_xtradata_mask(st.reassembler.get_xtradata_mask() | BIT(xid));
}
-static inline void set_window_scale(const TcpStreamTracker& talker, const TcpStreamTracker& listener,
- TcpSegmentDescriptor& tsd)
+static inline void set_window_scale(TcpSegmentDescriptor& tsd)
{
// scale the window. Only if BOTH client and server specified wscale option as part
// of 3-way handshake. This is per RFC 1323.
- if ( ( talker.get_tf_flags() & TF_WSCALE ) && ( listener.get_tf_flags() & TF_WSCALE ) )
- tsd.scale_seg_wnd(talker.get_wscale() );
+ if ( (tsd.get_talker()->get_tf_flags() & TF_WSCALE)
+ && (tsd.get_listener()->get_tf_flags() & TF_WSCALE) )
+ {
+ tsd.scale_wnd(tsd.get_talker()->get_wscale());
+ }
}
-void TcpSession::do_packet_analysis_post_checks(Packet* p)
+void TcpSession::check_events_and_actions(const TcpSegmentDescriptor& tsd)
{
+ if ( tsd.is_meta_ack_packet() )
+ return;
+
tel.log_tcp_events();
- if (!(pkt_action_mask & ACTION_LWSSN_CLOSED))
+ Packet* p = tsd.get_pkt();
+ if ( !(pkt_action_mask & ACTION_LWSSN_CLOSED) )
{
flow->markup_packet_flags(p);
-
flow->set_expire(p, flow->default_session_timeout);
}
else
- TcpHAManager::process_deletion(*p->flow);
+ TcpHAManager::process_deletion(*flow);
- if (pkt_action_mask & ACTION_DISABLE_INSPECTION)
- {
+ if ( pkt_action_mask & ACTION_DISABLE_INSPECTION )
DetectionEngine::disable_all(p);
- }
}
-// FIXIT-M can flow do these checks before calling stream tcp?
-bool TcpSession::is_flow_handling_packets(Packet* p)
+bool TcpSession::ignore_this_packet(Packet* p)
{
- bool flow_ready = true;
-
- // FIXIT-L can't get here without protocol being set to TCP, is this really needed??
- if (flow->pkt_type != PktType::TCP)
+ if ( no_ack_mode_enabled() and p->is_retry() )
{
- return false;
+ // Don't need to process a retry packet through stream again,
+ // just make sure the retransmit handler is called so that
+ // we do things like update file inspection.
+ flow->call_handlers(p, false);
+ return true;
}
- if(flow->session_state & STREAM_STATE_IGNORE)
- {
- tcpStats.ignored++;
- flow_ready = false;
- }
- else
- flow_ready = !Stream::blocked_flow(p);
+ if ( Stream::blocked_flow(p) )
+ return true;
// FIXIT-L expected flow should be checked by Stream before we get here
// harmonize this with that and the checks above
{
server.flush_policy = STREAM_FLPOLICY_IGNORE;
client.flush_policy = STREAM_FLPOLICY_IGNORE;
- flow_ready = false;
+ return true;
}
- return flow_ready;
+ return false;
}
void TcpSession::cleanup_session_if_expired(Packet* p)
{
// Check if the session is expired. Should be done before we do something with
// the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
- if (Stream::expired_flow(flow, p))
+ if ( Stream::expired_flow(flow, p) )
{
/* Session is timed out, if also reset then restart, otherwise clear */
- if (flow->get_session_flags() & SSNFLAG_RESET)
+ if ( flow->get_session_flags() & SSNFLAG_RESET )
clear_session(true, true, true, p);
else
clear_session(true, true, false, p);
cleanup_session_if_expired(p);
}
-bool TcpSession::do_packet_analysis_pre_checks(Packet* p, TcpSegmentDescriptor& tsd)
+void TcpSession::init_tcp_packet_analysis(TcpSegmentDescriptor& tsd)
{
- if ( !is_flow_handling_packets(p) )
- return false;
-
- if ( !splitter_init and tsd.get_seg_len() > 0 )
+ if ( !splitter_init and tsd.get_len() > 0 )
{
- if ( !(config->flags & STREAM_CONFIG_NO_REASSEMBLY) )
+ if ( !(tcp_config->flags & STREAM_CONFIG_NO_REASSEMBLY) )
{
client.set_splitter(tsd.get_flow());
server.set_splitter(tsd.get_flow());
client.init_flush_policy();
server.init_flush_policy();
- set_no_ack(config->no_ack);
+ set_no_ack(tcp_config->no_ack);
}
+
splitter_init = true;
}
// FIXIT-M: The snd_nxt and snd_una checks are only needed because
// the snd_nxt value isn't valid for SYN/ACK packet. Can remove those
// checks if that is fixed.
- if ( p->is_from_client() )
+ if ( tsd.is_packet_from_client() )
{
update_session_on_client_packet(tsd);
if ( no_ack_mode_enabled() and (server.get_snd_nxt() or server.get_snd_una()) )
- tsd.set_seg_ack(server.get_snd_nxt());
+ tsd.set_ack(server.get_snd_nxt());
}
else
{
update_session_on_server_packet(tsd);
if ( no_ack_mode_enabled() and (client.get_snd_nxt() or client.get_snd_una()) )
- tsd.set_seg_ack(client.get_snd_nxt());
+ tsd.set_ack(client.get_snd_nxt());
}
update_ignored_session(tsd);
- set_window_scale(*talker, *listener, tsd);
-
- if ( p->context->conf->is_address_anomaly_check_enabled() )
- check_for_session_hijack(tsd);
-
- return true;
+ set_window_scale(tsd);
}
bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd)
{
+ TcpStreamTracker* listener = tsd.get_listener();
+
pkt_action_mask |= listener->normalizer.handle_paws(tsd);
- if ( tsd.get_pkt()->context->conf->inline_mode() )
- if ( tsd.get_tcph()->is_ack() && !listener->is_ack_valid(tsd.get_seg_ack()) )
+ if ( tsd.is_policy_inline() )
+ if ( tsd.get_tcph()->is_ack() && !listener->is_ack_valid(tsd.get_ack()) )
pkt_action_mask |= ACTION_BAD_PKT;
return ( pkt_action_mask & ACTION_BAD_PKT ) ? false : true;
}
-/*
- * Main entry point for TCP
- */
-int TcpSession::process(Packet* p)
+int TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
{
- Profile profile(s5TcpPerfStats);
- assert(flow->ssn_server);
-
- if ( no_ack_mode_enabled() and p->is_retry() )
+ if ( tsm->eval(tsd) )
{
- // Don't need to process a retry packet through stream again,
- // just make sure the retransmit handler is called so that
- // we do things like update file inspection.
- flow->call_handlers(p, false);
- return ACTION_NOTHING;
+ check_events_and_actions(tsd);
+ S5TraceTCP(tsd);
}
+ else
+ {
+ if ( pkt_action_mask & ACTION_BAD_PKT )
+ {
+ inc_tcp_discards();
+ check_events_and_actions(tsd);
+ }
- // FIXIT-M need to do something here to handle check for need to swap trackers??
- if ( !config )
- config = get_tcp_cfg(flow->ssn_server);
+ tel.log_tcp_events();
+ S5TraceTCP(tsd);
+ }
- if( !tcp_init )
- set_os_policy();
+ return ACTION_NOTHING;
+}
- TcpSegmentDescriptor tsd(flow, p, tel);
+int TcpSession::process(Packet* p)
+{
+ Profile profile(s5TcpPerfStats);
+ assert(flow->ssn_server && flow->pkt_type == PktType::TCP);
- if ( !do_packet_analysis_pre_checks(p, tsd) )
+ if ( ignore_this_packet(p) )
return ACTION_NOTHING;
- if ( ( flow->get_session_flags() & SSNFLAG_RESET ) && tsd.get_tcph()->is_syn()
- && !handle_syn_on_reset_session(tsd) )
- return ACTION_NOTHING;
+ TcpSegmentDescriptor tsd(flow, p, tel);
+ init_tcp_packet_analysis(tsd);
- else
+ // if listener is in pre-ack mode, check for and process meta-ack info first if present
+ // the current listener is the talker for the meta-ack...
+ if ( tsd.get_listener()->get_flush_policy() == STREAM_FLPOLICY_ON_DATA )
{
- if ( tsm->eval(tsd, *talker, *listener) )
+ DAQ_PktTcpAckData_t* tcp_mack = (DAQ_PktTcpAckData_t*)p->daq_msg->meta[DAQ_PKT_META_TCP_ACK_DATA];
+ if ( tcp_mack )
{
- do_packet_analysis_post_checks(p);
- S5TraceTCP(p, flow, &tsd, 0);
+ 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);
+ tcpStats.meta_acks++;
}
- else
- {
- if ( pkt_action_mask & ACTION_BAD_PKT )
- {
- inc_tcp_discards();
+ }
- do_packet_analysis_post_checks(p);
- }
+ if ( p->context->conf->is_address_anomaly_check_enabled() )
+ check_for_session_hijack(tsd);
- tel.log_tcp_events();
- S5TraceTCP(p, flow, &tsd, 0);
- }
- }
+ if ( ( flow->get_session_flags() & SSNFLAG_RESET ) && tsd.get_tcph()->is_syn()
+ && !handle_syn_on_reset_session(tsd) )
+ return ACTION_NOTHING;
- return ACTION_NOTHING;
+ return process_tcp_packet(tsd);
}
void TcpSession::flush()
void clear_session(bool free_flow_data, bool flush_segments, bool restart, snort::Packet* p = nullptr) override;
void set_extra_data(snort::Packet*, uint32_t /*flag*/) override;
void update_perf_base_state(char new_state) override;
- TcpStreamTracker::TcpState get_talker_state() override;
- TcpStreamTracker::TcpState get_listener_state() override;
+ TcpStreamTracker::TcpState get_talker_state(TcpSegmentDescriptor& tsd) override;
+ TcpStreamTracker::TcpState get_listener_state(TcpSegmentDescriptor& tsd) override;
void update_timestamp_tracking(TcpSegmentDescriptor&) override;
void update_session_on_rst(TcpSegmentDescriptor&, bool) override;
bool handle_syn_on_reset_session(TcpSegmentDescriptor&) override;
void handle_data_segment(TcpSegmentDescriptor&) override;
bool validate_packet_established_session(TcpSegmentDescriptor&) override;
+ bool is_midstream_allowed(const TcpSegmentDescriptor& tsd)
+ { return tcp_config->midstream_allowed(tsd.get_pkt()); }
+
private:
+ int process_tcp_packet(TcpSegmentDescriptor&);
+ void process_tcp_stream(TcpSegmentDescriptor&);
+ int process_tcp_data(TcpSegmentDescriptor&);
void set_os_policy() override;
bool flow_exceeds_config_thresholds(const TcpSegmentDescriptor&);
void update_stream_order(const TcpSegmentDescriptor&, bool aligned);
- void process_tcp_stream(TcpSegmentDescriptor&);
- int process_tcp_data(TcpSegmentDescriptor&);
void swap_trackers();
void init_session_on_syn(TcpSegmentDescriptor&);
void init_session_on_synack(TcpSegmentDescriptor&);
void update_on_3whs_complete(TcpSegmentDescriptor&);
- bool is_flow_handling_packets(snort::Packet*);
+ bool ignore_this_packet(snort::Packet*);
void cleanup_session_if_expired(snort::Packet*);
- bool do_packet_analysis_pre_checks(snort::Packet*, TcpSegmentDescriptor&);
- void do_packet_analysis_post_checks(snort::Packet*);
+ void init_tcp_packet_analysis(TcpSegmentDescriptor&);
+ void check_events_and_actions(const TcpSegmentDescriptor& tsd);
void flush_tracker(TcpStreamTracker&, snort::Packet*, uint32_t dir, bool final_flush);
private:
bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+ if ( SEQ_GT(tsd.get_seq(), trk.get_fin_final_seq() ) )
{
trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
{
if ( !flow->two_way_traffic() )
trk.set_tf_flags(TF_FORCE_FLUSH);
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
}
return true;
trk.session->update_session_on_rst(tsd, true);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
trk.session->set_pkt_action_flag(ACTION_RST);
- tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
+ tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
}
else
{
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_close_wait.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_close_wait.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_CLOSE_WAIT_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_closed.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_closed.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifdef HAVE_CONFIG_H
bool TcpStateClosed::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
Flow* flow = tsd.get_flow();
- flow->set_expire(tsd.get_pkt(), trk.session->config->session_timeout);
+ flow->set_expire(tsd.get_pkt(), trk.session->tcp_config->session_timeout);
return true;
}
{
trk.update_tracker_ack_recv(tsd);
- if( tsd.get_seg_len() > 0 )
+ if( tsd.get_len() > 0 )
{
if ( trk.is_rst_pkt_sent() )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RESET);
if ( trk.get_tcp_event() != TcpStreamTracker::TCP_FIN_RECV_EVENT )
{
- TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state();
+ TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state(tsd);
Flow* flow = tsd.get_flow();
if ( ( talker_state == TcpStreamTracker::TCP_TIME_WAIT ) || !flow->two_way_traffic() )
bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
Flow* flow = tsd.get_flow();
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+ if ( SEQ_GT(tsd.get_seq(), trk.get_fin_final_seq() ) )
{
trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
if ( !flow->two_way_traffic() )
trk.set_tf_flags(TF_FORCE_FLUSH);
- if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
return true;
}
trk.session->update_session_on_rst(tsd, true);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
trk.session->set_pkt_action_flag(ACTION_RST);
- tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
+ tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
}
else
{
// Handle getting stuck in CLOSED/FIN_WAIT on simultaneous close (FIN FIN ACK ACK)
if ( trk.get_tcp_event() != TcpStreamTracker::TCP_FIN_RECV_EVENT )
{
- if ( ( trk.session->get_talker_state() == TcpStreamTracker::TCP_CLOSED ) &&
- ( trk.session->get_listener_state() == TcpStreamTracker::TCP_TIME_WAIT ) )
+ if ( ( trk.session->get_talker_state(tsd) == TcpStreamTracker::TCP_CLOSED ) &&
+ ( trk.session->get_listener_state(tsd) == TcpStreamTracker::TCP_TIME_WAIT ) )
{
Flow* flow = tsd.get_flow();
trk.session->clear_session(false, true, false, tsd.get_pkt() );
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_established.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_established.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifdef HAVE_CONFIG_H
bool TcpStateEstablished::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.session->check_for_repeated_syn(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
return true;
}
bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt()) )
+ if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
{
// FIXIT-M there may be an issue when syn/ack from server is seen
// after ack from client which causes some tracker state variables to
}
if ( trk.is_server_tracker() )
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
return true;
}
bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.update_on_fin_sent(tsd);
- trk.session->eof_handle(tsd.get_pkt());
+ trk.session->flow->call_handlers(tsd.get_pkt(), true);
trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
-
return true;
}
bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.update_tracker_ack_recv(tsd);
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
{
trk.session->handle_data_segment(tsd);
trk.flush_data_on_fin_recv(tsd);
}
// FIXIT-L might be good to create alert specific to RST with data
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
bool TcpStateFinWait1::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
trk.update_tracker_ack_recv(tsd);
if ( check_for_window_slam(tsd, trk) )
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
}
return true;
bool is_ack_valid = false;
if ( check_for_window_slam(tsd, trk, &is_ack_valid) )
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
if ( !flow->two_way_traffic() )
trk.session->update_session_on_rst(tsd, true);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
trk.session->set_pkt_action_flag(ACTION_RST);
- tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
+ tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
}
else
{
}
// FIXIT-L might be good to create alert specific to RST with data
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
}
bool TcpStateFinWait1::check_for_window_slam(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk, bool* is_ack_valid)
{
- if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
{
if ( (trk.normalizer.get_os_policy() == StreamPolicy::OS_WINDOWS)
- && (tsd.get_seg_wnd() == 0))
+ && (tsd.get_wnd() == 0))
{
trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
inc_tcp_discards();
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_fin_wait1.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_fin_wait1.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_FIN_WAIT1_H
bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
bool TcpStateFinWait2::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( SEQ_GT(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_GT(tsd.get_ack(), trk.get_snd_nxt() ) )
{
trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( SEQ_GT(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_GT(tsd.get_ack(), trk.get_snd_nxt() ) )
{
trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
else
{
trk.update_tracker_ack_recv(tsd);
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
}
return true;
trk.update_tracker_ack_recv(tsd);
if ( trk.update_on_fin_recv(tsd) )
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
if ( !flow->two_way_traffic() )
trk.session->update_session_on_rst(tsd, true);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
trk.session->set_pkt_action_flag(ACTION_RST);
- tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
+ tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
}
else
{
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_fin_wait2.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_fin_wait2.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_FIN_WAIT2_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_handler.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_handler.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jun 24, 2015
#ifdef HAVE_CONFIG_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_handler.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_handler.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jun 24, 2015
#ifndef TCP_STATE_HANDLER_H
bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
bool TcpStateLastAck::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
return true;
}
bool TcpStateLastAck::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
return true;
}
Flow* flow = tsd.get_flow();
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+ if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
if ( !flow->two_way_traffic() )
}
// FIXIT-L might be good to create alert specific to RST with data
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
}
trk.session->update_paws_timestamps(tsd);
trk.session->check_for_window_slam(tsd);
- if ( ( trk.session->get_listener_state() == TcpStreamTracker::TCP_CLOSED ) &&
+ if ( ( trk.session->get_listener_state(tsd) == TcpStreamTracker::TCP_CLOSED ) &&
( trk.get_tcp_event() != TcpStreamTracker::TCP_FIN_RECV_EVENT ) )
{
- TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state();
+ TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state(tsd);
Flow* flow = tsd.get_flow();
if ( ( talker_state == TcpStreamTracker::TCP_TIME_WAIT )
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_listen.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_listen.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifdef HAVE_CONFIG_H
bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->require_3whs() || tsd.has_wscale() || ( tsd.get_seg_len() > 0 ) )
+ if ( trk.session->tcp_config->require_3whs() || tsd.has_wscale() || ( tsd.get_len() > 0 ) )
{
- // FIXIT-L do we need this check? only server goes into Listen state...
- if ( tsd.get_pkt()->is_from_server() )
+ if ( tsd.is_packet_from_server() )
trk.session->tel.set_tcp_event(EVENT_4WHS);
}
return true;
bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.init_on_syn_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd) );
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_on_syn(tsd);
return true;
}
Flow* flow = tsd.get_flow();
flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
trk.init_on_synack_sent(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
trk.session->init_new_tcp_session(tsd);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( !trk.session->config->require_3whs() or
- trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( !trk.session->tcp_config->require_3whs() or trk.session->is_midstream_allowed(tsd) )
{
trk.init_on_synack_recv(tsd);
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() )
- && ( tsd.has_wscale() || ( tsd.get_seg_len() > 0 ) ) )
+ if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt())
+ && (tsd.has_wscale() || (tsd.get_len() > 0 )) )
{
Flow* flow = tsd.get_flow();
flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
trk.session->init_new_tcp_session(tsd);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() )
- && ( tsd.has_wscale() || ( tsd.get_seg_len() > 0 ) ) )
+ if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0 )) )
{
Flow* flow = tsd.get_flow();
- if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
+ if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK) )
{
trk.init_on_3whs_ack_recv(tsd);
trk.normalizer.ecn_tracker(
- tsd.get_tcph(), trk.session->config->require_3whs());
+ tsd.get_tcph(), trk.session->tcp_config->require_3whs());
}
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
Flow* flow = tsd.get_flow();
if ( flow->session_state & STREAM_STATE_ESTABLISHED )
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
Flow* flow = tsd.get_flow();
DataBus::publish(STREAM_TCP_MIDSTREAM_EVENT, tsd.get_pkt());
}
trk.init_on_data_seg_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
trk.session->handle_data_segment(tsd);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateListen::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( !trk.session->config->midstream_allowed(tsd.get_pkt()) and
- trk.session->config->require_3whs() )
+ if ( !trk.session->is_midstream_allowed(tsd) and trk.session->tcp_config->require_3whs() )
{
// FIXIT-L listen gets fin triggers 129:20 ??
trk.session->generate_no_3whs_event();
bool TcpStateListen::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
// FIXIT-L handle FIN on midstream
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
tcp_state_handlers[ state ] = &handler;
}
-bool TcpStateMachine::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& talker,
- TcpStreamTracker& listener)
+bool TcpStateMachine::eval(TcpSegmentDescriptor& tsd)
{
- const TcpStreamTracker::TcpState talker_state = talker.get_tcp_state( );
+ TcpStreamTracker* talker = tsd.get_talker();
+ const TcpStreamTracker::TcpState talker_state = talker->get_tcp_state();
- talker.set_tcp_event(tsd);
- if ( tcp_state_handlers[ talker_state ]->do_pre_sm_packet_actions(tsd, talker) )
+ talker->set_tcp_event(tsd);
+ if ( tcp_state_handlers[ talker_state ]->do_pre_sm_packet_actions(tsd, *talker) )
{
- if ( tcp_state_handlers[ talker_state ]->eval(tsd, talker) )
+ if ( tcp_state_handlers[ talker_state ]->eval(tsd, *talker) )
{
- const TcpStreamTracker::TcpState listener_state = listener.get_tcp_state( );
- listener.set_tcp_event(tsd);
- tcp_state_handlers[ listener_state ]->eval(tsd, listener);
- tcp_state_handlers[ listener_state ]->do_post_sm_packet_actions(tsd, listener);
+ TcpStreamTracker* listener = tsd.get_listener();
+ const TcpStreamTracker::TcpState listener_state = listener->get_tcp_state( );
+ listener->set_tcp_event(tsd);
+ tcp_state_handlers[ listener_state ]->eval(tsd, *listener);
+ tcp_state_handlers[ listener_state ]->do_post_sm_packet_actions(tsd, *listener);
return true;
}
{ return TcpStateMachine::tsm; }
virtual void register_state_handler(TcpStreamTracker::TcpState, TcpStateHandler&);
- virtual bool eval(TcpSegmentDescriptor&, TcpStreamTracker&, TcpStreamTracker&);
+ virtual bool eval(TcpSegmentDescriptor&);
protected:
TcpStateMachine();
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_none.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_none.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
#ifdef HAVE_CONFIG_H
{
Flow* flow = tsd.get_flow();
- if ( !trk.session->config->require_3whs() or
- trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( !trk.session->tcp_config->require_3whs() or trk.session->is_midstream_allowed(tsd) )
{
flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
trk.init_on_synack_sent(tsd);
trk.session->init_new_tcp_session(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
trk.init_on_synack_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() > 0 )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
- ( tsd.get_seg_len() > 0 ) ) )
+ if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0)) )
{
Flow* flow = tsd.get_flow();
trk.session->init_new_tcp_session(tsd);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
- ( tsd.get_seg_len() > 0 ) ) )
+ if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0)) )
{
Flow* flow = tsd.get_flow();
{
trk.init_on_3whs_ack_recv(tsd);
trk.normalizer.ecn_tracker(
- tsd.get_tcph(), trk.session->config->require_3whs());
+ tsd.get_tcph(), trk.session->tcp_config->require_3whs());
}
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
Flow* flow = tsd.get_flow();
if ( flow->session_state & STREAM_STATE_ESTABLISHED )
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
Flow* flow = tsd.get_flow();
}
trk.init_on_data_seg_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
trk.session->handle_data_segment(tsd);
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
// FIXIT-M handle FIN on midstream
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
// FIXIT-M handle FIN on midstream
}
- else if ( trk.session->config->require_3whs() )
+ else if ( trk.session->tcp_config->require_3whs() )
{
trk.session->generate_no_3whs_event();
return false;
bool TcpStateNone::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
+ if ( trk.session->is_midstream_allowed(tsd) )
{
// FIXIT-M handle RST on midstream
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_syn_recv.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_syn_recv.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifdef HAVE_CONFIG_H
Flow* flow = tsd.get_flow();
trk.finish_server_init(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
trk.session->update_timestamp_tracking(tsd);
if ( tsd.get_tcph()->are_flags_set(TH_ECE) &&
( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
- if ( tsd.get_pkt()->is_from_server() )
+ if ( tsd.is_packet_from_server() )
{
flow->set_session_flags(SSNFLAG_SEEN_SERVER);
trk.session->tel.set_tcp_event(EVENT_4WHS);
bool TcpStateSynRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
}
// FIXIT-H verify ack being sent is valid...
// norm/drop + discard
trk.finish_server_init(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
flow->session_state |= STREAM_STATE_SYN_ACK;
return true;
}
bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.is_ack_valid(tsd.get_seg_ack()) )
+ if ( trk.is_ack_valid(tsd.get_ack()) )
{
Flow* flow = tsd.get_flow();
trk.update_tracker_ack_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
flow->set_session_flags(SSNFLAG_ESTABLISHED);
flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
}
return true;
bool TcpStateSynRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->config->midstream_allowed(tsd.get_pkt()) )
+ if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
{
trk.session->update_session_on_ack( );
}
bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.is_ack_valid(tsd.get_seg_ack()) )
+ if ( trk.is_ack_valid(tsd.get_ack()) )
{
Flow* flow = tsd.get_flow();
trk.update_tracker_ack_recv(tsd);
trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
- tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+ tsd.set_packet_flags(PKT_STREAM_TWH);
flow->set_session_flags(SSNFLAG_ESTABLISHED);
flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
else
trk.session->check_for_window_slam(tsd);
bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.is_ack_valid(tsd.get_seg_ack()) )
+ if ( trk.is_ack_valid(tsd.get_ack()) )
{
trk.update_tracker_ack_recv(tsd);
- tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+ tsd.set_packet_flags(PKT_STREAM_TWH);
trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
}
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
return true;
}
trk.update_tracker_ack_recv(tsd);
trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
flow->session_state |= STREAM_STATE_ACK;
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
{
trk.session->handle_data_segment(tsd);
trk.flush_data_on_fin_recv(tsd);
}
// FIXIT-L might be good to create alert specific to RST with data
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_syn_recv_state.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_syn_recv_state.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_SYN_RECV_H
bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.finish_client_init(tsd);
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
trk.set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
return true;
if ( trk.update_on_3whs_ack(tsd) )
{
trk.session->update_timestamp_tracking(tsd);
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
}
else
bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
return true;
}
bool TcpStateSynSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
return true;
}
trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSED);
trk.session->set_pkt_action_flag(ACTION_RST);
- tsd.get_pkt()->flow->session_state |= STREAM_STATE_CLOSED;
+ tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
}
else
{
}
// FIXIT-L might be good to create alert specific to RST with data
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_syn_sent_state.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_syn_sent_state.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_SYN_SENT_H
bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
- if ( tsd.get_seg_len() )
+ trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ if ( tsd.get_len() )
trk.session->handle_data_on_syn(tsd);
return true;
bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.update_tracker_ack_recv(tsd);
- if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+ if ( SEQ_GT(tsd.get_seq(), trk.get_fin_final_seq() ) )
{
trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
}
- else if ( tsd.get_seg_len() > 0 )
+ else if ( tsd.get_len() > 0 )
trk.session->handle_data_segment(tsd);
return true;
// FIXIT-L might be good to create alert specific to RST with data
// FIXIT-L refactoring required? seen this in many places
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
return true;
if ( trk.get_tcp_event() != TcpStreamTracker::TCP_FIN_RECV_EVENT )
{
- TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state();
+ TcpStreamTracker::TcpState talker_state = trk.session->get_talker_state(tsd);
Flow* flow = tsd.get_flow();
if ( ( talker_state == TcpStreamTracker::TCP_TIME_WAIT )
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_state_time_wait.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_state_time_wait.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Aug 5, 2015
#ifndef TCP_STATE_TIME_WAIT_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_stream_config.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_stream_config.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Oct 22, 2015
#ifdef HAVE_CONFIG_H
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_stream_config.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_stream_config.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Oct 22, 2015
#ifndef TCP_STREAM_CONFIG_H
void TcpStreamSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
{
- flow->pkt_type = tsd.get_pkt()->type();
- flow->ip_proto = (uint8_t)tsd.get_pkt()->get_ip_proto_next();
+ Packet* p = tsd.get_pkt();
+
+ flow->pkt_type = p->type();
+ flow->ip_proto = (uint8_t)p->get_ip_proto_next();
/* New session, previous was marked as reset. Clear the reset flag. */
flow->clear_session_flags(SSNFLAG_RESET);
- flow->set_expire(tsd.get_pkt(), flow->default_session_timeout);
+ flow->set_expire(p, flow->default_session_timeout);
update_perf_base_state(TcpStreamTracker::TCP_SYN_SENT);
void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd)
{
flow->set_session_flags(SSNFLAG_SEEN_SERVER);
- talker = &server;
- listener = &client;
+ tsd.set_talker(server);
+ tsd.set_listener(client);
/* If we picked this guy up midstream, finish the initialization */
if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
}
}
- if (!flow->inner_server_ttl)
+ if ( !flow->inner_server_ttl && !tsd.is_meta_ack_packet() )
flow->set_ttl(tsd.get_pkt(), false);
}
{
/* if we got here we have seen the SYN already... */
flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
- talker = &client;
- listener = &server;
+ tsd.set_talker(client);
+ tsd.set_listener(server);
if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
&& ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
}
}
- if (!flow->inner_client_ttl)
+ if (!flow->inner_client_ttl && !tsd.is_meta_ack_packet() )
flow->set_ttl(tsd.get_pkt(), true);
}
void TcpStreamSession::set_no_ack(bool b)
{
- if (
- server.get_flush_policy() == STREAM_FLPOLICY_ON_DATA and
- client.get_flush_policy() == STREAM_FLPOLICY_ON_DATA )
+ if ( server.get_flush_policy() == STREAM_FLPOLICY_ON_DATA and
+ client.get_flush_policy() == STREAM_FLPOLICY_ON_DATA )
{
no_ack = b;
}
bool TcpStreamSession::set_packet_action_to_hold(Packet* p)
{
- return listener->set_held_packet(p);
+ if ( p->is_from_client() )
+ return server.set_held_packet(p);
+ else
+ return client.set_held_packet(p);
}
-void TcpStreamSession::SetPacketHeaderFoo(const Packet* p)
+void TcpStreamSession::set_packet_header_foo(const TcpSegmentDescriptor& tsd)
{
+ const Packet* p = tsd.get_pkt();
+
if ( daq_flags & DAQ_PKT_FLAG_NOT_FORWARDING )
{
ingress_index = p->pkth->ingress_index;
egress_index = p->pkth->egress_index;
egress_group = p->pkth->egress_group;
}
- else if ( p->is_from_client() )
+ else if ( tsd.is_packet_from_client() )
{
ingress_index = p->pkth->ingress_index;
ingress_group = p->pkth->ingress_group;
egress_index = p->pkth->ingress_index;
egress_group = p->pkth->ingress_group;
}
+
daq_flags = p->pkth->flags;
address_space_id = p->pkth->address_space_id;
}
-void TcpStreamSession::GetPacketHeaderFoo(DAQ_PktHdr_t* pkth, uint32_t dir)
+void TcpStreamSession::get_packet_header_foo(DAQ_PktHdr_t* pkth, uint32_t dir)
{
if ( (dir & PKT_FROM_CLIENT) || (daq_flags & DAQ_PKT_FLAG_NOT_FORWARDING) )
{
ingress_index = egress_index = 0;
ingress_group = egress_group = 0;
daq_flags = address_space_id = 0;
- config = nullptr;
+ tcp_config = nullptr;
return true;
}
void TcpStreamSession::start_proxy()
{
- config->policy = StreamPolicy::OS_PROXY;
+ tcp_config->policy = StreamPolicy::OS_PROXY;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_stream_session.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_stream_session.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Feb 18, 2016
#ifndef TCP_STREAM_SESSION_H
void reset();
void start_proxy();
- void SetPacketHeaderFoo(const snort::Packet* p);
- void GetPacketHeaderFoo(DAQ_PktHdr_t* pkth, uint32_t dir);
- void SwapPacketHeaderFoo();
+ void set_packet_header_foo(const TcpSegmentDescriptor&);
+ void get_packet_header_foo(DAQ_PktHdr_t*, uint32_t dir);
void set_no_ack(bool);
bool no_ack_mode_enabled() { return no_ack; }
- virtual void update_perf_base_state(char) { }
+ virtual void update_perf_base_state(char) = 0;
virtual void clear_session(
bool free_flow_data, bool flush_segments, bool restart, snort::Packet* p = nullptr) = 0;
- // FIXIT-RC these 2 function names convey no meaning afaict... figure out
- // why are they called and name appropriately...
- virtual void retransmit_process(snort::Packet* p)
- {
- // Data has already been analyzed so don't bother looking at it again.
- snort::DetectionEngine::disable_content(p);
- }
+ virtual void flush() = 0;
- virtual void retransmit_handle(snort::Packet* p)
- {
- flow->call_handlers(p, false);
- }
+ virtual TcpStreamTracker::TcpState get_talker_state(TcpSegmentDescriptor&) = 0;
- virtual void eof_handle(snort::Packet* p)
- {
- flow->call_handlers(p, true);
- }
-
- virtual void flush() { }
-
- virtual TcpStreamTracker::TcpState get_talker_state()
- { return TcpStreamTracker::TCP_MAX_STATES; }
-
- virtual TcpStreamTracker::TcpState get_listener_state()
- { return TcpStreamTracker::TCP_MAX_STATES; }
+ virtual TcpStreamTracker::TcpState get_listener_state(TcpSegmentDescriptor&) = 0;
TcpStreamTracker::TcpState get_peer_state(TcpStreamTracker* me)
{ return me == &client ? server.get_tcp_state() : client.get_tcp_state(); }
virtual void init_new_tcp_session(TcpSegmentDescriptor&);
- virtual void update_timestamp_tracking(TcpSegmentDescriptor&) { }
+ virtual void update_timestamp_tracking(TcpSegmentDescriptor&) = 0;
virtual void update_session_on_syn_ack();
virtual void update_session_on_ack();
virtual void update_session_on_server_packet(TcpSegmentDescriptor&);
virtual void update_session_on_client_packet(TcpSegmentDescriptor&);
- virtual void update_session_on_rst(TcpSegmentDescriptor&, bool) { }
- virtual bool handle_syn_on_reset_session(TcpSegmentDescriptor&) { return true; }
- virtual void handle_data_on_syn(TcpSegmentDescriptor&) { }
- virtual void update_ignored_session(TcpSegmentDescriptor&) { }
-
+ virtual void update_session_on_rst(TcpSegmentDescriptor&, bool) = 0;
+ virtual bool handle_syn_on_reset_session(TcpSegmentDescriptor&) = 0;
+ virtual void handle_data_on_syn(TcpSegmentDescriptor&) = 0;
+ virtual void update_ignored_session(TcpSegmentDescriptor&) = 0;
void generate_no_3whs_event()
{
if ( generate_3whs_alert && flow->two_way_traffic())
void set_pkt_action_flag(uint32_t flag)
{ pkt_action_mask |= flag; }
- virtual void update_paws_timestamps(TcpSegmentDescriptor&) { }
- virtual void check_for_repeated_syn(TcpSegmentDescriptor&) { }
- virtual void check_for_session_hijack(TcpSegmentDescriptor&) { }
- virtual bool check_for_window_slam(TcpSegmentDescriptor&) { return true; }
- virtual void mark_packet_for_drop(TcpSegmentDescriptor&) { }
- virtual void handle_data_segment(TcpSegmentDescriptor&) { }
- virtual bool validate_packet_established_session(TcpSegmentDescriptor&) { return true; }
+ virtual void update_paws_timestamps(TcpSegmentDescriptor&) = 0;
+ virtual void check_for_repeated_syn(TcpSegmentDescriptor&) = 0;
+ virtual void check_for_session_hijack(TcpSegmentDescriptor&) = 0;
+ virtual bool check_for_window_slam(TcpSegmentDescriptor&) = 0;
+ virtual void mark_packet_for_drop(TcpSegmentDescriptor&) = 0;
+ virtual void handle_data_segment(TcpSegmentDescriptor&) = 0;
+ virtual bool validate_packet_established_session(TcpSegmentDescriptor&) = 0;
TcpStreamTracker client;
TcpStreamTracker server;
uint32_t daq_flags = 0;
uint16_t address_space_id = 0;
bool generate_3whs_alert = true;
- TcpStreamConfig* config = nullptr;
+ TcpStreamConfig* tcp_config = nullptr;
TcpEventLogger tel;
private:
protected:
TcpStreamSession(snort::Flow*);
virtual void set_os_policy() = 0;
-
- TcpStreamTracker* talker = nullptr;
- TcpStreamTracker* listener = nullptr;
};
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_stream_tracker.cpp author davis mcpherson <davmcphe@@cisco.com>
+// tcp_stream_tracker.cpp author davis mcpherson <davmcphe@cisco.com>
// Created on: Jun 24, 2015
#ifdef HAVE_CONFIG_H
bool talker;
const tcp::TCPHdr* tcph = tsd.get_tcph();
- if ( tsd.get_pkt()->is_from_client() )
+ if ( tsd.is_packet_from_client() )
talker = ( client_tracker ) ? true : false;
else
talker = ( client_tracker ) ? false : true;
tcp_event = TCP_FIN_SENT_EVENT;
else if ( tcph->is_ack() || tcph->is_psh() )
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
tcp_event = TCP_DATA_SEG_SENT_EVENT;
else
tcp_event = TCP_ACK_SENT_EVENT;
}
- else if ( tsd.get_seg_len() > 0 ) // FIXIT-H no flags set, how do we handle this?
+ else if ( tsd.get_len() > 0 ) // FIXIT-H no flags set, how do we handle this?
// discard; drop if normalizing
tcp_event = TCP_DATA_SEG_SENT_EVENT;
else
}
else if ( tcph->is_ack() || tcph->is_psh() )
{
- if ( tsd.get_seg_len() > 0 )
+ if ( tsd.get_len() > 0 )
tcp_event = TCP_DATA_SEG_RECV_EVENT;
else
tcp_event = TCP_ACK_RECV_EVENT;
}
- else if ( tsd.get_seg_len() > 0 ) // FIXIT-H no flags set, how do we handle this?
+ else if ( tsd.get_len() > 0 ) // FIXIT-H no flags set, how do we handle this?
// discard; drop if normalizing
tcp_event = TCP_DATA_SEG_RECV_EVENT;
else
if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
- iss = tsd.get_seg_seq();
+ iss = tsd.get_seq();
snd_una = iss;
snd_nxt = tsd.get_end_seq();
- snd_wnd = tsd.get_seg_wnd();
+ snd_wnd = tsd.get_wnd();
- ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ ts_last_packet = tsd.get_packet_timestamp();
tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
- ts_last = tsd.get_ts();
+ ts_last = tsd.get_timestamp();
if (ts_last == 0)
tf_flags |= TF_TSTAMP_ZERO;
tf_flags |= tsd.init_mss(&mss);
void TcpStreamTracker::init_on_syn_recv(TcpSegmentDescriptor& tsd)
{
- irs = tsd.get_seg_seq();
+ irs = tsd.get_seq();
- rcv_nxt = tsd.get_seg_seq() + 1;
- r_win_base = tsd.get_seg_seq() + 1;
- reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+ rcv_nxt = tsd.get_seq() + 1;
+ r_win_base = tsd.get_seq() + 1;
+ reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
cache_mac_address(tsd, FROM_CLIENT);
tcp_state = TcpStreamTracker::TCP_SYN_RECV;
if (tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE))
tsd.get_flow()->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
- iss = tsd.get_seg_seq();
- irs = tsd.get_seg_ack() - 1;
- snd_una = tsd.get_seg_seq();
+ iss = tsd.get_seq();
+ irs = tsd.get_ack() - 1;
+ snd_una = tsd.get_seq();
snd_nxt = tsd.get_end_seq();
- snd_wnd = tsd.get_seg_wnd();
+ snd_wnd = tsd.get_wnd();
- r_win_base = tsd.get_seg_ack();
- rcv_nxt = tsd.get_seg_ack();
- reassembler.set_seglist_base_seq(tsd.get_seg_ack() );
+ r_win_base = tsd.get_ack();
+ rcv_nxt = tsd.get_ack();
+ reassembler.set_seglist_base_seq(tsd.get_ack() );
- ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ ts_last_packet = tsd.get_packet_timestamp();
tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
- ts_last = tsd.get_ts();
+ ts_last = tsd.get_timestamp();
if ( ts_last == 0 )
tf_flags |= TF_TSTAMP_ZERO;
tf_flags |= tsd.init_mss(&mss);
void TcpStreamTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
{
- iss = tsd.get_seg_ack() - 1;
- irs = tsd.get_seg_seq();
- snd_una = tsd.get_seg_ack();
+ iss = tsd.get_ack() - 1;
+ irs = tsd.get_seq();
+ snd_una = tsd.get_ack();
snd_nxt = snd_una;
- rcv_nxt = tsd.get_seg_seq() + 1;
- r_win_base = tsd.get_seg_seq() + 1;
- reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+ rcv_nxt = tsd.get_seq() + 1;
+ r_win_base = tsd.get_seq() + 1;
+ reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
cache_mac_address(tsd, FROM_SERVER);
tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
- iss = tsd.get_seg_seq();
- snd_una = tsd.get_seg_seq();
+ iss = tsd.get_seq();
+ snd_una = tsd.get_seq();
snd_nxt = snd_una;
- snd_wnd = tsd.get_seg_wnd();
+ snd_wnd = tsd.get_wnd();
- r_win_base = tsd.get_seg_ack();
- rcv_nxt = tsd.get_seg_ack();
+ r_win_base = tsd.get_ack();
+ rcv_nxt = tsd.get_ack();
- ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ ts_last_packet = tsd.get_packet_timestamp();
tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
- ts_last = tsd.get_ts();
+ ts_last = tsd.get_timestamp();
if (ts_last == 0)
tf_flags |= TF_TSTAMP_ZERO;
tf_flags |= tsd.init_mss(&mss);
void TcpStreamTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
{
- iss = tsd.get_seg_ack() - 1;
- irs = tsd.get_seg_seq();
- snd_una = tsd.get_seg_ack();
+ iss = tsd.get_ack() - 1;
+ irs = tsd.get_seq();
+ snd_una = tsd.get_ack();
snd_nxt = snd_una;
- rcv_nxt = tsd.get_seg_seq();
- r_win_base = tsd.get_seg_seq();
- reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+ rcv_nxt = tsd.get_seq();
+ r_win_base = tsd.get_seq();
+ reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
cache_mac_address(tsd, FROM_CLIENT);
tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
else
flow->set_session_flags(SSNFLAG_SEEN_SERVER);
- iss = tsd.get_seg_seq();
- irs = tsd.get_seg_ack();
- snd_una = tsd.get_seg_seq();
- snd_nxt = snd_una + tsd.get_seg_len();
- snd_wnd = tsd.get_seg_wnd();
+ iss = tsd.get_seq();
+ irs = tsd.get_ack();
+ snd_una = tsd.get_seq();
+ snd_nxt = snd_una + tsd.get_len();
+ snd_wnd = tsd.get_wnd();
- r_win_base = tsd.get_seg_ack();
- rcv_nxt = tsd.get_seg_ack();
- reassembler.set_seglist_base_seq(tsd.get_seg_ack());
+ r_win_base = tsd.get_ack();
+ rcv_nxt = tsd.get_ack();
+ reassembler.set_seglist_base_seq(tsd.get_ack());
- ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ ts_last_packet = tsd.get_packet_timestamp();
tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
- ts_last = tsd.get_ts();
+ ts_last = tsd.get_timestamp();
if (ts_last == 0)
tf_flags |= TF_TSTAMP_ZERO;
tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
void TcpStreamTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
{
- iss = tsd.get_seg_ack();
- irs = tsd.get_seg_seq();
- snd_una = tsd.get_seg_ack();
+ iss = tsd.get_ack();
+ irs = tsd.get_seq();
+ snd_una = tsd.get_ack();
snd_nxt = snd_una;
snd_wnd = 0; /* reset later */
- rcv_nxt = tsd.get_seg_seq();
- r_win_base = tsd.get_seg_seq();
- reassembler.set_seglist_base_seq(tsd.get_seg_seq());
+ rcv_nxt = tsd.get_seq();
+ r_win_base = tsd.get_seq();
+ reassembler.set_seglist_base_seq(tsd.get_seq());
cache_mac_address(tsd, tsd.get_direction() );
tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
void TcpStreamTracker::finish_server_init(TcpSegmentDescriptor& tsd)
{
- iss = tsd.get_seg_seq();
- snd_una = tsd.get_seg_seq();
+ iss = tsd.get_seq();
+ snd_una = tsd.get_seq();
snd_nxt = tsd.get_end_seq();
- snd_wnd = tsd.get_seg_wnd();
+ snd_wnd = tsd.get_wnd();
// FIXIT-M move this to fin handler for syn_recv state ..
//if ( tcph->is_fin() )
// server->set_snd_nxt(server->get_snd_nxt() - 1);
tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
- ts_last = tsd.get_ts();
+ ts_last = tsd.get_timestamp();
if ( ts_last != 0 )
- ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ ts_last_packet = tsd.get_packet_timestamp();
else
tf_flags |= TF_TSTAMP_ZERO;
if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
{
- reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+ reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
r_win_base = tsd.get_end_seq();
}
else
{
- reassembler.set_seglist_base_seq(tsd.get_seg_seq() );
- r_win_base = tsd.get_seg_seq();
+ reassembler.set_seglist_base_seq(tsd.get_seq() );
+ r_win_base = tsd.get_seq();
}
}
void TcpStreamTracker::update_tracker_ack_recv(TcpSegmentDescriptor& tsd)
{
- if ( SEQ_GT(tsd.get_seg_ack(), snd_una) )
+ if ( SEQ_GT(tsd.get_ack(), snd_una) )
{
- snd_una = tsd.get_seg_ack();
+ snd_una = tsd.get_ack();
if ( snd_nxt < snd_una )
snd_nxt = snd_una;
}
if ( SEQ_GT(tsd.get_end_seq(), snd_nxt) )
snd_nxt = tsd.get_end_seq();
- if ( SEQ_GT(tsd.get_seg_ack(), r_win_base) )
- r_win_base = tsd.get_seg_ack();
+ if ( SEQ_GT(tsd.get_ack(), r_win_base) )
+ r_win_base = tsd.get_ack();
if ( ( fin_seq_status == TcpStreamTracker::FIN_WITH_SEQ_SEEN )
&& SEQ_EQ(r_win_base, fin_final_seq) )
fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_ACKED;
}
- snd_wnd = tsd.get_seg_wnd();
+ snd_wnd = tsd.get_wnd();
reassembler.flush_on_ack_policy(tsd.get_pkt());
}
{
bool good_ack = true;
- if ( is_ack_valid(tsd.get_seg_ack()) )
+ if ( is_ack_valid(tsd.get_ack()) )
{
Flow* flow = tsd.get_flow();
- irs = tsd.get_seg_seq();
+ irs = tsd.get_seq();
finish_client_init(tsd);
update_tracker_ack_recv(tsd);
flow->set_session_flags(SSNFLAG_ESTABLISHED);
&& (flush_policy != STREAM_FLPOLICY_ON_DATA)
&& normalizer.is_tcp_ips_enabled())
{
- tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
+ tsd.set_packet_flags(PKT_PDU_TAIL);
}
reassembler.flush_on_data_policy(tsd.get_pkt());
{
fin_final_seq = tsd.get_end_seq();
fin_seq_set = true;
- if( tsd.get_seg_len() == 0 )
+ if( tsd.get_len() == 0 )
fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_SEEN;
}
else
left_seq = r_win_base;
- if ( tsd.get_seg_len() )
+ if ( tsd.get_len() )
right_ok = SEQ_GT(tsd.get_end_seq(), left_seq);
else
right_ok = SEQ_GEQ(tsd.get_end_seq(), left_seq);
{
uint32_t win = normalizer.get_stream_window(tsd);
- if ( SEQ_LEQ(tsd.get_seg_seq(), r_win_base + win) )
+ if ( SEQ_LEQ(tsd.get_seq(), r_win_base + win) )
{
return true;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_stream_tracker.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_stream_tracker.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jun 24, 2015
#ifndef TCP_STREAM_TRACKER_H
// ack number must ack syn
bool is_rst_valid_in_syn_sent(const TcpSegmentDescriptor& tsd) const
- { return tsd.get_seg_ack() == snd_una; }
+ { return tsd.get_ack() == snd_una; }
uint32_t get_ts_last() const
{ return ts_last; }